消息队列高手课
李玥
美团高级技术专家
52199 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 42 讲
进阶篇 (21讲)
消息队列高手课
15
15
1.0x
00:00/00:00
登录|注册

13 | 传输协议:应用程序之间对话的语言

实现高性能通信程序
序号标识请求与响应对应关系
TCP连接的全双工通道
单工通信
预置长度
标点符号分隔
思考题
双工通信提升吞吐量
断句方法和技巧
传输协议设计

该思维导图由 AI 生成,仅供参考

你好,我是李玥。
经过前面几课的学习,我们已经可以实现高性能的结构化数据传输了。不过,应用程序之间要想互相通信,一起配合来实现业务功能,还需要有一套传输协议来支持。
传输协议就是应用程序之间对话的语言。设计传输协议,并没有太多规范和要求,只要是通信双方的应用程序都能正确处理这个协议,并且没有歧义就好了。
这节课,我们就来说一下设计高性能传输协议的一些方法和技巧。

如何“断句”?

既然传输协议也是一种语言,那么在应用程序之间“通话”的过程中,与我们人类用自然语言沟通有很多相似之处,但是需要处理的问题却又不同。
现代语言,无论是汉语还是英语,都是通过标点符号来分隔句子的,这个叫“断句”。古代汉语是没有标点符号的,断句全靠上下文,但这种断句方式有的时候会出现歧义,比如很著名的那个段子“下雨天留客天天留我不留”,不同的断句方式,意思完全不一样。
我们在传输数据的的时候,首先要解决的就是断句问题。对于传输层来说,收到的数据是什么样的?就是一段一段的字节,但是,因为网络的不确定性,你收到的分段并不一定是我们发出去的分段。比如我们发送的数据是这样的:
下雨天 留客天 天留 我不留
这样断句,意思就是,作为主人我不想让你在我这儿住。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

设计高性能传输协议需要解决断句和双工通信的问题。在传输协议设计中,断句问题可以通过使用分隔符或前置长度的方法来解决。分隔符方法需要处理转义问题,而前置长度方法则更为简单高效。另外,实现双工通信可以提升数据传输的吞吐量,通过给每个请求加上唯一序号,并在响应中带上请求的序号,可以确保请求和响应能够正确对应。这种方法是一种通用的实现双工通信的方式,可以有效提升数据传输的吞吐量。综合以上方法,配合专用的序列化方法,可以实现一套高性能的网络通信协议,适用于进程间通信。文章还提出了一个思考题,鼓励读者动手实现一个简单的高性能通信程序,以加深对所学知识的理解。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《消息队列高手课》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(43)

  • 最新
  • 精选
  • Switch
    用 netty 实现了,使用了多种 序列化方式实现,差异还是很大的。写出来和知道怎么做,差距还是非常大的,当完整的写完练习,确实把老师讲到的这些知识点都串起来了。序列化框架的选型及接口设计、通讯协议设计、编解码设计、 netty 服务端客户端的处理。 代码在该目录下:https://github.com/Switch-vov/mq-learing/tree/master/src/main/java/com/switchvov/network/chat 整个实现下来,不同的序列化框架,性能差异还是很大的。用 protostuff 性能是最好的。 麻烦老师看看,哪些地方还能再优化。 - fastjson - 遍历10000次,花费:1400ms - 遍历100000次,花费:7272ms - 遍历1000000次,花费:86840ms - protostuff - 遍历10000次,花费:1224ms - 遍历100000次,花费:5381ms - 遍历1000000次,花费:51677ms - kryo - 遍历10000次,花费:1307ms - 遍历100000次,花费:6774ms - 遍历1000000次,花费:102819ms

    作者回复: 代码结构很清晰,值得大家学习。 优化的建议:可以采用专用序列化方式,另外,你在做测试的时候有没有关闭控制台的打印输出?这个对性能的影响是很大的。

    2019-10-13
    2
    88
  • 晴空
    老师请教个问题,tcp协议中已经协商好了最大报文长度,应用协议为什么又要设置一下报文长度呢,期待老师帮忙解惑

    作者回复: 需要注意的是,在OSI七层网络协议栈中,tcp协议是四层(传输层)协议,而我们设计的传输协议都是七层(应用层)协议,下层协议对上层来说是透明的。 通俗的说,tcp包的长度和我们协议中一条消息的长度是完全没有关系的,一个tcp包可能包含n条完整的消息,也可能包含半条消息,或者前后2个半条消息加上中间n条完整的消息,这都是不一定的。

    2019-09-04
    3
    16
  • oldman
    老师,我理解的双工通信,是不是说不管是客户端还是服务端建立好链接之后,双方都可以基于该socket进行收发消息就好了,而不是说服务器只能accept到message之后再做一些处理。

    作者回复: 是这样的。

    2019-08-23
    13
  • 知己逢知遇
    多线程下异步处理一次会话的结果消息体,除了对这次会话的结果消息进行编号,是否也要对分割的消息体进行顺序编号? 电驴,迅雷,p2p这种软件的消息协议大概是什么样的呢?是不是部分协议跟今天老师讲的情况类似? 我是不是可以理解为,在双全功下,我和一个网站就可以建立一条长链接,然后所有的资源请求都通过这条链接进行交换,只要协议正确,就可以保证数据的完整性,正常访问并解析打开的该网站的所有页面。 多线程,异步的io操作,是不是也有自己的协议?

    作者回复: 你需要了解,协议是分层的,就像我们发快递,我发给你的可能是个手机,对于快递小哥来说,这就是个小包裹,他不关心里面是什么,总之我保证给你把包裹安全的送到站点儿就行了。包裹到了站点儿会分拣装箱,然后用小货车运到机场,对于小货车司机来说,它也不关心车里装的是什么,只要把车安全开到机场就行了。 对于协议来说已是这样在发送的时候一层一层的封装,然后接收的时候再一层一层解封,对于每一层协议来说,他是不知道底层是什么协议的,也不知道上层协议是如何封装的(送件的快递小哥不知道也不关心这个件是怎么到配送站的,也不知道包裹里到底装的啥),只在自己的协议层完成处理即可。

    2019-08-20
    2
    12
  • 刘天鹏
    https://gist.github.com/liutianpeng/85ce524452c8206396c94ab93506deda 一个"胡同"做中转 两个"大爷"TCP连接到胡同 我这个版本的胡同效率有点低 大爷相遇1万次就用了 3.8s

    作者回复: 赞分享代码的同学👍👍👍

    2019-08-20
    11
  • Switch
    看了加餐之后,重构了下执行逻辑。更改一问一答交互为 主客户端同时发送消息。主客户端根据消息类型答复相应内容。 另外,老师,专用化序列方式在哪能找到借鉴的地方呢? 是的,没关闭输出。关闭输出后,重新测试后的结果如下: - 关闭打印 - fastjson - 遍历10000次,花费:555ms - 遍历100000次,花费:2740ms - 遍历1000000次,花费:28418ms - protostuff - 遍历10000次,花费:440ms - 遍历100000次,花费:2599ms - 遍历1000000次,花费:23991ms - kryo - 遍历10000次,花费:522ms - 遍历100000次,花费:2805ms - 遍历1000000次,花费:28130ms - 没关闭打印 - fastjson - 遍历10000次,花费:1400ms - 遍历100000次,花费:7272ms - 遍历1000000次,花费:86840ms - protostuff - 遍历10000次,花费:1224ms - 遍历100000次,花费:5381ms - 遍历1000000次,花费:51677ms - kryo - 遍历10000次,花费:1307ms - 遍历100000次,花费:6774ms - 遍历1000000次,花费:102819ms 老师加餐中给的示例代码,在我电脑上 10W 次,在 [8,12]s 这个区间 代码在该目录下:https://github.com/Switch-vov/mq-learing/tree/master/src/main/java/com/switchvov/network/chat

    作者回复: 可以参考一下加餐这节课中的序列化代码。

    2019-10-14
    3
    6
  • A9
    看了直播,没想到老师你是这样的人 所以,到底谁快?

    作者回复: 同学当然是你最快呀!😏

    2019-08-20
    5
  • 大白先生
    老师,那在一次会话过程中,开头的先是唯一序列号么。然后后面跟的是数据长度,再然后是内容么。那接到消息的一方,该如何分辨序列号的长度大小,做到区分序列号和内容前的数据长度信息?

    作者回复: 开头是数据长度,序号也是数据的一部分,所以应该在长度之后。

    2019-08-21
    2
    4
  • 花子翁
    通过预设长度的方式来断句,不会出现分隔符同样的问题吗? 因为预设长度的信息,理论上也会同样出现在数据内容本身,那如何进行区分呢?

    作者回复: 只要数据没有在传输途中被篡改,预设长度断句就总是有效的。 比如,我们约定长度为int类型,占4个字节。从连接建立开始,收到的一个4个字节,一定是第一句的长度。每读取一句之后,接下来的4个字节,一定是下一句的长度,以此类推。

    2020-04-30
    2
    3
  • 宋晓明
    老师,昨天您的直播我看了 但心中一直有个疑问:一般架构师coding能力非常强,尤其是java,现在很多招聘要求都是java架构师,目前本人擅长的语言是python和go,说实话 java虽好,但本人很不喜欢,是不是我与架构师就无缘了??

    作者回复: 跟语言关系不大,其实各种编程语言背后的实现原理都是差不多的。一般的大厂的架构师职位对语言也没有强要求,而且很多架构师都是掌握多门编程语言的。

    2019-08-21
    3
收起评论
显示
设置
留言
43
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部