Netty优化
扩展序列化算法
- 序列化,反序列化主要用在消息正文的转换上。
- 为了可扩展性,后续代码可以支持更多的序列化算法,需要进行优化。
- 通过读取配置的方式动态获取需要使用的序列化算法。
- 步骤如下
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.6</version>
</dependency>
- 定义一个抽象的序列化接口,分别包含有序列化和反序列化方法。并且实现接口(这里采用枚举的方式)
public interface Serializer {
<T> byte[] serialize(T object);
<T> T deserialize(Class<T> clazz,byte[] bytes);
enum Algorithm implements Serializer{
JDK{
@Override
public <T> byte[] serialize(T object) {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(object);
return bos.toByteArray();
} catch (IOException e) {
throw new RuntimeException("序列化失败",e);
}
}
@Override
public <T> T deserialize(Class<T> clazz, byte[] bytes) {
try {
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
return (T) ois.readObject();
} catch (IOException | ClassNotFoundException e) {
throw new RuntimeException("反序列化失败",e);
}
}
},
GSON{
@Override
public <T> byte[] serialize(T object) {
return new Gson().toJson(object).getBytes(StandardCharsets.UTF_8);
}
@Override
public <T> T deserialize(Class<T> clazz, byte[] bytes) {
return new Gson().fromJson(new String(bytes,StandardCharsets.UTF_8),clazz);
}
}
}
}
# 配置序列化算法
serializer:
type: Gson
@Component
public class PropertyConfig {
private static String value = "JDK";
@Value("${serializer.type}")
public void setValue(String value) {
PropertyConfig.value = value;
}
public static Serializer.Algorithm getSerialize(){
System.out.println("value:"+value);
return Serializer.Algorithm.valueOf(value);
}
}
- 修改编解码代码(编码时根据配置文件动态决定选择哪一种序列化算法,解码时根据协议传过来的序列化类型去解码)枚举类型在定义时自带顺序,可以获取下标ordinal()方法作为序列化的类型传参。
out.writeByte(PropertyConfig.getSerialize().ordinal());
byte[] bytes = PropertyConfig.getSerialize().serialize(msg);
out.writeInt(bytes.length);
out.writeBytes(bytes);
byte serializeMethod = in.readByte();
byte messageType = in.readByte();
Serializer.Algorithm algorithm = PropertyConfig.getSerialize();
Class<?> clazz = MessageConstant.getMessageClass(messageType);
Object message = algorithm.values()[serializeMethod].deserialize(clazz, bytes);
out.add(message);
参数调优
- 客户端可以通过Bootstrap的option()来配置参数。
- 服务端的ServerBootstrap中有两个方法,option()用来配置ServerSocketChannel,childOption()用来配置SocketChannel。
- 配置参数都封装在了CannelOption.中。
connect_timeout_millis
- 用于在客户端建立连接时,如果在指定毫秒时无法连接,会抛出timeout异常。
- netty中的promise用于线程之间的通信。
SO_BACKLOG
- 复习三次握手:
- 第一次握手:client发送syn到server,状态改变为syn_send,server收到,状态改变为syn_revd,并将该请求放到sync queue队列。
- 第二次握手:server回复syn+ack给client,client收到,状态改变为established,并发送ack给server。
- 第三次握手:server收到ack,将状态改成established,将该请求从sync queue放入accept queue队列中。
- 如果全连接队列满了,server将发送一个拒绝连接的错误消息到client。