Java Jmeter协议测试。无法读取Protobuf消息

Java Jmeter协议测试。无法读取Protobuf消息,java,jmeter,protocol-buffers,Java,Jmeter,Protocol Buffers,我正在通过protobuf协议和HTTP请求采样器测试一个项目。目标appserver也是用Java编写的。 响应中存在错误问题: 无法读取Protobuf消息:协议消息包含 无效标记(零)。;嵌套异常为 com.google.protobuf.InvalidProtocolBufferException:协议消息 包含无效的标记(零)” 情况是,它不是在100%的请求中发生的。当我使用HttpClient4时,大约有30-40%的请求失败。在我将其更改为HttpClient3.1之后,错误率降

我正在通过protobuf协议和HTTP请求采样器测试一个项目。目标appserver也是用Java编写的。 响应中存在错误问题:

无法读取Protobuf消息:协议消息包含 无效标记(零)。;嵌套异常为 com.google.protobuf.InvalidProtocolBufferException:协议消息 包含无效的标记(零)”

情况是,它不是在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));
此外,我还尝试使用不同的编码,如新字符串(数据,“UTF-8”)anso on

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


似乎有些奇怪的符号不应该发送,但在保存字节数组以包含字符串后,约有10%的请求包含这些符号。

在高负载情况下,Beanshell解释器可能会导致意外行为,因为它有一些性能问题。尝试切换到并作为一种语言使用。Groovy脚本引擎实现了这个接口,所以只要您遵循一些简单的规则,就可以获得最佳性能,并且您的问题就可以解决


有关groovy引擎安装说明、脚本编写最佳实践以及Beanshell与groovy基准测试的比较,请参阅文章。

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

  • 将二进制数据写入文件,而不是保存为字符串,然后在HTTP采样器的body from file部分中将文件名用作变量

  • 使用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端点进行测试,请告诉我它是如何为您工作的。

    因此,您正在将二进制流转换为字符串以另存为变量,这可能会因编码不同而出现问题。它还依赖于系统,行为可以改变。此外,当您使用
    ${data}
    时,您正在发送一个字符串,对于某些二进制数据,该字符串正在插入
    。首先想到的解决方法是将二进制流写入文件,并将文件路径用作bodydata中的变量。但是,这将导致大量的文件I/O用于高容量。隐马尔可夫模型。。这有点像一个思考者。或者,您可以组装自己的HTTP请求,并从beanshell采样器发送它,而不是使用HTTP采样器。不知道来自jmeter插件的
    HTTP原始请求是否有用。尝试过JSR223预处理器后,结果完全相同:(@v0devil)您的问题是,您正在将二进制数据转换为字符串,并在转换过程中丢失一些不可打印的字符。Beanshell稳定性不是问题。@RaGe yep似乎是。我没有收到您关于使用HTTP Raw请求的评论-这将是相同的方式,没有?我没有使用Raw请求采样器,但我没有使用Raw请求采样器使用它可以更好地控制您可以将哪些内容放入POST Body中也许base64编码数据会有所帮助?(FWIW,这个问题肯定是因为试图将非文本二进制数据推入
    字符串中
    s——这是行不通的。)@RaGe你能提供一些Beanshell中HTTPClient的例子吗?用一些代码更新。我在一个常规http端点上测试了它,但没有在protobuf端点上测试,手头没有。