• 一,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. 精通并发与 Netty (二)常用的 rpc 框架

    Google Protobuf 使用方式分析 对于 RPC 协议来说,最重要的就是对象的发送与接收,这就要用到序列化与反序列化,也称为编码和解码,序列化与反序列化和网络传输一般都在对应的 RPC 框架 ...

  2. .Net之Layui多图片上传

    前言: 多图上传在一些特殊的需求中我们经常会遇到,其实多图上传的原理大家都有各自的见解.对于Layui多图上传和我之前所说的通过js获取文本框中的文件数组遍历提交的原理一样,只不过是Layui中的up ...

  3. Ural 2070:Interesting Numbers(思维)

    http://acm.timus.ru/problem.aspx?space=1&num=2070 题意:A认为如果某个数为质数的话,该数字是有趣的.B认为如果某个数它分解得到的因子数目是素数 ...

  4. vue中修改子组件样式

    一.问题叙述 项目里需要新添加一个表单页面,里面就只是几个select,这个几个select是原本封装好的组件,有自己原本的样式,而这次的原型图却没有和之前的样式统一起来,需要微调一下,这里就涉及到父 ...

  5. select自定义下拉三角符号,css样式小细节

    本来没有写文章的习惯,但是闲下来了,整理资料,发现还挺纠结,对前端来说.所以整理下,希望对看到的人有所帮助,毕竟我不是前端开发. 起因,是前端告诉我select 框的三角箭头不能自定义.但是第二次的时 ...

  6. Visual Studio中Es6的开发环境搭建

    1.打开终端,输入初始化代码.输入代码之后会在目录中出现package.json,可以在红色下划线上写上作者名和描述(不写也可以) npm init -y    2.安装Babel转换器 npm in ...

  7. SpringCloud解析之Eureka

    本文基于Spring Cloud Edgware.SR6版本,从功能和架构上解析Eureka,让大家对Eureka有一个较为清晰的认识(本文默认大家对分布式微服务有一个初步的概念和理解,本文不涉及或少 ...

  8. 设计模式——通用泛型单例(普通型和继承自MonoBehaviour)

    单例模式是设计模式中最为常见的,不多解释了.但应该尽量避免使用,一般全局管理类才使用单例. 普通泛型单例: public abstract class Singleton<T> where ...

  9. Excel公式中问题-记住不要忽略空格!

    总结一下之前犯得愚蠢的小问题: 程序:每日报表:从DB下载数据填充到excel,包括3个sheet,sheet1:总结<模板,公式填充,数据源为sheet2,sheet3>;sheet2: ...

  10. java高并发系列 - 第14天:JUC中的LockSupport工具类,必备技能

    这是java高并发系列第14篇文章. 本文主要内容: 讲解3种让线程等待和唤醒的方法,每种方法配合具体的示例 介绍LockSupport主要用法 对比3种方式,了解他们之间的区别 LockSuppor ...