当前位置: 首页 > Web前端 > CSS

凯克拉dubbo-go微服务升级实践

时间:2023-03-31 00:20:38 CSS

介绍:杭州凯克拉教育科技有限公司是一家致力于为中小学生提供学习指导的在线教育公司。目前公司后端服务基础设施主要依托阿里云原生。它包括计算、网络、存储和Kubernetes服务。技术选型背景2020年是公司发展壮大的一年。整个公司团队从几百人发展到现在的几千人。基本上在密集使用的时候会有几千人同时在后台操作。运营方面,公司原有的内部后台操作系统是用PHP搭建的,其性能和业务已经不能满足公司的需求规划。另外,公司开发部门拆分了微服务,主要对外服务为java语言的Dubbo集群,后台系统需要与java的Dubbo服务无缝对接,所以PHP逐渐不能满足需求公司。当时还研究了PHP的Dubbo项目。由于项目基本没人更新维护,所以我通过了。后来对简单高性能的go语言感兴趣,才关注到dubbo-go这个项目。经过一段时间的调研,发现DubboGo符合我们的业务需求,社区也很活跃,所以我们决定使用Dubbo-go作为后台PC业务框架。可能还有同学会问为什么不使用跨语言支持更好的gRPC,因为很多公司最初的RPC服务集群都是基于Dubbo生态搭建的。如果改框架的成本太高,他们基本不会考虑。虽然gRPC跨语言支持比较好,但是很多东西需要自己搭建,比如服务注册、服务发现、日志监控等。当时在决定Dubbo-go选择Dubbo-go的时候,有开发团队内部有一些反对的声音。为什么不直接切换到java?如果换成java,就不会有跨语言交流的问题了。转java的问题是入门成本高,而且对于整个公司的技术栈而言,只有保持语言的多样性,才能更从容地应对未来的业务变化。Go本身是一门不弱于Java的高性能语言,非常适合微服务架构。面临的挑战确定框架选型后,接到的第一个任务是搭建一套可以快速创建业务项目的脚手架,开发一个基于HTTP协议的RPC代理服务,部署到接入公司容器化部署的平台,一切从零开始,网上基本没有可以参考的资料。首先是规划Dubbo-go项目的结构,确定项目目录结构。参考了Dubbo-goDemo等Go项目,最终确定了项目目录结构。下面的目录结构可以作为参考。为了与Java服务注册中心保持一致,Dubbo-go在项目选择中选择了以下组件:使用zookeeper作为注册中心nacos作为配置中心数据库orm使用gorm消息队列,使用RocketMQ提高开发效率,在provider服务初始化之前,我们可以简化配置,只保留最基本的配置,可以类似下面这样。provider服务的编码参考Dubbo-godemo。以下是服务启动的主要方法代码:Dubbo-goRPC服务网关设计一般使用Dubbo,提供方需要暴露接口和方法,消费方需要非常清楚所使用的接口定义和方法定义通过服务,以及输入和返回参数的类型等信息,还需要使用提供方提供的API,让两端可以正常通信和调用。但是网关的使用场景并不关心调用接口的详细定义。网关只关心要调用的方法、传递的参数以及接收返回结果的能力。通话功能。下面是Dubbo-go官方给出的demo。广义服务加载完成后,需要等待3秒才能完成调用。但是在实际使用中,肯定不可能实时加载服务等待3秒,所以需要在网关应用启动时加载缓存需要泛化的好服务。通过研究dubbo-go广义调用demo,发现设计一个具有该特性的dubbo-go网关是可行的。难点在于我们需要获取并缓存每个网关代理RPC服务方法和服务路径的参数。起床,让广义呼叫服务在呼叫前初始化。服务的配置如下。由于是go语言做的网关代理,无法通过javajar包获取javaRPC服务配置。如果手动维护,工作量太大,容易出错,显然是不能接受的。经过一段时间的了解,Java服务可以通过注解实现配置获取。Java端在方法上添加注解并启动服务时,会将配置信息通过消息发送给MQ,网关消费这些消息获取JavaRPC服务。配置。DubboGo的RPC服务因为go语言不支持注解,于是想了想写了一个扫码的小工具,在每个RPC服务方法前添加相应的注释,通过注释获取RPC服务的配置获取配置后,在项目目录下生成RPC服务配置,应用启动时读取配置发送给MQ。实现网关代理后,可以在网关的基础上实现更多的功能,比如token校验、白名单、限流、断路器、日志监控等功能。网关代理请求实现效果如下:容器化部署公司内部容器化部署环境是阿里云的K8s,只需要提供镜像文件即可部署到K8s平台。由于Dubbo-go编译为二进制文件,不需要任何额外的第三方库,可以在Docker环境中稳定运行。有如下图所示的docker镜像文件,任何Linux发行版如centos都可以作为基础镜像。LABELmaintainer=""LABELversion="1.0"LABELdescription="KKL-GO-NKO-BASE"`ARGenvType=stable#设置环境变量ENVenvType${envType}#编译打包压缩packageADD./target/nko-base-${envType}.tar.gz/app/WORKDIR/appEXPOSE20000镜像写入后提供给发布平台,发布平台机器启动镜像并解压打包文件,并执行Dubbo-Go程序。由于开发测试到production一般有多个部署环境,所以我们需要修改dubbo-gosamplesdemo中的编译脚本,支持多环境打包。另外,dubbo-go默认注册的IP是K8spod的虚拟IP,不同K8s集群之间的网络无法互通,所以如果需要跨集群调用,需要修改默认注册IP,并将默认注册的podIP+端口改为Kubernetes物理机的IP加上对应的端口,Kubernetes会在pod中写入物理机的IP和对应的端口环境变量,应用程序可以获取到IP和通过读取环境变量获取物理机的端口。如果需要实现这个功能,需要修改Dubbo-go的注册逻辑。比如以zookeeper注册中心为例,我们可以通过扩展register/zookeeper/registry.go的registerTempZookeeperNode方法修改注册的IP和端口。代码如下图所示。Dubbo-go将在后续版本中正式支持以配置的形式进行自定义注册IP和端口的功能。func(r*zkRegistry)registerTempZookeeperNode(rootstring,nodestring)error{...regIp=os.Getenv(constant2.RegistryEnvIP)//物理机的ipregPort=os.Getenv(constant2.RegistryEnvPort)//物理机端口urlNode,_:=common.NewURL(node)role,_:=strconv.Atoi(urlNode.GetParam(constant.ROLE_KEY,""))ifrole==common.PROVIDER&®Ip!=""&®Port!=""{urlNode.Ip=regIpurlNode.Port=regPortnode=url.QueryEscape(urlNode.String())}zkPath,err=r.client.RegisterTemp(root,node)...}作者:曾凡伟,一名一线程序员,拥有9年服务端业务开发经验。曾在腾讯阅读等公司担任后端开发工程师。目前就职于杭州凯克拉教育科技有限公司,从事Go语言服务基础设施、中间件和部分业务开发工作。原文链接本文为阿里云原创内容,未经允许不得转载