• 一,Broker服务端入口(NettyServer端)

首先RocketMq网络通信采用的Netty通信。服务端主要集中在Broker中。我们先看一下Broker的启动类BrokerStartup

显然具体逻辑是在start方法里面,下面是实现:

 public void start() throws Exception {
if (this.messageStore != null) {
this.messageStore.start();
} if (this.remotingServer != null) {
this.remotingServer.start();
} if (this.fastRemotingServer != null) {
this.fastRemotingServer.start();
} if (this.fileWatchService != null) {
this.fileWatchService.start();
} if (this.brokerOuterAPI != null) {
this.brokerOuterAPI.start();
} if (this.pullRequestHoldService != null) {
this.pullRequestHoldService.start();
} if (this.clientHousekeepingService != null) {
this.clientHousekeepingService.start();
} if (this.filterServerManager != null) {
this.filterServerManager.start();
} if (!messageStoreConfig.isEnableDLegerCommitLog()) {
startProcessorByHa(messageStoreConfig.getBrokerRole());
handleSlaveSynchronize(messageStoreConfig.getBrokerRole());
} this.registerBrokerAll(true, false, true); this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() { @Override
public void run() {
try {
BrokerController.this.registerBrokerAll(true, false, brokerConfig.isForceRegister());
} catch (Throwable e) {
log.error("registerBrokerAll Exception", e);
}
}
}, 1000 * 10, Math.max(10000, Math.min(brokerConfig.getRegisterNameServerPeriod(), 60000)), TimeUnit.MILLISECONDS); if (this.brokerStatsManager != null) {
this.brokerStatsManager.start();
} if (this.brokerFastFailure != null) {
this.brokerFastFailure.start();
} }

可以从名字大致猜出接收远程消息是remotingServer.start(),点进去观察一下其具体实现:

这里看到我们熟悉的面孔ServerBootStrap, 那么可以明确一点,我们要知道的具体通信协议实现,必定是写在一个handler里面的:

.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline()
.addLast(defaultEventExecutorGroup, HANDSHAKE_HANDLER_NAME,
new HandshakeHandler(TlsSystemConfig.tlsMode))
.addLast(defaultEventExecutorGroup,
new NettyEncoder(),
new NettyDecoder(),
new IdleStateHandler(0, 0, nettyServerConfig.getServerChannelMaxIdleTimeSeconds()),
new NettyConnectManageHandler(),
new NettyServerHandler()
);
}

从这些handler中,由名字可以猜测,通信消息的解析发生在NettyServerHandler,进入NettyServerHandler:

由上图可知,它本身就是一个读消息的Handler, 可以看到的是接收的消息体是RemotingCommand。这个类必然就是整个RocketMq的通信协议。

点进去看一下:

大致上看由code、Header、body以及一些metedata组成。其实所有的Rpc调用框架基本上都是这个设计思路。所有的请求必须继承自某一个父类。

不过现在的微服务体系似乎没有这样子做,可能是出于不同的服务需求多样性考虑,但是没有统一的请求头着实怪异,后续有时间看一下这方面的设计考虑。

至此,Rpc的Netty调用链基本结束。

  •  二,RocketMq 通信编码 

由一的部分成功定位到了接收消息的入口,本章着重讲解其解析消息的细节实现。

rocketMq通信协议Netty采用的是面向字节流的报文设计。在发送端,前4个字节存储整个报文长度,紧接着4个字节存储头信息,然后紧接着发送body字节流。源码如下:

 public ByteBuffer encodeHeader(final int bodyLength) {
// 定义头4个字节储存整个报文长度
int length = 4; // 计算头部长度
byte[] headerData;
headerData = this.headerEncode();
length += headerData.length; // 计算body长度
length += bodyLength;

     // 头部信息:整体报文长度信息(4个字节) + 头部数据(length-bodyLehth)
ByteBuffer result = ByteBuffer.allocate(4 + length - bodyLength); // 第一个4字节: 存放报文整体长度信息,从这里我们可以看到meaasge的消息长度是有限制的
result.putInt(length); // 第二个4字节: 第一个字节存放的是序列化类型,有Java或者RocketMq类型。后三个字节存放的是头部数据长度
result.put(markProtocolType(headerData.length, serializeTypeCurrentRPC)); // 写入头部数据
result.put(headerData); result.flip(); return result;
}

  通过对编码部分源码学习,一般对字节的操作喜欢用位运算符,比如要整型的第三个字节,int >>>0xff & 0xff 即可。下面是rocketMq解析的部分示例代码:

   public static SerializeType getProtocolType(int source) {
return SerializeType.valueOf((byte) ((source >> 24) & 0xFF));
}

  待续。。。。。。

RocketMq中网络通信之服务端的更多相关文章

  1. web应用中浏览器与服务端的编码和解码

    转自:http://blog.sina.com.cn/s/blog_87cb63e50102w2b6.html 以下为正文: ************************************* ...

  2. DelphiXE7中创建WebService(服务端+客户端)

    相关资料: http://www.2ccc.com/news/Html/?1507.html http://www.dfwlt.com/forum.php?mod=viewthread&tid ...

  3. 在python中编写socket服务端模块(二):使用poll或epoll

    在linux上编写socket服务端程序一般可以用select.poll.epoll三种方式,本文主要介绍使用poll和epoll编写socket服务端模块. 使用poll方式的服务器端程序代码: i ...

  4. DelphiXE7中创建WebService(服务端+客户端) good

    相关资料:http://www.2ccc.com/news/Html/?1507.html DelphiXE7新建WebService具体操作:1.打开“DelphiXE7”->“File”-& ...

  5. Asp.net 中,在服务端向客户端写脚本的常用方法

    在Asp.net 服务端处理脚本,一般都用 ClientScriptManager ,即web窗体服务端的this.ClientScript.该对象比较常用的方法: 1.RegisterArrayDe ...

  6. 在Unity3D中连接WCF服务端

    服务端不多讲解,有一处需要改的地方.具体服务端请看WCF入门学习2-控制台做为宿主 建议实际项目不要拿去用,毕竟是mono不是原生.net.或许是个坑 由于Unity的mono版本问题不能直接用net ...

  7. [gRPC] 在 .NET Core 中创建 gRPC 服务端和客户端

    gRPC 官网:https://grpc.io/ 1. 创建服务端 1.1 基于 ASP.NET Core Web 应用程序模板创建 gRPC Server 项目. 1.2 编译并运行 2. 创建客户 ...

  8. php开发中怎么获取服务端MAC地址?

    MAC(Media Access Control或者Medium Access Control)地址,意译为媒体访问控制,或称为物理地址.硬件地址,用来定义网络设备的位置.在php中如何获取MAC(M ...

  9. jQuery中的ajax服务端返回方式详细说明

    http://blog.sina.com.cn/s/blog_6f92e3a70100u3b6.html     上次总结了下ajax的所有参数项,其中有一项dataType是设置具体的服务器返回方式 ...

随机推荐

  1. js动态生成数据的抓取

    需求:爬取https://www.xuexi.cn/f997e76a890b0e5a053c57b19f468436/018d244441062d8916dd472a4c6a0a0b.html页面中的 ...

  2. Linux环境下虚拟环境virtualenv安装和使用(转)

    virtualenv用于创建独立的Python环境,多个Python相互独立,互不影响,它能够: 1. 在没有权限的情况下安装新套件 2. 不同应用可以使用不同的套件版本 3. 套件升级不影响其他应用 ...

  3. vim与系统剪切板之间的复制粘贴

    背景 vim各种快捷建溜得飞起,然而与系统剪切板之间的复制粘贴一直都是我的痛. 每次需要从vim中拷贝些文字去浏览器搜索,都需要用鼠标选中vim的文字后,Ctrl+c.Ctrl+v,硬生生掐断了纯键盘 ...

  4. c++学习书籍推荐《数据结构C++语言描述:应用标准模板库STL(第2版)》下载

    本书是Ford和Topp两位教授于1996看出版的名著Data Structures with C++的第2版,在全球范围内已经有数以万计的学生从中受益.作者将C++语言作为算法描述语言,应用包含规范 ...

  5. .Net Core 创建和使用中间件

    1. 定义中间内容 1.1 必须有一个RequestDelegate 委托用了进入一个中间件 1.2 通过构造函数设置这个RequestDelegate委托 1.3 必须有一个方法Task Invok ...

  6. 洛谷P2057 [SHOI2007]善意的投票 题解

    题目链接: https://www.luogu.org/problemnew/show/P2057 分析: 由0和1的选择我们直觉的想到0与S一堆,1与T一堆. 但是发现,刚开始的主意并不一定是最终的 ...

  7. Java 将PDF 转为Word、图片、SVG、XPS、Html、PDF/A

    本文将介绍通过Java编程来实现PDF文档转换的方法.包括: 1. PDF转为Word 2. PDF转为图片 3. PDF转为Html 4. PDF转为SVG 4.1 将PDF每一页转为单个的SVG ...

  8. 2017day1

    http://www.cnblogs.com/alex3714/articles/5465198.html 四.Python安装 windows 1 2 3 4 5 6 7 1.下载安装包     h ...

  9. join,列表和字典用for循环的删除,集合,深浅拷贝

    1.join() 将列表转换成字符串,并且每个字符之间用另一个字符连接起来,join后面必须是可迭代的对象(字符串,列表,元组,字典,集合),数字不能迭代 例如: s = ['a','b','c'] ...

  10. 使用java Apache poi 根据word模板生成word报表

    项目开发过程中,客户提出一堆导出报表的需求,需要导出word格式,页眉还需要加上客户公司的logo,试了几种方案,最后选择了用 Apache poi 加上自定义标签的方式实现. 目前功能还比较简单,一 ...