协议是在通信层之上管理具体消息在应用之间如何传递和理解的逻辑规则,而协议生成器则是一种根据这些规则生成具体的消息定义的工具。协议生成器大大降低了维护协议的难度,是某些协议(例如大名鼎鼎的 Protobuf 和老牌一些的 Thrift 等)得以流行的关键。本文将假设读者对计算机通信和协议有一定了解,重点讲述生成器的设计和作用。

协议的设计

从最高层来看,一个通信协议必须具备三种要素:数据交互方式、消息描述和编解码规范。这里也许会有不同意见——将编解码规范列入到通信层。但是本文所持的观点是,编解码规范也是协议不可或缺的一部分,因为协议本身是为了通过媒介在多个程序实例之间通信而设计的。如果脱离了编解码,协议便成为了单纯的接口描述,并不能体现出“通信”的功能了。

协议的制定

设计协议时,一般会从需求入手,围绕上述的协议三个要素进行反复论证。本文想要探讨的协议是在网络协议栈里最顶层的应用层协议,其余层级的协议因为通用性较强、需要底层的软硬件支持,日常开发中针对其应用的场景较多,而修改甚至重写的可能性较小,因此不作讨论。

应用层协议通常会有广播式应答式两大类,通常对应单向传输信息交互两种类型的应用。例如 GPS 卫星信号就是一种广播式协议,设备只需要接收信号,并不需要向卫星发射信号;而我们常见的网络浏览器所使用的 HTTP 协议就是一种信息交互式的协议——服务器需要知道客户端想要什么,客户端也必须知道服务器给出的结果。这通常是协议设计的第一步。

接着则是选择合适的编码方式,通常会在编码效率、传输效率(即信息压缩比)、解码效率(例如是否允许局部解码)这三个维度之间进行权衡。

确定编解码方式后,大部分的协议制定工作也就完成了。剩下的就是根据业务来规定组件之间的交互方式——同步(如 HTTP )还是异步(如交易所)、如何管理客户端(会话管理)等。

如果抛开业务层,协议的本质就是将内存中的一段信息从一个组件通过网络等介质传递到另一个组件并还原成原本信息的过程。

协议的维护

当协议被设计出来之后,总会有各种需求变化要求协议进行一些更改或者扩充。例如维持编解码方式不变,在业务层多加了一个组件,该组件提供的功能需要加入新的消息来满足;或者某个组件升级了版本,在某个消息中添加或删除了某几个字段等。

协议的维护在日常开发中非常常见,一个便于维护、灵活的协议实现就变得非常重要了。

为何需要生成器

前面列举了协议的三个要素,如果从最不容易更改到最容易更改来排序的话,应该是编解码规范(例如规定了编解码为键值对形式的二进制编码后,便不会轻易更改)、信息交互方式、消息描述。因此我们应该构建一种体系,使得消息描述更改很容易,而利用编解码规范相对固定的特点将其固化到程序里。这样可以使得协议变更操作更高效,也降低了故障率。

同时,在较大型的应用中,通常希望协议的编解码流程静态化(如解码出来的结果应该是一个有明确定义的对象,各字段都由编译器检查拼写、类型是否正确;而不是一种通用的字典格式,由调用者来随意存取字段),以此降低维护成本。而且出于性能的考虑,这些代码将不会使用反射等机制,因此重复性很高(多数代码都一样,只是字段名字和类型不同),见下例:

某解码器代码片段,其作用是将 MongoDB 的对象结构转化成预先定义的对象格式

如何构建生成器

在前面描述的协议设计各个环节中,生成器都可以被使用。从本质上来说,生成器只是一种按照规则生成可编译代码的工具。

生成代码的方式可以多种多样, 例如在 Java 中有 jCodeModel 这样的代码构建工具,也可以用 velocity 这样的模板库(一般被用来生成网页)来生成代码,不拘一格。

一个基本的协议生成器至少包含协议描述、代码生成、代码编译三部分。其中代码编译比较简单,即生成出来的代码必须能通过编译。下面重点说前两部分。

协议描述

在代码生成前,必须让生成器了解将要生成的协议是什么样子的。同时在决定开发或使用协议生成器的时候,也必须决定好生成的代码将会安插在协议的什么部分。例如 Protobuf 是一种序列化生成器,而 gRPC 则是从通信一直到回调生成了全套代码。使用者只需要编辑描述文件,其余的重复性工作由机器完成。

对于协议描述,一般来说我们会定义如下术语:

  1. 消息及其字段
  2. 字段类型

其中“消息”是协议中完整信息传递的最小单位,而“字段”则是构成消息的组成部分(单独的字段无法独立代表明确的业务信息,因此“消息”是最小单位而不是“字段”)。

具体到不同的协议类型,还有可能会定义诸如“操作”、“服务”等上层分类。例如在请求应答式的协议中,一次完整的信息传递依赖于一个请求和一个应答两条消息。

协议描述的格式不拘一格,Java 世界中更偏向用 XSD 定义的 XML 格式,Python 世界中可能直接使用源代码文件作为描述文件,而 Protobuf 及 gRPC 这类跨语言的工具则自定义了描述文件格式。直接使用源码作为描述文件的做法在开发时相对简单,但是无法跨语言。

代码生成

有了描述文件后自然是根据描述文件按照一定规则生成代码了。这里并无统一的方法论,看各自的需求决定如何编写。这里只能提供一些编写建议,供参考。

在生成器读取描述文件后需要对其正确性进行验证,如果有错误则要提供明确的错误信息。因为内部使用的描述文件并非广为人知的文件格式,因此使用者能依靠的只有报错信息,无法在网上搜索资料。因此明确、友好的报错信息就显得特别重要了 —— 尤其是当描述文件比较复杂的时候。

先手写几个有代表性的消息代码,再设计代码生成器。这样做的好处是能直观地知道需要什么样的模板,生成目标代码后可以将其和手写的代码来对比,调试起来更容易。在选择试写消息时最好是选择一个相对复杂的消息,包含了每一种协议支持的数据类型,尤其是相对复杂的数组、对象数组、枚举、各种可变长度类型等。这些消息的编解码规则相对复杂,如果在早期阶段没有纳入考量,很容易在生成器编写的中后期出现大量重构的情况。

对于生成后的代码在性能和可读性之间选择性能。因为代码生成器的作用就是让机器帮助人做重复性的劳动,而生成之后的代码并不需要人类阅读(调试生成器时除外)。因此可以将生成后的代码视为编译结果,只要机器能读或执行即可,因此在可读性与性能冲突时选择性能。例如避免使用有已知性能问题的语法糖、尽可能使用位运算等。实际上代码生成器的最终目标是生成经该语言编译器编译后的机器码(如有此类机制,当然有很多例外,例如 Python ),生成器之所以生成该语言的源文件实际上是为了便于生成器的开发。如果不复用语言本身的编译器的话就得直接开发一个从描述语言到机器语言的编译器了,这是完全没有必要的。

总结

米筐在创业初期就实现了一套针对 Java 语言的类似 gRPC 的全套编解码生成器(当时 gRPC 还在 beta 阶段,包括其依赖于某个支持 http2.0 的 netty 版本也在 beta 阶段)。之后米筐将后台架构改成了 Python,后台组件的通信协议也直接使用了 gRPC 。虽然自研的协议在性能上比起 gRPC 略有优势,但是研发投入非常大,遇到跨语言场景时就显得力不从心了。

自研的通信机制在对性能有极致要求的场景下会优于 gRPC 的方案,一般使用场景下还是推荐直接使用 gRPC 来作为底层通信框架。如果是小型项目,或者使用场景比较简单的项目,甚至不推荐使用 RPC 框架,而是通过自动化测试来保证应用的正确性,以灵活的协议来提高开发效率。例如 RQData 的选择就是如此,它只服务于金融数据调取这一种场景,非常容易做自动化测试,因此直接使用了类似 JSON 的 MessagePack 作为序列化格式。具体协议是如何设计的请见《如何设计 RQData 通讯协议》。

说一说协议生成器 - Ricequant米筐量化相关推荐

  1. python海龟代码大全_海龟交易系统的Python完全版 | RiceQuant米筐量化社区 交易策略论坛...

    @zhaoyang-chen 海龟的Python版出炉. 为方便对比,这里把java.python两种语言代码同时贴出,回测时间及初始资金均使用页面默认的20140104-20150104,10000 ...

  2. 米筐量化提供的数据质量怎么样?

    Quant友们,大家好,最近不少B站粉丝私信问数据获取的问题.毕竟从事量化就得和数据打交道,有大量完整稳定的数据来源能帮助大大提高策略开发效率,是吧! 所以,给大家整理了以下好用又常见的数据获取平台, ...

  3. 米筐量化如何安装使用?

    米筐量化如何进行安装使用呢?其实这是个比较简单的过程,用户不需要使用者用pip install,虽然米筐也可以pip install,但是不是必需的.注册账户,打开编译器: rq.get_price( ...

  4. 怎么利用米筐量化测试实盘数据?

    怎么利用米筐量化测试实盘数据? 第一步,先用股票交易接口米筐量化 第二步:用米筐量化查询各类交易数据 以上就是关于怎么样利用利用米筐量化测试实盘数据的方式,如果大家还想了解更多可以在这里看MetaTr ...

  5. 分享米筐量化的使用方法

    米筐量化都是量化金融分析经常会用到的数据提供平台,今天主要是来讲一下关于米筐量化的使用方法: 基本操作: 在这里把tushare和rqdatac是import为ts和rq,这import as会对之后 ...

  6. 米筐量化不支持c语言_量化 | 从零开始学量化(三):数据获取途径

    本系列的前两篇都是一些笼统的介绍,供小白制定学习计划时参考,现在该铺垫的都铺垫的差不多了.循序渐进,从本篇开始会写一些能实操的内容,尽量写的很细节,有任何问题欢迎私戳. 本篇给出一些数据获取途径,基本 ...

  7. 米筐量化不支持c语言_从零开始学量化(三):数据获取途径

    本系列的前两篇都是一些笼统的介绍,供小白制定学习计划时参考,现在该铺垫的都铺垫的差不多了.循序渐进,从本篇开始会写一些能实操的内容,尽量写的很细节,有任何问题欢迎私戳. 本篇给出一些数据获取途径,基本 ...

  8. 米筐量化不支持c语言_AQ答疑:三分钟入门量化投资

    答疑丨量化投资三分钟入门(一) 量化投资在国外的发展已经有很长时间的历史,虽然国内市场目前仍处于初起阶段,但是因其投资业绩稳定,市场规模和份额不断扩大,得到了越来越多投资人的认可,各个大型券商也在发展 ...

  9. 米筐量化不支持c语言_量化初级之量化选股

    前言 所谓量化交易,个人理解,就是将投资理念,仓位管理等定量的表达出来,之后通过代码的方式,通过 程序去代替人去实现交易.相比主观交易,量化交易的有点很多,譬如,可以避免投资者因为心理因素 而导致错误 ...

  10. 知不知道什么叫米筐量化?怎么来的?

    现在量化市场范围越来越大,各种量化系统也是普遍性的了,不过米匡量化这个开发系统通常是由交易接口的专业开发团队开发的的结果,那么米匡量化的终端又是是怎么开发成功的呢? 首先,我们可以从api接口的调用来 ...

最新文章

  1. centos7 virtualbox使用internal network 内网模式
  2. 北大成功研发 “忘情水” ,可精准删除特定记忆,有望今年进行人体测试
  3. 一维循环数组最大子数组求解
  4. 打不开mysql exe文件怎么打开文件_exe文件打不开怎么办?
  5. 数据结构和算法系列13 五大查找之哈希查找
  6. can接收进入两次中断_STM32的CAN2口无法进入接收中断
  7. gcc/g++ 编译、链接与常用命令工具(1)
  8. HttpServlet请求重定向
  9. selenium下载安装
  10. int转byte数组以及相关原理
  11. 程序员不要轻易去上海
  12. 震惊!这浏览器居然进过全球 Top10
  13. 一文理解所有需求分析中的基本术语
  14. MySQL及同类产品的技术调研报告
  15. el-table 表格内容多一根线的解决办法
  16. 2023西湖论剑wirteup
  17. “燕云十六将”之Lion李哲
  18. 一文告诉你胜任力模型对企业有多重要
  19. 工具类App原型制作分享-Explain Everything
  20. 达梦DM数据库网页数据维护工具

热门文章

  1. gridview 排序
  2. activesync同步问题
  3. 高数 | 【微分方程】技巧性例题 及 李林880详解
  4. 所用计算机网卡品牌得的型号,惠普无线网卡驱动,详细教您如何
  5. 漏洞补丁在线更新失败或软件安装提示ERROR的解决方案
  6. system.gc()和-XX:+DisableExplicitGC启动参数,以及DirectByteBuffer的内存释放
  7. VMware系列序列号
  8. 如何把播放器转换成HTML5,Chrome把普通flash播放器转变成HTML5播放器插件:HTML5ify...
  9. 哆啦A梦版主题餐厅手游《机器猫烧烤店BBQ》
  10. [附源码]计算机毕业设计JAVAJAVA大方汽车租赁管理系统