3

我有一个本土协议,它使用 HttpURLConnection(来自 Java 1.6)和 Jetty(6.1.26)来发布一个 xml 块作为请求并接收一个 xml 块作为响应。xml 的数量约为。5KB。

在世界不同地区的 Linux EC2 实例上同时运行发送方和接收方时,我发现在大约 0.04% 的请求中,Jetty 处理程序将 xml 请求(帖子正文)视为空字符串。我已经检查并且客户端输出它一直在尝试发送正确的(> 0 长度)xml 请求字符串。

我还通过在我的本地(Win 8)机器上循环我的 JUnit 测试来重现这一点。

我认为错误一定是这样的:

  • 滥用缓冲区
  • 一个 HttpURLConnection 错误
  • 网络错误
  • 一个码头错误
  • 我在代码中做的一个随机的头部拍打愚蠢的事情

相关代码如下:

客户

        connection = (HttpURLConnection) (new URL (url)).openConnection();
        connection.setReadTimeout(readTimeoutMS);
        connection.setConnectTimeout(connectTimeoutMS);
        connection.setRequestMethod("POST");
        connection.setAllowUserInteraction(false);
        connection.setDoOutput(true);

        // Send request
        byte[] postBytes = requestXML.getBytes("UTF-8");
        connection.setRequestProperty("Content-length", "" + postBytes.length);
        OutputStream os = connection.getOutputStream();
        os.write(postBytes);
        os.flush();
        os.close();

        // Read response
        InputStream is = connection.getInputStream();
        StringWriter writer = new StringWriter();
        IOUtils.copy(is, writer, "UTF-8");
        is.close();
        connection.disconnect();
        return writer.toString();

服务器(码头处理程序)

    public void handle(java.lang.String target, javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, int dispatch) {
        InputStream is = request.getInputStream();
        StringWriter writer = new StringWriter();
        IOUtils.copy(is, writer, "UTF-8");
        is.close(); 
        String requestXML = writer.toString();
        // requestXML is 0 length string about 0.04% of time

谁能想到为什么我会随机将请求作为空字符串获取?

谢谢!

编辑

我引入了更多跟踪,当错误发生时 getContentLength() 返回 -1,但客户端输出仍然显示它正在发送正确数量的字节。

4

2 回答 2

2

我想不出你为什么得到一个空字符串。代码看起来正确。如果您更新代码以检查空字符串,如果发现报告请求的内容长度和传输编码,这将有助于识别罪魁祸首。网络数据的wireshark跟踪也很好。

但坏消息是,jetty-6 真的是生命的尽头,我们不太可能更新它。如果您今天正在编写代码,那么您真的应该使用 jetty-7 或 8。如果您勇敢的话,甚至可以使用 jetty-9 里程碑版本。如果您在 jetty-9 中发现此类错误,我会全力以赴,试图为您修复它!

于 2012-11-01T21:20:19.280 回答
1

确保您设置connection.setRequestProperty("Content-Type", "application/xml"); 了没有某些 Content-type 的情况下可能会丢弃 POST 数据。当我在本地复制您的问题(针对 Grails 嵌入式 Tomcat 实例)并提供此解决方案时就是这种情况。

于 2012-11-07T17:23:04.477 回答