搜索关注微信公众号"捉虫大师",后端技术分享,架构设计、性能优化、源码阅读、问题排查、踩坑实践。

协议

协议通俗易懂地解释就是通信双方需要遵循的约定。

我们了解的常见的网络传输协议有tcp、udp、http等。再到我们常用的基础组件,一般来说client端与server端也有相应的协议,如redis、mysql、zookeeper等都是各自约定的私有协议,同样今天标题中的dubbo协议也是一种私有协议,他们都是应用层协议,基于tcp或udp设计。

通常应用层协议都是基于tcp和udp,可靠传输通常使用tcp,如大多数的基础组件,如redis、mysql。只有能容忍丢失且需要很高的性能时使用udp协议,比如metric上报等场景。

这里介绍几种基于tcp的应用协议。

redis协议

redis协议足够简单,所以先介绍一下。redis协议基于tcp设计,客户端和服务器发送的命令一律使用\r\n(CRLF)结尾。他的格式如下

*<参数数量> CRLF
$<参数1 字节数量> CRLF
<参数1的数据> CRLF
...
$<参数n 字节数量> CRLF
<参数n的数据> CRLF

举个例子,client向server端发送命令 set mykey myvalue

*3 CRLF
$3 CRLF
SET CRLF
$5 CRLF
mykey CRLF
$7 CRLF
myvalue CRLF

也就是 *3\r\n$3\r\nSET\r\n$5\r\nmykey\r\n$7\r\nmyvalue\r\n

关于redis协议更详细信息可以看这个链接:

http://redisdoc.com/topic/protocol.html

http协议

http协议是我们最常见的协议,它的请求报文格式是由三部分组成:

  • 请求行:包括method、url、version,由空格分隔,\r\n结尾
  • 请求头:多行,每行是key:value的格式,以\r\n结尾
  • 请求体:请求头与请求体直接由一个空白行分隔,请求体的长度在请求头中由content-length给出

redis和http协议的处理方式截然不同。他们都是基于tcp,而tcp协议传输的数据是流式的,通俗地说就是它就像水流,不断地发送字节,tcp保证不重复,不丢包。而接收端要拿到想要的数据必须得从流式的数据中“判断出数据包的边界”,这就是tcp的粘包问题,解决它通常有三种方法:

  1. 发送固定长度的消息
  2. 使用特殊标记区分消息间隔
  3. 将消息的尺寸和消息一起发送

redis协议使用了第2种,http和接下来要介绍的dubbo协议使用了第3种,固定长度的消息比较理想,在实际中很少遇到。

dubbo协议

由于dubbo支持的协议很多,本文提到的dubbo协议特指dubbo框架的默认协议,也就是dubbo的私有协议。它的格式如下:

  • 0-15: 魔数,判断是否是dubbo协议
  • 16: 判断是请求还是返回
  • 17: 判断是否期望返回
  • 18: 判断是否为事件消息,如心跳事件
  • 19-23: 序列化标志
  • 24-31: 标志响应状态(类似http status)
  • 32-63: 请求id
  • 64-95: 内容长度(字节)
  • 96-?: 序列化后的内容(换行符分隔)

常用的attachments在dubbo协议的哪里?

dubbo的attachments,我们通常将他类比为http协议的header,可以携带一些隐式的参数信息(不用编码到请求对象中),如压测标志等。从他的类型

private Map<String, String> attachments;

基本可以推断出attachments存在于dubbo协议的96字节之后的内容中,因为前面头的根本放不下这个map。

从dubbo的实现中可以看出,dubbo的一个请求被封装为一个DecodeableRpcInvocation对象,里面包含了methodNameparameterTypesargumentsattachments等,将该对象序列化后填入dubbo协议的96字节后的内容中发送出去。

使用时,consumer端:

RpcContext.getContext().setAttachment("hello", "from_consumer");

provider端:

RpcContext.getContext().getAttachment("hello");

这里能看出dubbo协议相比较http协议来说设计的还是有所欠缺的,想要拿到一些隐式参数,或者想要知道请求发往哪里,必须得把请求体解析出来才可以,这也是dubbo协议往mesh方向发展的一个绊脚石。

dubbo协议支持在返回值中带回attachments吗?

consumer端向provider端发送请求可以在头部携带隐式参数,那么返回时也可以从provider端带回到consumer端吗?

比如provider回传给consumer它自身的处理耗时,consumer计算出请求的响应时间,两者相减即可得到网络耗时,此时provider端最好是将耗时放在attachments中隐式地传回。

dubbo的协议是请求和回复都是相同格式,理论上consumer可以带隐式参数到provider端,则provider端肯定也可以回传。

从dubbo的返回对象DecodeableRpcResult中可以看到是存在attachments的,但从实际的测试来看,2.7.x版本是不支持的,但2.6.x(>=2.6.3)版本是支持的。

provider端设置:

RpcContext.getServerContext().setAttachment("hello", "from_provider");

consumer端获取:

RpcContext.getServerContext().getAttachment("hello")

github上相关的issue链接如下:

https://github.com/apache/dubbo/pull/1843

协议和序列化有什么区别?

我们可能会经常听到这样的说法,dubbo除了dubbo协议外还支持rest、thrift、grpc等协议,也支持hessian、json序列化。协议与序列化是什么关系?

通过刚刚介绍的dubbo协议格式或许就能明白,dubbo协议是如上的格式包含了头和内容,其中96字节之后的内容是序列化后的内容,默认使用hessian2序列化,也可以修改为fastjson、gson、jdk等。只需要配置即可修改协议

<dubbo:protocol name="dubbo" serialization="fastjson"/>

如果非要做个类比的话,就是你不仅可以通过http协议传输json格式的数据,也可以传输xml格式的数据。http就是协议,json和xml就是序列化。

最后

dubbo协议的设计虽然有所欠缺,但依然不能阻止它成为dubbo使用最广泛的协议。


搜索关注微信公众号"捉虫大师",后端技术分享,架构设计、性能优化、源码阅读、问题排查、踩坑实践。

聊聊dubbo协议的更多相关文章

  1. 聊聊dubbo协议2

    本文已收录 https://github.com/lkxiaolou/lkxiaolou 欢迎star. 在<聊聊dubbo协议>中介绍了attachments在consumer和prov ...

  2. Dubbo(五):Dubbo中的URL统一资源模型与Dubbo协议

    一.URL简介 URL也就是Uniform Resource Locator,中文叫统一资源定位符.Dubbo中无论是服务消费方,或者服务提供方,或者注册中心.都是通过URL进行定位资源的.所以今天来 ...

  3. dubbo源码分析4-基于netty的dubbo协议的server

    dubbo源码分析1-reference bean创建 dubbo源码分析2-reference bean发起服务方法调用 dubbo源码分析3-service bean的创建与发布 dubbo源码分 ...

  4. Dubbo协议与连接控制

    协议参考手册 (+) (#) 推荐使用Dubbo协议 性能测试报告各协议的性能情况,请参见:性能测试报告 (+) dubbo:// (+) (#) Dubbo缺省协议采用单一长连接和NIO异步通讯,适 ...

  5. Dubbo协议

    参考dubbo官方文档http://dubbo.apache.org/zh-cn/docs/user/references/protocol/dubbo.html dubbo共支持如下几种通信协议: ...

  6. dubbo协议下的单一长连接与多线程并发如何协同工作

    上班的路上突然就冒出了这么个问题:既然在dubbo中描述消费者和提供者之间采用的是单一长连接,那么如果消费者端是高并发多线程模型的web应用,单一长连接如何解决多线程并发请求问题呢? 其实如果不太了解 ...

  7. dubbo hessian+dubbo协议

    Dubbo缺省协议采用单一长连接和NIO异步通讯,适合于小数据量大并发的服务调用,以及服务消费者机器数远大于服务提供者机器数的情况 Hessian协议用于集成Hessian的服务,Hessian底层采 ...

  8. 聊聊Http协议

    http协议是大家在互联网中最为熟悉的协议,只要上网大家都会遇到,但是,很多人被问道什么是http协议,http协议的内容是什么就懵了.这里,我们随便聊聊http协议. 首先,我们说说协议.我一直觉得 ...

  9. dubbo协议参考手册(转)

    原文链接:http://wely.iteye.com/blog/2331332 协议参考手册 (+) (#) 推荐使用Dubbo协议 性能测试报告各协议的性能情况,请参见:性能测试报告 (+) dub ...

随机推荐

  1. 使用 WPF 做个 PowerPoint 系列 基于 OpenXML 解析实现 PPT 文本描边效果

    本文是使用 WPF 做个 PowerPoint 系列的博客,本文来告诉大家如何解析 PPT 里面的文本描边效果,在 WPF 应用中绘制出来,实现像素级相同 背景知识 在开始之前,期望你了解了 PPT ...

  2. Excel的内置功能,其实真的是够用了。(学习观)

    很多人问我,学好Excel是不是要背好多函数,是不是要会写VBA代码? 我说,那得看你能放多少时间和精力在Excel上. Excel的内置功能,其实真的是够用了:觉得不够用的,花几十块钱买个插件,也差 ...

  3. Python变量的作用域在编译过程中确定

    为了节省读友的时间,先上结论(对于过程和细节感兴趣的读友可以继续往下阅读,一探究竟): [结论] 1)Python并不是传统意义上的逐行解释型的脚本语言 2)Python变量的作用域在编译过程就已经确 ...

  4. 深度解析HashMap

    讲讲HashMap? 源码解析 final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) { //辅助 ...

  5. C语言之字符串替换库函数replace

    头文件 #include <algorithm> 例子 下面的代码, 将字符串中的 /替换为\ std::string str("C:/demo/log/head/send&qu ...

  6. VS2013 or up version +常用插件

    !!版权声明:本文为博主原创文章,版权归原文作者和博客园共有,谢绝任何形式的 转载!! 作者:mohist 下载地址: https://github.com/mohistH/vs2013_extens ...

  7. 【LeetCode】156. Binary Tree Upside Down 解题报告(C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 递归 迭代 日期 题目地址:https://leet ...

  8. 【九度OJ】题目1015:还是A+B 解题报告

    [九度OJ]题目1015:还是A+B 解题报告 标签(空格分隔): 九度OJ http://ac.jobdu.com/problem.php?pid=1015 题目描述: 读入两个小于10000的正整 ...

  9. 【LeetCode】189. Rotate Array 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 切片 递归 日期 题目地址:https://leet ...

  10. 【LeetCode】567. Permutation in String 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地址:https://leetcode.com/problems/permutati ...