apache / brpc

brpc is an Industrial-grade RPC framework using C++ Language, which is often used in high performance system such as Search, Storage, Machine learning, Advertisement, Recommendation etc. "brpc" means "better RPC".
https://brpc.apache.org
Apache License 2.0
16.41k stars 3.96k forks source link

support https alpn #1991

Open ml-haha opened 1 year ago

ml-haha commented 1 year ago

Is your feature request related to a problem? (你需要的功能是否与某个问题有关?) http2/ssl 需要支持alpn

Describe the solution you'd like (描述你期望的解决方法) 支持client/server的alpn 功能

Describe alternatives you've considered (描述你想到的折衷方案) 可以只支持https的alpn。(或者其他协议的alpn string用protocol name?)

Additional context/screenshots (更多上下文/截图)

leaf-potato commented 1 year ago

比较好奇,rpc什么场景下需要协议版本的协商呢?发送或者接受某一方为类似nginx这样的http服务?

leaf-potato commented 1 year ago

@wwbmmm 对这个需求比较感兴趣,想尝试去实现,提PR的话社区是否会考虑合入呢

wwbmmm commented 1 year ago

@wwbmmm 对这个需求比较感兴趣,想尝试去实现,提PR的话社区是否会考虑合入呢

欢迎~

leaf-potato commented 1 year ago

@wwbmmm Client端的实现有几个问题想请教下:目前考虑的是在ChannelSSLOptions中新增ALPN的配置,在TLS协商成功后覆盖ChannelOptions.protocol字段进行后续的数据发送。

Q1:Channel.Init()方法并不会实际建立连接,这样在初始化阶段并不知道需要使用哪种协议。而在Channel.CallMethod()方法调用Socket发送数据前,函数内已经有根据protocol值的特殊逻辑处理。这样的话是否可以在在Init就进行TLS握手确定使用的协议?或者还有其他比较好的办法吗?

Q2:由于protocol是针对下游整体而言的,当下游是集群时,某个下游(ip:port)协商成功了是否就可以认为是整个集群的结果?以及后续连接断开重连(连接池)是否可以直接复用之前的协商结果?

Q3:除了普通的Channel,考虑到ParallelChannel、SelectiveChannel等其他Channel也有可能需要涉及到ALPN,是否可以将协商功能实现在ChannelBase中?

wwbmmm commented 1 year ago

@wwbmmm Client端的实现有几个问题想请教下:目前考虑的是在ChannelSSLOptions中新增ALPN的配置,在TLS协商成功后覆盖ChannelOptions.protocol字段进行后续的数据发送。

Q1:Channel.Init()方法并不会实际建立连接,这样在初始化阶段并不知道需要使用哪种协议。而在Channel.CallMethod()方法调用Socket发送数据前,函数内已经有根据protocol值的特殊逻辑处理。这样的话是否可以在在Init就进行TLS握手确定使用的协议?或者还有其他比较好的办法吗?

Q2:由于protocol是针对下游整体而言的,当下游是集群时,某个下游(ip:port)协商成功了是否就可以认为是整个集群的结果?以及后续连接断开重连(连接池)是否可以直接复用之前的协商结果?

Q3:除了普通的Channel,考虑到ParallelChannel、SelectiveChannel等其他Channel也有可能需要涉及到ALPN,是否可以将协商功能实现在ChannelBase中?

ALPN的流程对现有RPC框架的冲击较大。因为ALPN是在连接建立之后才能确定协议,而RPC是在Channel::Init确定协议,CallMethod时根据协议序列化好请求,用LB选择后端服务器,再发起与后端的连接。特别是当后端是个集群时,不同后端实例的ALPN协商结果可能是不同的,这样会让问题变得很复杂。

所以我建议,如果要在bRPC中支持ALPN协议,仅支持后端是单个ip的情况(single server模式),在这种模式下,可以在Channel::Init的时候,先向后端发起一个连接,然后根据协商结果确定协议。

ParallelChannel、SelectiveChannel没必要处理ALPN的逻辑,只要子Channel支持了就可以。

leaf-potato commented 1 year ago

@wwbmmm

特别是当后端是个集群时,不同后端实例的ALPN协商结果可能是不同的,这样会让问题变得很复杂。

是这样的,实际在考虑的时候发现集群模式实现起来比较复杂,对现有的流程有很大的改动。

所以我建议,如果要在bRPC中支持ALPN协议,仅支持后端是单个ip的情况(single server模式),在这种模式下,可以在Channel::Init的时候,先向后端发起一个连接,然后根据协商结果确定协议。

OK 那Client端暂时就先支持single server模式下的ALPN,集群模式后续有更多实际场景时再进行考虑。

Menci commented 1 year ago

如果 brpc 服务器在 Nginx 后面,在 brpc 客户端没有 ALPN 的情况下,发出去 h2:grpc 请求会直接被 Nginx 当做 h1 请求来处理,会直接 400