Java 网络编程最佳实践(转载)

时间:2024-01-11 15:52:02

http://yihongwei.com/2015/09/remoting-practice/

Java 网络编程最佳实践

Sep 10, 2015 | [JavaNetwork]

1. 通信层

  • 直接使用最成熟的网络框架,如 Netty
  • 单连接 & 连接复用 & 长连接
    • 建议提前设计心跳机制
    • 集群较小,长连接无需开启心跳
    • 如果网络情况比较复杂,建议开启心跳。如有防火墙,会将连接清掉且不会向客户端发送 RST 信令,导致长连接变成一个脏连接

2. 线程模型

如果采用了 Netty 这样的框架,线程模型基本已经决定了,但是 Netty 只需负责 IO 处理,需要提供额外的业务线程池负责处理业务请求。

  • 序列化过程在业务线程中处理
  • 请求/响应包多个批量从 IO 线程交给业务线程处理
  • 服务端线程池需要有保护策略
    • 框架层面的 RejectExcetpion
    • 业务层面的限流策略
  • 需要定时打印线程池大小,方便性能分析

3. 序列化

  • 全站都是 Java 系

为了以后能让其它语言更好的交互,协议设计越扁平越好,切忌将整个协议类对象序列化,仅整个序列化方法参数对象列表及返回值对象。

  • 全站各种语言百花齐放

可以考虑直接使用 Protobuf 或者 msgpack 这样的跨语言的序列化协议,但我个人没使用经验。

4. 容灾

  • 必须要有超时时间,分布式环境下无超时机制对整体环境影响非常大
  • 需要有连接隔离机制(根据请求量、错误率等)

5. 故障定位

  • 客户端发送、服务端接收均需要打印日志,日志必须要有的几个字段:
    • 时间戳
    • 唯一ID: 由于客户端和服务端的请求量较大,所以需要有唯一 ID 能够将客户端日志和服务端请求串起来
    • IP 信息
    • 如下:
      • client:time,unique-id,server-ip
      • server:time,unique-id,client-ip
  • 提供较好的方式打印网络层日志
    • 经常会发生客户端有请求日志,但是服务端没有接收日志的情况
    • 这个时候无法判断是客户端出错还是服务端出错,可以提供 debug 日志打印网络层的请求日志