Caviar:一个基于Netty的通信框架

自己基于Netty实现了一个通信框架,给它起名叫Caviar(https://github.com/mailzyw/caviar)。下面给出框架介绍。

一、功能设计

提供了两个通信相关的接口Client和Server

1、网络客户端Client

Client接口提供建连、登录、登出、发送请求消息(同步)、发送请求消息(异步回调)、接收服务端请求消息等功能。

public interface Client {

    /**
     * 连接服务端
     * @param host host
     * @param port port
     */
    void connect(String host, int port) throws CaviarNetworkException;

    /**
     * 关闭客户端
     * @throws IOException
     */
    void close() throws IOException;

    /**
     * 重连服务端
     */
    void reconnect();

    /**
     * 设置客户端运行状态
     * @param running running
     */
    void setRunningState(boolean running);

    /**
     * 客户端登录
     * @param loginMsg loginMsg
     * @return 登录响应
     */
    byte[] login(byte[] loginMsg) throws CaviarNetworkException;

    /**
     * 客户端登出
     * @param logoutMsg logoutMsg
     * @return
     */
    byte[] logout(byte[] logoutMsg) throws CaviarNetworkException;

    /**
     * 发送消息——同步
     * @param msg msg
     * @throws CaviarNetworkException
     */
    byte[] sendMsgSync(byte[] msg) throws CaviarNetworkException;

    /**
     * 发送消息——异步
     * @param msg msg
     * @throws CaviarNetworkException
     */
    void sendMsgAsync(byte[] msg, CaviarMsgCallback caviarMsgCallback);
}

CaviarServer为Client接口的实现类,提供CaviarServer(long timeout, CaviarServerBizListener caviarBizListener)构造方法。

2、网络服务端Server

Server接口提供bind方法和close方法。bind方法用于绑定对应服务端口并开始监听客户端连接请求,close方法为服务端关闭操作。

public interface Server {

    /**
     * 启动操作
     * @param port 监听端口
     */
    void bind(int port) throws CaviarNetworkException;

    /**
     * 关闭操作
     * @throws IOException
     */
    void close() throws IOException;
}

CaviarServer为Server接口的实现类,提供CaviarServer(long timeout, CaviarServerBizListener caviarBizListener)构造方法。

3、请求消息处理器CaviarServerBizListener/CaviarServerBizListener

服务端和客户端的请求消息处理器,定义了处理请求消息的方法。
使用者通过实现这两个接口完成对消息处理的具体业务逻辑。

public interface CaviarServerBizListener {

    /**
     * 处理客户端登录请求
     */
    void processClientLogin(RequestContext requestContext, SessionContext sessionContext, byte[] msg);

    /**
     * 处理客户端登出请求
     */
    void processClientLogout(RequestContext requestContext, SessionContext sessionContext, byte[] msg);

    /**
     * 处理客户端请求消息
     */
    void processClientMsg(RequestContext requestContext, SessionContext sessionContext, byte[] msg);

}
public interface CaviarClientBizListener {

    /**
     * 处理服务端请求消息
     */
    void processServerMsg(RequestContext requestContext, SessionContext sessionContext, byte[] msg);

}

4、连接上下文SessionContext

用于标识一个网络连接(客户端与服务端),内部维护了网络连接信息Channel,并提供了向当前连接发送请求/响应消息等接口功能。使用者使用该接口完成请求消息的发送和响应。
NettySessionContext为SessionContext的具体实现。

5、请求上下文RequestContext

用于标识一次请求,内部维护了请求唯一标识、请求消息、响应消息、响应异步回调接收器等信息。在进行请求应答时会用到,使用者一般不需要直接操作。

二、协议设计

1、消息协议

    Long        address         消息发送端IP转换为的Long
    Integer     crcCode         版本号
    Integer     msgType         消息类型
    Integer     codeType        消息体序列化方式(0:json,1:xml)
    Integer     length          消息体长度
    byte[]      body            消息体
  • 消息体定义为byte[]数组,留给使用者充分的实现自由。
  • 使用者可以定义自己个性化实现方式的消息体,最后只需要将其序列化成byte[]进行网络传输即可
  • codec包中提供了默认的序列化Gson实现类GsonSerialization,使用者可以基于此实现业务消息体的序列化和反序列化,当然也可以使用其他的序列化方式。

2、消息类型

    |-请求消息
        |-CLIENT_LOGIN_REQ(1001),                 //客户端登录
        |-CLIENT_LOGOUT_REQ(1002),                //客户端登出
        |-CLIENT_MSG_SEND_REQ(1003),              //客户端请求——同步
        |-CLIENT_MSG_SEND_ASYNC_REQ(1004),        //客户端请求——异步回调
        |-SERVER_MSG_SEND_REQ(1013),              //服务端请求——同步
        |-SERVER_MSG_SEND_ASYNC_REQ(1014),        //服务端请求——异步回调
    |-响应消息
        |-CLIENT_LOGIN_RESP(2001),                //客户端登录
        |-CLIENT_LOGOUT_RESP(2002),               //客户端登出
        |-CLIENT_MSG_SEND_RESP(2003),             //客户端请求
    |-心跳消息
        |-PING(9001),                             //客户端Ping
        |-PONG(9002),                             //服务端Pong

三、可靠性设计

1、客户端连接/请求超时功能:

  • Client接口提供出来的connect/sendMsgSync/sendMsgAsync方法均支持超时时间的设置,超时时间为CaviarServer(long timeout, CaviarServerBizListener caviarBizListener)构造方法的timeout字段。
  • 当客户端连接/请求超时时,将抛出CaviarNetworkException进行提示。

2、客户端断连重连:

  • 客户端Client监测到网络断连事件后,会自动进入重连逻辑,每2秒进行一次重连操作,直到重连成功。

3、心跳检测:

  • 当没有业务消息交互时,客户端与服务端之间会自动以5秒/次的频率进行心跳请求响应交互。
  • 当客户端与服务端网络存在故障时,会导致心跳包交互超时,服务端会自动断连对应的客户端连接。

4、客户端重复登录保护:

  • 该功能与业务紧密相关,开放给使用者按需自行实现。

5、消息缓存重发

  • 该功能与业务紧密相关,开放给使用者按需自行实现。
  • Caviar框架提供了完善的请求/响应消息收发接口,使用者可以基于这些接口实现业务层的消息接收确认及缓存重发。

四、性能设计

1、IO模型

Caviar框架底层基于Netty实现,继承了Netty提供的非阻塞IO模型

  • 底层基于Selector的多路复用IO模型,实现非阻塞IO通信,使网络连接与IO线程解耦,具有高性能和高扩展性。
  • 进行IO读写时,Netty采用DirectByteBuffer存储数据,同时引入了Buffer池,以此减少内存数据拷贝,提高IO性能。

2、线程模型

Caviar框架底层基于Netty实现,基础了Netty的Reactor线程模型

  • 专门的NIO线程Acceptor负责监听服务端,接收客户端的TCP连接请求。
  • IO读写事件由专门的NIO线程池负责。
  • 无锁化的串行设计,一个NIO线程可以同时处理多条通信链路,但一条通信链路内的IO事件只由一个NIO线程处理,从而避免多线程切换的锁问题。
  • 将IO事件解析为业务消息后,交由Caviar的业务分发器处理,业务处理逻辑在专门的业务线程池中进行执行,不影响NIO线程。

3、序列化框架

  • Caviar消息协议直接基于byte数组进行序列化与反序列化,简单高效。
  • 业务消息体直接定义为byte数组,将编解码操作开放给使用者自行实现。

4、同步/异步请求线程模型

同步请求线程模型
异步请求线程模型

五、使用示例

caviar框架源码中的demo包中提供了一个简单的使用示例。

  • CaviarServerBootstrap为服务端的启动器,它完成了服务端构造及bind操作
  • CaviarClientBootstrap为客户端的启动器,它完成了客户端的构造及连接、登录、发送请求等操作
  • CaviarClientBizListenerDefaultImp和CaviarServerBizListenerDefaultImp为请求消息处理器的业务实现类,demo里面只是做了简单的操作。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,524评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,869评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,813评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,210评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,085评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,117评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,533评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,219评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,487评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,582评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,362评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,218评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,589评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,899评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,176评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,503评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,707评论 2 335

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,497评论 18 139
  • 1、Netty基础入门 Netty是由JBOSS提供的一个java开源框架。Netty提供异步的、事件驱动的网络应...
    我是嘻哈大哥阅读 4,679评论 0 31
  • 前奏 https://tech.meituan.com/2016/11/04/nio.html 综述 netty通...
    jiangmo阅读 5,829评论 0 13
  • 文本只适合给web开发入门人员阅读!专业人士请勿浪费时间! 只要了解一点web前端开发知识的人都知道:HTML、C...
    小松_路飞阅读 630评论 1 4
  • 美剧爱好者一枚,看了很多很长很没营养的剧。《绯闻女孩》《真爱如血》…而《行尸》是到现在一直还在追的故事,从刚开...
    甚少阅读 266评论 4 0