使用Jersey Client 1.9报SocketException: No buffer space available如何解决
问题原因分析
- Jersey 1.x版本的
Client属于重量级对象,默认每个实例都会维护独立的HTTP连接池。你每次请求都新建Client实例,旧实例没有被正确销毁回收时,底层关联的Socket连接不会主动释放,累计到一定量级就会占满系统Socket缓冲区,达到最大连接数上限,触发对应异常。 - 你的现有代码没有显式关闭
ClientResponse对象,即使后续Client被销毁,未关闭的响应也会导致底层Socket连接泄漏,持续占用系统资源。 - 默认的Client连接池参数没有做适配调整,高频率调用场景下很容易快速占满连接资源。
解决方案
1. 全局复用Client实例
Client本身是线程安全的,全局仅需要初始化1次即可,不要每次请求都新建实例,可通过单例模式维护全局实例:
// 全局仅初始化一次,重复复用 private static final Client GLOBAL_CLIENT = Client.create();
每次请求直接用该全局实例创建WebResource即可。
2. 显式关闭ClientResponse避免连接泄漏
每次请求结束后,无论业务处理成功还是失败,都需要在finally块中手动关闭响应对象:
ClientResponse response = null; try { WebResource webResource = GLOBAL_CLIENT.resource(url); response = webResource .queryParam(PARAM1, param1) .queryParam(PARAM2, param2) .type(MediaType.APPLICATION_JSON) .get(ClientResponse.class); // 处理业务逻辑 } finally { if (response != null) { response.close(); } }
3. 自定义连接池配置适配业务量
创建Client时可根据实际调用频率调整连接池、超时相关参数,避免资源被占满:
ClientConfig clientConfig = new DefaultClientConfig(); // 设置连接池最大总连接数,可根据业务量调整 clientConfig.getProperties().put(ClientConfig.PROPERTY_THREADPOOL_SIZE, 20); // 设置连接超时时间,单位毫秒 clientConfig.getProperties().put(ClientConfig.PROPERTY_CONNECT_TIMEOUT, 5000); // 设置读取响应超时时间,单位毫秒 clientConfig.getProperties().put(ClientConfig.PROPERTY_READ_TIMEOUT, 10000); // 用自定义配置初始化全局Client private static final Client GLOBAL_CLIENT = Client.create(clientConfig);
4. 优雅停机主动释放资源
如果你的服务有优雅停机逻辑,停机时可调用GLOBAL_CLIENT.destroy()方法主动释放所有连接占用的系统资源。
内容的提问来源于stack exchange,提问作者hamwac5
相关产品推荐
相关产品推荐

