gRPC-Web是一个JavaScript客户机库,它允许web应用程序使用Envoy来与后端gRPC服务交互,而不是使用自定义HTTP服务器作为中介。上周,经过近两年的积极开发,gRPC团队在CNCF博客上宣布了gRPC-Web的GA发布。
就我个人而言,自从我第一次在 Improbable engineering的博客上看到gRPC-Web之后,我就对它产生了浓厚的兴趣。我一直很喜欢gRPC的性能、可伸缩性和服务交互的IDL驱动方法,并且渴望一种尽可能从服务路径中消除REST的方法。我很高兴地看到gRPC-Web已经准备就绪,因为我认为它为web开发打开了一些极具前景的领域。
在我看来,gRPC- Web的美妙之处在于,它使你能够从web客户机一直到下创建完整的端到端gRPC服务体系结构。以前,如果你希望将一个gRPC驱动的后端与web客户端结合使用,那么你需要编写REST API逻辑来将HTTP调用转换到gRPC上或从gRPC上进行转换——如果可能的话,我们大多数人都很乐意避免这种工作。gRPC-Web允许你使用Protocol Buffers封装所有数据接口,从而使你不必编写另一个HTTP服务器(是在令人难以置信的Envoy帮助下,我将进一步解释)。
gRPC- web的美妙之处在于,它使你能够从web客户机一直创建完整的端到端gRPC服务体系结构。这使你无需编写另一个HTTP服务器,因为它允许你使用Protocol Buffers封装所有的数据接口(在Envoy的关键帮助下)。
REST的方式
下图展示了两种构建基于gRPC的服务体系结构的web应用程序的方法。在左侧面板中,你将看到基于REST的“传统”方式,而在右侧面板中,你将看到gRPC-Web方式。
REST API与gRPC-Web中的客户机-后端交互
在左侧面板中,你将注意到REST API服务器充当web应用程序和后端之间的联系人。在很多情况下,REST服务器只是将HTTP从客户端调用转换为gRPC到后端服务的调用。
让我们来看一个示例:客户端希望通过将JSON发送到HTTP服务器的/auth端点来使用gRPC后端服务器进行身份验证。HTTP服务器将POST请求转换为AuthRequest的Protobuf消息,将该消息发送到后端gRPC auth服务器,最后将auth服务器的AuthResponse消息转换为web客户机的JSON负载。正如我在为CNCF博客写的博文中所述,这种方法本身并没有什么问题。这是一个很好的模式,很多开发人员都很成功地使用了这种模式;如果它对你有用,就留着吧。
但让我们面对现实吧:如果web客户端能够删除HTTP中介并直接将请求发送到后端(想象一下JavaScript auth客户端发送AuthRequest消息并返回AuthResponse消息),那么将节省大量工作。这意味着不需要HTTP状态码,不需要JSON SerDe,也不需要HTTP服务器本身的部署和管理负担。
在右边的面板中,你可以看到新的gRPC-Web替代方案。你将注意到:拼图的碎片更少了,一个协议(绿色的行!),没有HTTP逻辑,所有数据接口都使用.proto文件定义。客户端向gRPC后端发送一个Protobuf消息,返回一个Protobuf消息。
为了得到这个好处,还有一件事你需要做好…
Envoy的角色
坦白说:我撒了点小谎。前面我说过,使用gRPC- Web客户端可以“直接”对后端服务进行gRPC调用。这并不完全正确。对于gRPC-Web,客户端调用仍然需要转换为对gRPC友好的调用,但是这个角色现在由Envoy来填补,Envoy具有对gRPC-Web的内置支持,并作为其默认的服务网关。
下图给出了特使适用于gRPC-Web图片的基本图片。在这里,web应用程序与后端gRPC服务交互,后端gRPC服务依赖于另外两个gRPC服务。Envoy将客户端产生的HTTP/1.1调用转换为可以由这些服务处理的HTTP/2调用(gRPC使用HTTP/2进行传输)。HTTP仍然在幕后运行,但是客户机和服务器都不需要考虑HTTP术语。
Envoy在gRPC-Web应用程序中的角色
gRPC-Web是一个巨大的胜利,因为你不需要创建那个翻译层——你只需要为Envoy提供一些基本的配置。
对于gRPC-Web,客户端调用仍然需要转换为对gRPC友好的调用,但是这个角色现在由Envoy来填补,Envoy具有对gRPC-Web的内置支持,并作为其默认的服务网关。
Envoy配置例子
下面是一个用于Envoy代理的YAML配置示例,该代理侦听端口8080上的HTTP客户机连接,然后将这些请求代理给后端gRPC服务。
static_resources:
listeners:
- name: listener_0
address:
socket_address: { address: 0.0.0.0, 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: auth_service
cors:
allow_origin:
- "*"
allow_methods: GET, PUT, DELETE, POST, OPTIONS
allow_headers: keep-alive,user-agent,cache-control,content-type,content-transfer-encoding,x-accept-content-transfer-encoding,x-accept-response-streaming,x-user-agent,x-grpc-web
max_age: "1728000"
expose_headers: grpc-status,grpc-message
enabled: true
http_filters:
- name: envoy.grpc_web
- name: envoy.cors
- name: envoy.router
clusters:
- name: auth_service
connect_timeout: 0.25s
type: logical_dns
http2_protocol_options: {}
lb_policy: round_robin
hosts:
socket_address:
address: auth-server
port_value: 9090
一般来说,这是特使使用的非常标准的HTTP配置。只有几个小小的区别:
你只是将自己从围绕开发HTTP服务器的所有常见的繁琐程序中拯救出来,所需要的只是一个小YAML。不需要将HTTP谓词映射到API操作,不需要询问StackOverflow哪个HTTP状态代码对应哪个服务器状态,不需要将JSON转换为Protobuf消息。
一条新的道路
gRPC- Web和Envoy提供了一种非常引人注目的web开发新方法,它提供了Protocol Buffers和gRPC的类型安全性,并规避了HTTP和REST的许多缺陷,这些缺陷我们都非常熟悉。我鼓励——不乞求——你在下一个项目中尝试一下。