HTTP处理器间通过ObjectOutputStream传输对象失败排查
排查HTTP服务器间Java对象传输停滞的问题
看起来你遇到了主服务器转发Task对象到第二服务器时,第二服务器卡在读取对象环节的问题——第二服务器只打印Recieved object:就停滞,主服务器那边也卡在test.getResponseCode()。我帮你分析下可能的问题点和修复方案:
核心问题分析
从你的代码来看,主服务器发送对象到第二服务器的逻辑存在几个关键问题,导致第二服务器的ObjectInputStream.readObject()一直阻塞,等待完整的序列化数据:
具体修复步骤
1. 修正主服务器的HTTP请求配置
主服务器发送请求时缺少了关键的配置,并且流操作顺序有误:
- 必须设置请求方法为POST:默认的GET方法不支持请求体,你需要显式指定POST才能发送序列化对象
- 调整流操作顺序:你现在先调用了
stream.flush()再写对象,这会导致flush空流,后续写入的对象可能滞留在缓冲区,没有被及时发送 - 显式开启输入流:要读取第二服务器的响应,需要开启输入流(虽然默认是true,但显式设置更稳妥)
修复后的代码片段:
HttpURLConnection test = (HttpURLConnection) new URL(fogServ1URL).openConnection(); test.setRequestMethod("POST"); // 关键:设置POST请求 test.setDoOutput(true); test.setDoInput(true); // 开启输入流用于读取响应 // 可选但推荐:告诉服务器发送的是Java序列化对象 test.setRequestProperty("Content-Type", "application/x-java-serialized-object"); System.out.println("test__1"); ObjectOutputStream stream = new ObjectOutputStream(test.getOutputStream()); stream.writeObject(t); // 先写入对象 stream.flush(); // 确保数据写入底层HTTP流 stream.close(); System.out.println("test__3"); System.out.println("test__4"); int responseCode = test.getResponseCode(); System.out.println("test__5, Response code: " + responseCode); // 必须读取响应体,否则会导致连接资源泄漏 BufferedReader respReader = new BufferedReader(new InputStreamReader(test.getInputStream())); String respLine; StringBuilder respBuilder = new StringBuilder(); while ((respLine = respReader.readLine()) != null) { respBuilder.append(respLine); } respReader.close(); test.disconnect(); // 断开连接释放资源
2. 验证Task类的序列化正确性
确保你的Task类满足以下条件:
- 实现了
java.io.Serializable接口 - 主服务器和第二服务器的
Task类包名、类结构完全一致,如果显式定义了serialVersionUID,两边的值必须相同 - 所有成员变量都是可序列化的(你的int数组没问题,但如果有自定义类型成员,也要确保它们可序列化)
3. 调试数据传输完整性
如果修复后还是有问题,可以添加调试步骤确认数据是否完整发送:
- 在主服务器发送前,打印
Task的所有属性,确认对象是完整的 - 在第二服务器的处理器中,先检查输入流的可用字节数:
如果可用字节数为0,说明主服务器根本没发送数据,回到主服务器的代码排查;如果有字节数但读取卡住,可能是序列化数据不完整。InputStream rawIn = exchange.getRequestBody(); System.out.println("Received request body bytes available: " + rawIn.available()); ObjectInputStream ois = new ObjectInputStream(rawIn);
后续扩展多服务器的建议
针对你后续计划扩展多台服务器的需求,给你几个实用建议:
- 使用HTTP连接池:比如Apache HttpClient的
PoolingHttpClientConnectionManager,避免频繁创建和关闭HTTP连接,提升并发性能 - 基于请求头分发:在主服务器转发时,给请求添加自定义请求头(比如
X-Task-Type),标识Task类型,然后根据头值分发到不同的服务器 - 替换序列化方式:Java自带的序列化效率低且兼容性差,可以考虑用Protobuf、Kryo等更高效的序列化框架,提升传输速度和跨服务兼容性
内容的提问来源于stack exchange,提问作者shurrok
相关产品推荐
相关产品推荐

