正常项目中,对外提供的接口都是HTTP接口,可是后端架构中,我们内部已经迭代成gRPC版本了。这样还得做一层抽象HTTP层去调用server端的GRPC,在项目中,能免去这个HTTP层吗?

答案是可以的,使用网关,通过网关层做掉HTTP转GRPC的协议这层,这样就可以尽量让后端都提供出grpc了。

网关的选择有很多种,这里选型有,apisix、kong以及envoy,前两者是lua+openresty,后者是C++,考虑到维护性(C++的水太深,我把握不住),故直接选择前两者。

对比

详细的对比结果没啥意义,各个公司都有自己的考量,我就不放了。

相比较于grpc的支持,apisix只能说不太行,首先dashboard(社区版)的支持就没做好,管理proto文件不方便,得通过API导入,且不支持proto文件依赖。

kong可以,所以我选择kong。

至于其他方面的对比,或者说部署上,我还是偏向于apisix的,因为它是依托于etcd完成的整体构建,比kong使用DB+轮询的方式,配置下发响应,以及维护难度上,还是领先不少的。

kong的使用

搭建的过程直接使用docker-compose一键搭建。(只作为验证)

https://gist.github.com/adib-enc/d82415128cdb6d313e54d5b606e8c1ab

KONG中有两个针对GRPC的插件,GRPC-web和GRPC-Gateway,

GRPC-web插件不需要proto文件做额外的注解。

proto file

访问接口,则需要使用POST Method,数据通过JSON传输。

GRPC-Gateway 使用GRPC所带的注解,可以使用不同Restful的方法,是理想的状态。

带annotations.proto的proto

引入annotations.proto文件,其protobuf所扩展的HTTP Option,在proto文件中对函数转换HTTP提供支持,protoc工具在编译时,会把HTTP相关信息一并写入.pb.go文件。

问题

现阶段两者都有个问题:

proto文件更新;proto文件被加载过一次后,KONG在map中若找到此文件,则不会去解析文件,只会从缓存中拿取。

https://github.com/Kong/kong/blob/master/kong/plugins/grpc-gateway/deco.lua

解析proto file

解决问题的方法

  • 单点上要引入一个手动触发更新的trigger,让插件重新读取一次数据。

  • 分布式多体的场景,则需要引入Redis了,由于不是etcd,所以kong只能借助到共享内存来完成。proto file保存到某一节点即可,但此节点承担起了预备数据的责任。

参考资料

kong的很多方面其实很多博客都讲解的非常详尽了,我其实也是搜集了很多放在OneNote上,这里我就不截取内容了,把链接丢在这里。

Kong中使用grpc-web插件代理grpc服务时遇到的坑

来自 https://www.jianshu.com/p/0a7e3a8fa8a0

Kong 插件开发指南

来自 https://ms2008.github.io/2018/06/19/kong-plugin-development/

kong – 如何编写插件

来自 <https://yuerblog.cc/2019/12/18/kong-%E5%A6%82%E4%BD%95%E7%BC%96%E5%86%99%E6%8F%92%E4%BB%B6/>

云原生网关 Kong 源码分析

来自 <https://cloudnative.to/blog/kong-source-code-reading/#1-%E6%A6%82%E8%BF%B0>

分布式系统的负载均衡来自 https://z.itpub.net/article/detail/9B74CCC9C2F14E3BEA5E548C63B16315

插件使用https://tech.aufomm.com/tags/kong-plugin/