内容简介:本文主要介绍了gRPC,网络现状及测试的简介,好不好用等相关内容。gRPC是谷歌开源的一款不那么快的基于原型缓冲区的RPC框架。既然不那么快,为什么还要提它呢?相较于节俭,gRPC会慢一点,但是,本文的着眼点并不在于RPC吞吐量的极限值,也不是框架的通信时间减少几十几千纳秒,本文要介绍的是除GraphQL外,JSON RPC优化的另一个取向--gRPCweb。
本文主要介绍了gRPC,网络现状及测试的简介,好不好用等相关内容。
gRPC是什么?
gRPC是谷歌开源的一款不那么快的基于原型缓冲区的RPC框架。
既然不那么快,为什么还要提它呢?相较于节俭,gRPC会慢一点,但是,本文的着眼点并不在于RPC吞吐量的极限值,也不是框架的通信时间减少几十几千纳秒,本文要介绍的是除GraphQL外,JSON RPC优化的另一个取向--gRPCweb。
众所周知,GraphQL着眼的优化点在于通过移交一部分查询的逻辑到客户端,从而减少了数据的交换量,而RPC则着眼于使用可压缩的二进制/文本协议,减少JSON文本传输带来的不必要的协议损失。本文着眼于此,对比gRPCweb当前的进展,对易用性,便捷性,成本方面进行了评价,结论虽然有些武断,但是仍然反映了当前gRPCweb仍然有待进一步发展的事实。
01gRPC web能给我们带来什么?
1. 传输数据量减少,传输延迟降低
HTTP / 2天生具有头压缩等特性,解决了大量频繁的RPC交互通信带来的头部重复传输问题;使用二进制流或压缩文本传输,减少了一部分稀疏编码带来的字节空洞,提高了信息密度。传输速度更快,数据量更小,不仅降低成本,而且可以减少延迟。
2.可靠一致的API设计
客户端服务端使用相同的原文件进行接口定义,双方接口暴露完全相同,一致性更强,相较于传统的招摇接口管理,其数据结构更加直观精确,不再需要维护接口-URL间的复杂对应关系,API升级管理更加简单
3.对传输基础设施无感知的通信协议
节俭不能推出类似gRPCweb的方案的原因也正在于此.Thrift使用私有Tprotocol传输协议,与gRPC的HTTP / 2相比起来通用性大打折扣,Nginx的在最新的稳定版中已经提供了grpc_pass负载均衡支持,我们可以无痛使用原有的四层/七层负载均衡器提供大规模的调用支持
4.高效的序列化/反序列化支持
gRPC相较于JSON,拥有更高的序列化/反序列化效率,易于实现更高的吞吐性能
02
gRPC web能不能用?好不好用?
话不多说,接下来我们就开始进行一套gRPCserver + envoy代理+ gRPCweb on TypeScript的echo通信测试,作为对比,笔者将实现一套同样功能的websocket链路,用以测试双方通信性能,比较这些功能的实现难度并评价两种“看似比较底层”的网络通讯协议。
gRPC网站测试
首先定义一个我们的回声服务的原型:
syntax = "proto3";package chatman; message ChatRequest { string messages = 1; } message ChatResponse { string messages = 1; } service Chat { rpc chat (ChatRequest) returns (ChatResponse); }复制代码
然后写服务器端代码,此处使用的 Python 的实现:
生成服务器端的protobuf的的文件,使用gRPC工具生成代码即可,然后我们引入grpcio和这些的protobuf的库文件:
import grpcimport service_pb2,service_pb2_grpc from concurrent.futures import ThreadPoolExecutorimport time class ChatServicer(service_pb2_grpc.ChatServicer): def chat(self,request,context): print(request.messages) return service_pb2.ChatResponse(messages="Server Received: %s" % request.messages)def server_start(): server = grpc.server(ThreadPoolExecutor(max_workers=5)) service_pb2_grpc.add_ChatServicer_to_server(ChatServicer(),server) server.add_insecure_port('0.0.0.0:8800') server.start() time.sleep(3600*24)if __name__ == '__main__': server_start()复制代码
我们先测试下HTTP / 2二进制流模式的gRPC:
Python中的代码如下:
import grpcimport service_pb2_grpcimport service_pb2 channel = grpc.insecure_channel('0.0.0.0:8800') stub = service_pb2_grpc.ChatStub(channel) message = service_pb2.ChatRequest(messages="test message") msg = stub.chat(message) print(msg)复制代码
返回消息:“Server Received:test message”。测试成功,抓包结果如下:
可以看到,两方使用“不安全“的HTTP协议交换了数据,通信成功完成。
接下来,我们使用gRPC的网络实现相同功能。值得注意的一点是,目前gRPC幅还不能直接运行在浏览器上,因为浏览器尚未提供裸HTTP协议的接口,因此需要进行一层简单的封装,并通过代理剥去这层封装才能与真正的gRPC后端通信,这种通信方式被称为gRPC的网页文本。
同理,使用gRPC的 工具 生成打字稿文件,生成文件包含一个原始的JS库,一个描述文件以及一个TS客户端库,编写代码:
import { ChatRequest,ChatResponse } from './service_pb'import { ChatClient } from './ServiceServiceClientPb'const client1 = new ChatClient("http://127.0.0.1:8001",{},{}); let req = new ChatRequest() req.setMessages("messages") client1.chat(req,{},(err: any, res)=>{ console.log(res); });复制代码
在HTML中直接引用这个JS,并使用特使代理进行gRPC的网页文本到gRPC协议的转换,配置如下:
admin: access_log_path: /tmp/admin_access.log address: socket_address: { address: 127.0.0.1, port_value: 9901 } static_resources: listeners: - name: listener_0 address: socket_address: { address: 127.0.0.1, port_value: 8080 } filter_chains: - filters: - name: envoy.http_connection_manager config: codec_type: auto stat_prefix: ingress_http route_config: name: local_route virtual_hosts: - name: local_service domains: ["*"] routes: - match: { prefix: "/" } route: cluster: echo_service max_grpc_timeout: 0s cors: allow_origin: - "*" allow_methods: GET, PUT, DELETE, POST, OPTIONS allow_headers: keep-alive,user-agent,cache-control,content-type,content-transfer-encoding,custom-header-1,x-accept-content-transfer-encoding,x-accept-response-streaming,x-user-agent,x-grpc-web,grpc-timeout max_age: "1728000" expose_headers: custom-header-1,grpc-status,grpc-message enabled: true http_filters: - name: envoy.grpc_web - name: envoy.cors - name: envoy.router clusters: - name: echo_service connect_timeout: 0.25s type: logical_dns http2_protocol_options: {} lb_policy: round_robin hosts: [{ socket_address: { address: 127.0.0.1, port_value: 8800 }}]复制代码
现在进行测试,访问刚才的网页,可以看到通信情况:
一看就知道是的的base64编码,果断解码:
果然不出所料,是一个封装在HTTP里的HTTP通讯
Web Socket的测试
接下来,使用的WebSocket的进行对比:
编写服务端程序:
console.log("Server started"); var Msg = ''; var WebSocketServer = require('ws').Server , wss = new WebSocketServer({port: 8010}); wss.on('connection', function(ws) { ws.on('message', function(message) { console.log('Received: %s', message); ws.send('Server received: ' + message); }); });复制代码
使用节点启动后,在浏览器的控制台里连接并访问:
const ws_echo = new WebSocket("ws://127.0.0.1:8081/") ws_echo.addEventListener('message', (event) => { console.log(event.data); }) ws_echo.send("Hello!")复制代码
控制台返回服务器收到:您好!
通信完成,查看协议:
可以看到,经过一次通信后,服务器直接返回升级升级连接的报头,随后双方使用的WebSocket的进行通信,比起gRPC的协议,更加简易直白。
结论
在测试前我一直在思考,gRPCweb究竟是一个怎样的存在第一眼看到gRPCweb文本这个词,我的第一感觉是这个?
在Gmail中的邮箱里,充满了这种极其类似的的protobuf的XHR请求,当看到需要使用专用代理进行转发的时候,我一度以为是这种高度压缩的文本协议正式出现在了通用的框架里,然而事实是,不论是gRPC-web还是gRPCweb-text,不论是易用性还是请求响应体长度,比起jon over brotli over websocket都仍然有很大的进步空间,要实现通过CDN分发js节省API服务器带宽的构思目前仍然需要自己造轮子,gRPCweb并不是银弹,至少目前不是。
本文首发于公众号”小米运维“,点击查看原文。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
CSS权威指南(第三版·英文影印版)
[美] Eric A.Meyer / 东南大学出版社 / 2007-06 / 68.00元
著名的CSS专家Eric A.Meyer他招牌式的智慧和无与伦比的经验引领读者探索了CSS的各个部 分,包括属性、标记、特性和实现。此外,他还就现实应用中的一些问题,例如浏览器的支持和设计方针,发表了看法。你所要知道的就是HTML 4.0的知识,这样就可以创建整洁、易于维护的脚本,以与桌面出版系统同样的优雅和控制能力管理网站布局和分页。你将会学到: 精妙地设计文本风格 用户界面、......一起来看看 《CSS权威指南(第三版·英文影印版)》 这本书的介绍吧!