Jmeter protobuf 测试。无法读取 Protobuf 消息

Jmeter protobuf testing. Could not read Protobuf message

我正在通过 protobuf 协议和使用 HTTP Request Sampler 测试一个项目。目标appserver也写在Java上。 响应错误存在问题:

"Could not read Protobuf message: Protocol message contained an invalid tag (zero).; nested exception is com.google.protobuf.InvalidProtocolBufferException: Protocol message contained an invalid tag (zero)"

情况是它不是在 100% 的请求中发生的。当我使用 HttpClient4 时,大约有 30-40% 的请求失败。在我将它更改为 HttpClient3.1 之后,错误率下降到 ~10% 这也不是一个好交易。

为了发送 protobuf 消息,我在 HttpSampler 的 Bodydata 选项卡中使用了变量 ${data}。在 BeanShell 预处理器中,我执行以下操作:

(import and non-necessary stuff were ommited)
MapViewport mv = MapRequest.MapViewport.newBuilder().setMaxX(mc.getX()+15).setMaxY(mc.getY()+15).setMinX(mc.getX()-15).setMinY(mc.getY()-15).build();

byte[] data = mv.toByteArray();
vars.put("data", new String(data));

我还尝试使用不同的编码,例如 new String(data,"UTF-8") 等。

如果要在“请求”选项卡上查看“查看结果树”,我可以说所有失败的消息都包含“?”符号:

似乎不​​应该发送一些奇怪的符号,但是将字节数组保存到 String 后约 10% 的请求包含它们。

在高负载下,Beanshell 解释器可能会导致意外行为,因为它有一些性能问题。尝试切换到 JSR223 PreProcessor and use groovy as a language. Groovy scripting engine implements Compilable 界面,因此如果您遵循一些简单的规则,您可以获得最佳性能并且您的问题可以消失。

有关 groovy 引擎安装说明、脚本最佳实践和 Beanshell 与 Groovy 基准测试的对比,请参阅 Beanshell vs JSR223 vs Java JMeter Scripting: The Performance-Off You've Been Waiting For! 文章。

我相当确信您的问题是您在从二进制流转换为字符串然后再转换回来时丢失了一些不可打印的字符。我正在考虑两种可能的解决方法:

  1. 将二进制数据写入文件而不是保存到字符串,然后使用文件名作为 HTTP 采样器中的变量,在文件部分的主体中

  2. 使用 beanshell 采样器,构建您自己的 HTTPClient 对象和 POST 请求,在正文中使用二进制数据并自行触发它,而不是使用 HTTP 采样器

我不喜欢第一个选项,因为所有附加文件 I/O。我不喜欢第二个选项,因为测量响应时间现在将包括您在 beanshell 中执行的所有请求程序集 - 所以我猜您必须选择对您影响较小的那个。

如果您想让我为这两种情况编写一些代码示例,请告诉我。

编辑:对于使用 HttpClient 4 的 beanshell HTTP 调用:

import org.apache.http.HttpEntity;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.impl.client.DefaultHttpClient;

byte[] data = null;
//...assign protobuf binary buffer to data...

HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost("http://127.0.0.1");
HttpEntity entity = new ByteArrayEntity(data);
post.setEntity(entity);
post.setHeader(HttpHeaders.CONTENT_TYPE, "application/octet-stream");
HttpResponse response=null;
try {
    response = client.execute(post);
} catch (ClientProtocolException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

ResponseCode = response.getStatusLine().getStatusCode().toString();
//if some assert is true then
Issuccess = true;
ResponseMessage="Some Response Message";

这还没有针对 protobuf 端点进行测试,让我知道它是如何为您服务的。