RocketMq中网络通信之服务端
- 一,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中网络通信之服务端的更多相关文章
- web应用中浏览器与服务端的编码和解码
转自:http://blog.sina.com.cn/s/blog_87cb63e50102w2b6.html 以下为正文: ************************************* ...
- DelphiXE7中创建WebService(服务端+客户端)
相关资料: http://www.2ccc.com/news/Html/?1507.html http://www.dfwlt.com/forum.php?mod=viewthread&tid ...
- 在python中编写socket服务端模块(二):使用poll或epoll
在linux上编写socket服务端程序一般可以用select.poll.epoll三种方式,本文主要介绍使用poll和epoll编写socket服务端模块. 使用poll方式的服务器端程序代码: i ...
- DelphiXE7中创建WebService(服务端+客户端) good
相关资料:http://www.2ccc.com/news/Html/?1507.html DelphiXE7新建WebService具体操作:1.打开“DelphiXE7”->“File”-& ...
- Asp.net 中,在服务端向客户端写脚本的常用方法
在Asp.net 服务端处理脚本,一般都用 ClientScriptManager ,即web窗体服务端的this.ClientScript.该对象比较常用的方法: 1.RegisterArrayDe ...
- 在Unity3D中连接WCF服务端
服务端不多讲解,有一处需要改的地方.具体服务端请看WCF入门学习2-控制台做为宿主 建议实际项目不要拿去用,毕竟是mono不是原生.net.或许是个坑 由于Unity的mono版本问题不能直接用net ...
- [gRPC] 在 .NET Core 中创建 gRPC 服务端和客户端
gRPC 官网:https://grpc.io/ 1. 创建服务端 1.1 基于 ASP.NET Core Web 应用程序模板创建 gRPC Server 项目. 1.2 编译并运行 2. 创建客户 ...
- php开发中怎么获取服务端MAC地址?
MAC(Media Access Control或者Medium Access Control)地址,意译为媒体访问控制,或称为物理地址.硬件地址,用来定义网络设备的位置.在php中如何获取MAC(M ...
- jQuery中的ajax服务端返回方式详细说明
http://blog.sina.com.cn/s/blog_6f92e3a70100u3b6.html 上次总结了下ajax的所有参数项,其中有一项dataType是设置具体的服务器返回方式 ...
随机推荐
- 精通并发与 Netty (二)常用的 rpc 框架
Google Protobuf 使用方式分析 对于 RPC 协议来说,最重要的就是对象的发送与接收,这就要用到序列化与反序列化,也称为编码和解码,序列化与反序列化和网络传输一般都在对应的 RPC 框架 ...
- .Net之Layui多图片上传
前言: 多图上传在一些特殊的需求中我们经常会遇到,其实多图上传的原理大家都有各自的见解.对于Layui多图上传和我之前所说的通过js获取文本框中的文件数组遍历提交的原理一样,只不过是Layui中的up ...
- Ural 2070:Interesting Numbers(思维)
http://acm.timus.ru/problem.aspx?space=1&num=2070 题意:A认为如果某个数为质数的话,该数字是有趣的.B认为如果某个数它分解得到的因子数目是素数 ...
- vue中修改子组件样式
一.问题叙述 项目里需要新添加一个表单页面,里面就只是几个select,这个几个select是原本封装好的组件,有自己原本的样式,而这次的原型图却没有和之前的样式统一起来,需要微调一下,这里就涉及到父 ...
- select自定义下拉三角符号,css样式小细节
本来没有写文章的习惯,但是闲下来了,整理资料,发现还挺纠结,对前端来说.所以整理下,希望对看到的人有所帮助,毕竟我不是前端开发. 起因,是前端告诉我select 框的三角箭头不能自定义.但是第二次的时 ...
- Visual Studio中Es6的开发环境搭建
1.打开终端,输入初始化代码.输入代码之后会在目录中出现package.json,可以在红色下划线上写上作者名和描述(不写也可以) npm init -y 2.安装Babel转换器 npm in ...
- SpringCloud解析之Eureka
本文基于Spring Cloud Edgware.SR6版本,从功能和架构上解析Eureka,让大家对Eureka有一个较为清晰的认识(本文默认大家对分布式微服务有一个初步的概念和理解,本文不涉及或少 ...
- 设计模式——通用泛型单例(普通型和继承自MonoBehaviour)
单例模式是设计模式中最为常见的,不多解释了.但应该尽量避免使用,一般全局管理类才使用单例. 普通泛型单例: public abstract class Singleton<T> where ...
- Excel公式中问题-记住不要忽略空格!
总结一下之前犯得愚蠢的小问题: 程序:每日报表:从DB下载数据填充到excel,包括3个sheet,sheet1:总结<模板,公式填充,数据源为sheet2,sheet3>;sheet2: ...
- java高并发系列 - 第14天:JUC中的LockSupport工具类,必备技能
这是java高并发系列第14篇文章. 本文主要内容: 讲解3种让线程等待和唤醒的方法,每种方法配合具体的示例 介绍LockSupport主要用法 对比3种方式,了解他们之间的区别 LockSuppor ...