基准RPC系统(和Inverted Json)


比较用于在微服务之间组织RPC的各种工具(RabbitMQ,Crossbar.io,Nats.io,Nginx等)。

内存使用量


CPU使用率


多处理器测试



文章更新于2019-12-15

总结 通过经典的MQ系统实现同步RPC调用是无效的-降低了性能,并降低了需要手动解决(或使用其他工具)的副作用。
Inverted Json是轻型任务服务器,允许您进行“诚实的”同步RPC调用(客户端和服务器通过Inverted Json连接以发送信息),从而确保了高性能(比RabbitMQ快7倍),并且可以通过http进行通信,它使您可以使用任何http工具,甚至可以从控制台卷曲。

1.测试


所有工具分为3组:
  • “直接连接” -当客户端直接与工作人员联系时,在具有大量工作人员/服务的项目中,配置起来最困难,它需要一个“智能客户端”,即 进行呼叫时,客户端应了解有关如何以及在何处发送请求的信息(或需要其他本地代理),通常它在网络上产生的负载最少。
  • “代理连接” -一种具有单个入口点的变体,一个简单的客户端,但同时在工作人员/序列号方面仍然存在困难-转发和分配端口,为代理注册地址,更复杂的防火墙设置,经常使用其他工具来管理整个服务器场。
  • “反向连接” -客户和工作人员的单个入口(可以视为ESB),这是最简单的网络设置。
  • 取自docker stats的内存和处理器使用率
  • 在“ 2核”测试中,服务器和带有断路器的客户端被划分为不同的核,以减少彼此之间的影响,因此,通过任务集将服务器限制为2个核(无限制的多核测试)
关于以下基准的一些想法。

2. MQ或RPC


尽管这两种通信方法不同,但有时会使用第一种而不是第二种,反之亦然。
如果您试图勾勒出边界,何时使用什么,您将获得如下信息:
  • RPC (同步过程调用)-当客户端立即(在短时间内)要求响应时,当工作人员需要在客户端等待响应时进行回答,并且如果客户端离开(由于超时),则不再需要此答案(这就是为什么您不需要保存“请求”,这在MQ系统中通常是这样)。
    例如,当您在数据库中进行查询时(执行RPC),您将不想为此使用MQ。
  • MQ (异步过程调用)-当不需要答案(立即),仅需最终完成某种任务或仅传输数据时。
    例如,要发送信件,您可以通过MQ发送任务

3.通过RabbitMQ进行RPC


RabbitMQ通常用于组织RPC,但与类似的MQ系统一样,它也会产生额外的开销,这就是为什么其使用效率不高的原因。

如果对RPC使用“队列”,则需要清除通道,因为 如果工作人员倒下了一段时间,那么重新启动后,它可能会执行一系列无关的任务,因为客户端一直都在发送请求,并且徒劳地等待答案。 该工人不活跃。 总体而言,即使客户端之前离开客户端,工作人员也将收到任务,与客户端相同,如果不计算客户端的渠道,那么他可能会因为未收到工作人员的答复而被阻塞,尽管在RabbitMQ中可以关闭客户端通道,但同时性能将大大降低。

您还需要让一名猪肉工人知道他是否还活着。
另外,当在RPC系统中将数据简单地发送给工作程序时,资源会花费在处理通道上,反之亦然。

4.倒Json


MQ有很多不同的系统,但是诸如Gearman / Crossbar.io之类的作业服务器(RPC)并不是很多选择,因此开发人员经常将MQ系统用于RPC。
因此,创建了反向JSON (iJson)-具有http接口的代理服务器,客户端和工作人员通过该接口作为网络客户端进行连接:[client]-> [Inverted Json] <-[worker],用C / C ++编写,使用epoll,状态机用于路由,JSON流解析器,切片而不是字符串*等,以提高性能。

相对于RabbitMQ,反向JSON的优势:
  • 无需清除未收到的消息中的客户和工作人员通道
  • 不需要ping工作者,如果工作者断开连接(使用keepalive连接),客户端将立即收到错误。
  • 更加简单的api-仅是一个http请求(通常,所有语言和框架都已支持该请求)
  • 工作更快,消耗更少的内存
  • 一种将命令发送给特定工作人员的简便方法(例如,如果队列中有多个工作人员,但是您需要使用一个特定的工作人员)

其他倒Json信息
  • 传输二进制数据的能力(顾名思义,不仅仅是json)
  • 如果将工作程序连接为保持活动状态,则无需指定id。InvertedJson只是直接将客户端和工作程序连接。
  • “订阅”多个命令(通道),订阅模式(例如命令/ *)而不会损失性能的能力。
  • Docker映像仅2.6 MB (精简版)
  • 内核反向Json仅约1400行代码(v0.3),更少的代码-更少的错误;)
  • 反向JSON不会修改请求正文(正文),而是按原样发送。


5. 3分钟内尝试反转Json


如果您具有Dockercurl,可以立即尝试Inverted Json:


图片说明:
1)在端口8001上启动Inverted Json的docker映像,--log 47记录传入的请求等:
$ docker run -it -p 8001:8001 lega911/ijson --log 47 

2)注册工作者以执行“计算/求和”任务,然后等待任务,要求输入“获取”,即 -获取任务:
 $ curl localhost/calc/sum -H 'type: get' 

3)客户端发出RPC calc / sum请求:
 $ curl localhost/calc/sum -d '{"id": 15, "data": "2+3"}' 

4)工作者接收任务`{“ id”:15,“ data”:“ 2 + 3”}`-数据未更改,现在您需要将结果发送到相同的id,请求类型为“结果”:
 $ curl localhost -H 'type: result' -d '{"id": 15, "result": 5}' 

...,客户端将得到结果,因为它是`{"id": 15, "result": 5}`

5.1。 杰森


不支持JsonRPC 2,但是有一些基础,例如,客户端可以发送(url / rpc / call)之类的请求:
 {"jsonrpc": "2.0", "method": "calc/sum", "params": [42, 23], "id": 1} 
接受如下错误:
 {"jsonrpc": "2.0", "error": {"code": -32601, "message": "Method not found"}, "id": null} 
但是,如果有需求,则可以改善对JsonRPC的支持。

5.2。 Python客户端和工作程序示例


 # client.py import requests print(requests.post('http://127.0.0.1:8001/test/command', json={'id': 1, 'params': 'Hello'}).json()) # worker.py import requests while True: req = requests.post('http://127.0.0.1:8001/test/command', headers={'type': 'get'}).json() response = { 'id': req['id'], 'result': req['params'] + ' world!' } requests.post('http://127.0.0.1:8001/', json=response, headers={'type': 'result'}) 

在这里,您可以找到“工作模式”下的示例,该示例更加高效和紧凑。

6.对基准测试结果的一些思考


  • Crossbar.io :基于python,所以它不是那么快,并且由于GIL而不能使用多个内核。
  • RabbitMQ :MQ之上的RPC,这会带来额外的开销。 性能随着负载的增加而迅速下降(未反映在测试中)。
  • Nats :虽然不如Inverted Json, 基于MQ的RPC也将具有相同的问题。
  • Inverted Json :达到网络限制(即在不同内核上启动多份测试副本不会总带来更好的结果),显示出相对于性能而言,最有效地使用内存和处理器。
  • Nginx :当通过代理时,如果未启用保持活动模式(默认情况下关闭),性能会迅速下降,这是因为Linux不允许在短时间内打开/关闭许多套接字(这在测试中没有体现)。
  • Traefik :非常贪婪,在峰值时使用了600%的CPU,速度不如Nginx
  • uvloop (在asyncio下)-提供非常好的性能,因为 大多数用C / C ++编写,因为RPC比ZeroMQ更可取
  • ZeroMQ -worker本身是用Python编写的,因此尽管多处理器测试消耗了100%以上的CPU,但它还是跑进了内核,这是由于zeromq本身是用C / C ++编写的,没有捕获GIL。 它提供了出色的性能,但是,另一方面,如果worker不只是a + b,那么任何复杂化都会导致RPC的显着减少,因为 将更早达到核心。
  • ZeroRPC :被声明为ZeroMQ的轻量级包装,实际上,ZeroMQ的性能损失了95%,似乎并不是那么轻巧。
  • GRPC :python的选项会产生很多样板的python代码,即 事实证明,处理器很重,很快就靠在CPU上,对于编译后的语言来说,可能没有这种问题。
  • 2核和多核测试,在多核中某些指标有所下降,因为您必须与客户端测试代码争夺CPU资源,另一方面,某些测试则提供了出色的性能,例如Traefik占用了600%的CPU


7.结论


如果您的公司规模较大且员工众多,那么您可以允许自己支持各种复杂的工具来组织微服务之间的直接连接,从而可以提供有效的通信。
对于需要小型团队来解决各个领域问题的小型公司和初创公司,Inverted Json可以节省时间和资源。

对于Inverted Json的开发,计划包括对pubsub,kubernetes和其他有趣想法的支持。
如果您对该项目感兴趣或只想帮助作者,则可以在github项目上加一个星号,谢谢。

PS:


  • 与创建Inverted Json本身相比,创建包含测试的本文花了更多时间
  • 倒置的Json原型也是用1. python + asyncio + uvloop,2.用GoLang编写的。
  • 测试由不同的专家进行审查。
  • “切片而不是字符串”-在大多数情况下,在解析http / json时,数据不会复制到字符串中,但是会使用到源数据的链接,因此,不会进行额外的分配和内存复制。
  • 如果您要测试-不要在python中使用请求,它会非常慢,比pycurl更好, 该包装器可用于测试中。
  • 基准在这里
  • 来源在这里

Source: https://habr.com/ru/post/zh-CN466263/


All Articles