netty服务端设计,适用于app、游戏等场景

netty服务端设计,适用于app、游戏等场景_第1张图片
components.png

一、系统目标

使用netty搭建tcp服务器,支持长连接,短连接模式。

使用protobuf作为主要的数据编码手段

将数据传输隐藏在框架内,使得业务开发人员可直接关注业务实现,无需关注通信,甚至无需关心多线程问题。

可扩展的架构,方便接入其他中间件。

将编码任务简单化。

二、系统分层

netty服务端设计,适用于app、游戏等场景_第2张图片
Class Diagram.png
netty服务端设计,适用于app、游戏等场景_第3张图片

2.1 通信层

绝大部分的功能,netty已经支持了。

2.1.1 通信协议

服务器在收到数据之后,需要进行如下的过滤判断:
a、数据是否合法
b、数据版本是否支持
c、如何解析客户端数据,客户端数据类型是什么
d、客户端期望服务端提供什么服务

数据包具体协议设计如下:

长度(4字节)| 时间戳(4字节) | 版本 (2字节) | 服务id (2字节)| 数据(不定长)| 校验码(2字节)

2.1.2 Mapping

由上述协议传输的数据中的服务id,具体对应到哪个类的哪个方法执行
上传数据如何解析由方法参数决定
下发数据如何解析由方法返回值决定
如返回值为void,且方法中带异步回调参数,则一般为异步执行
如返回值不为void,则为同步执行。

服务id计算,(65536上限,一般应用足够了):
所有Controller的method列表,使用字典顺序排序的序号,并持久化序号和method的对应关系,新版本新的Controller的排序基数使用上个版本排序最大值。

2.1.3 通信用POJO

在网络层为protobuf生成,.proto文件,可以根据method方法参数生成。
具体规则为:
int Calc.add(int a,int b);
则生成

syntax = "proto3";
package com.project.net.pojo;
message CalcAdd{
  int32 a = 1;
  int32 b=2;
}

void Articals.add(Artical a);

syntax = "proto3";
package com.project.net.pojo;
message ArticalsAdd{
  //Artical字段
}

不支持Map或List作为参数

返回值规则:
返回值为简单型,则可使用通用的.proto文件

message IntResult{
  int32 result =1 ;
}
message StringResult{
  string result = 1;
}

客户端解析规则:
在程序内内置服务id和.proto的对应关系,并可在线更新或整体更新。

2.2 线程管理

可配置使用额外的线程管理,或是直接使用netty自己的工作线程。

额外的线程管理,设计如下:

2.2.1 逻辑线程

有必要将逻辑线程和工作线程分开
a、逻辑线程为单线程,整个服务器单元只有一个逻辑线程
b、原则上,逻辑线程只处理逻辑,不做重度任务处理
c、如涉及长时间任务,将任务投递到工作线程上。
优点:无线程安全问题,可放心大胆使用hashmap、hashset等数据结构。

2.2.2 任务线程

a、处理重任务,如数据库操作等
b、非线程安全,原则上不存放线程共享数据
c、框架应提供齐全的工具类以规避线程安全问题,保证在开发人员水平参差不齐的情况下仍然不影响业务逻辑的开发。
d、将缩小异常范围,以减少对整个系统的损害。
e、提供线程退出机制。

2.2.3 任务队列

上述任务线程的共享的队列。

2.2.4 异步回调机制

在工作线程中做完任务之后,可以将结果投递逻辑线程
也可以直接与客户端通信,并主动关闭连接。

2.3. Controller层

设计思路可以参考spring mvc。或直接整合spring、jfinal等框架(待研究)。

2.3.1 java class

Controller可设计单例模式

2.3.2 method

可支持aop技术

2.3.3 参数解析、结果解析

参见2.1.3 节

你可能感兴趣的