当前位置: 首页 > 科技观察

一个近乎完美基于Dubbo的微服务改造实践

时间:2023-03-13 19:42:17 科技观察

基于Dubbo近乎完美的微服务改造实践的快速成长离不开其技术团队的支持。微服务是电商IT架构演进的必然趋势,而网易考拉的服务架构演进也经历了从单体应用到微服务的全过程。以下内容整理自近期ApacheDubboMeetup上网易考拉陶阳的分享。通过本文,你将了解到:考拉架构演进过程考拉面向服务转型的实践考拉解决注册中心性能瓶颈考拉未来规划实践考拉架构演进过程2015年初考拉上线时,只有七个项目上线,商品详情页和购物车下单页都耦合在中间的线上项目上。单体架构刚推出的时候,这种架构还是有优势的,因为当时考拉的开发者不多,所有的功能都耦合在一个进程中,有利于集中开发、测试和上线。一种更高效、更经济的方式。但是随着业务的不断发展,包括需求的逐渐增加和开发团队的不断扩大,单体架构的一些弊端也逐渐暴露出来。比如开发效率低下:功能之间的相互耦合,不同需求的不同分支经常修改同一段代码,使得组合代码的过程非常痛苦,经常出问题。再比如上线成本高:几乎所有的发布需求都会涉及到这些应用的上线。同时,不断增长的业务需求也会让我们的代码越来越臃肿。这导致维护困难,可用性差,功能之间相互耦合,所有这些都耦合在一个过程中。这样一来,一旦某个业务需求涉及的代码或资源出现问题,就会影响到其他业务。比如我们之前在线上的项目中,因为优惠券兑换热点的问题,影响了核心的下单服务。这套架构在考拉运行的4、5个月时间里,从开发到测试再到上线,大家都非常痛苦。于是我们开始了服务拆分的工作。分布式服务架构这是考拉目前的分布式服务架构。伴随着服务的分离,我们的组织架构也进行了很多调整,比如商品中心、用户中心、订单中心。拆分其实是业务驱动的,有些横向或者纵向的拆分是通过业务来进行的。同时,拆分也会面临一个拆分粒度的问题。比如什么算作服务,或者把服务拆解的太细了,会不会导致我们的管理成本过高,或者会不会带来新的结构性问题。考拉的分裂是一个由粗到细的渐进过程。随着服务的拆分,服务架构越来越复杂,各种公共技术应运而生,如服务治理、平台配置中心、分布式事务、分布式定时任务等。考拉的服务化实践微服务框架在服务化转型中扮演着非常重要的角色,是服务化转型的基石。经过严格的技术选型,我们选择了Dubbo作为考拉服务转型的重要支柱。Dubbo可以解决服务过程中的服务定义、服务注册与发现、服务调用与路由等问题。此外,Dubbo还有一些服务治理和服务监控的功能。下面介绍考拉基于Dubbo的一些面向服务的实践。融合首先,让我们谈谈融合。服务拆分后,应用中原来的本地调用会变成远程调用,引入了更多的复杂度。比如服务A依赖服务B,在这个过程中可能会出现网络抖动、网络异常等情况。换句话说,当服务B变得不可用或难以使用时,也会影响到A的服务性能,甚至可能导致服务A占用整个线程池,导致本应用中的其他服务受到影响,从而导致更多严重的问题。雪崩效应。所以,服务之间有了这样的依赖关系之后,就要认识到服务的依赖其实是不稳定的。这时候就需要采取一些服务治理措施,比如熔断、降级、限流、隔离、超时等,保证应用不会被外部异常拖累。Dubbo提供降级功能。比如可以通过mock参数配置一些服务的失败降级或者强制降级,但是Dubbo缺少自动熔断的特性,所以我们在Dubbo上引入了Hystrix。消费者在进行服务调用时会通过熔断器。当服务提供者出现异常,比如暂时不可用时,熔断器将被打开,对消费者的调用将被短路。这个时候消费者不会再发起远程调用,而是直接进入降级逻辑。同时,消费者会继续检测服务的可用性。一旦服务恢复,熔断器将关闭,呼叫将恢复。在Dubbo的服务治理平台上,可以动态配置运行在Hystrix上的各种动态参数,包括是否允许自动熔断、是否强制熔断、熔断失败率和时间窗口等。限流先说说限流。当用户请求和调用量超过系统所能承受的并发量时,系统QPS会下降、不可用甚至宕机。这需要一种机制来保护我们的系统。当预期的并发量超过系统可以承受的范围时,它会迅速失败并直接返回以保护系统。Dubbo提供了一些基本的限流功能,比如配置信号量来限制我们消费者的调用并发,或者限制提供者的执行并发。但这些还远远不够。Koala开发了自己的限流框架NFC,基于Dubbofilter的形式,实现了对Dubbo的支持,也支持对URL等资源的限流。流控规则是通过配置中心动态获取的。Dubbo调用等资源请求,会通过流控客户端进行处理,判断是否触发限流。一旦请求超过定义的阈值,就会很快失败。同时,这些限流的结果也会上报给监控平台。上图中的页面是考拉流控平台的监控页面。我们可以为页面上的每个资源(URL、Dubbo接口)配置一个阈值,对限流进行准实时监控,包括限流的速率、限流次数、当前QPS.除了基本的并发限流,限流框架还实现了基于令牌桶和漏桶算法的QPS限流,基于Redis实现集群级限流。这些措施确保系统不会在高流量条件下不堪重负。考拉在服务转型上的实践考拉在监控服务上的转型在服务化的过程中,系统越来越复杂,服务的数量也越来越多。这时候就需要引入更多维度的监控功能,帮助快速定位和解决系统中的各种问题。监控主要分为四个方面:LogMetricsTrace健康检查(HealthCheck)在应用程序和操作系统运行时会产生各种日志,通过日志平台收集、分析和展示这些日志,并支持查询和运行。指标反映了系统运行的基本状态,包括瞬时值或聚合值,例如系统CPU使用率、磁盘使用率和服务调用期间的平均延迟。Trace是对服务调用链的监控,比如调用过程中的耗时分析、瓶颈分析、依赖分析、异常分析等。Healthcheck可以检测应用程序是否就绪、健康或活动。接下来介绍考拉围绕Dubbo在监控方面的改造实践。首先是服务监控。Dubbo提供服务监控功能,支持服务监控数据定时上报,通过代码增强收集Dubbo调用数据,存储在时序数据库中,并将Dubbo的调用监控功能接入考拉自身的监控平台。上图中的页面是Dubbo提供者的服务监控,包括服务接口、源集群等不同维度的监控。除了全局的调用监控,还包括不同维度的监控,比如监控项中的调用次数。有时候我们更关心慢请求,所以我们将响应时间划分为多个范围,比如从0到10毫秒,或者从10到50毫秒,这样我们就可以看到每个范围内的请求数,从而更好的了解服务质量。同时还可以通过各种告警规则定义告警,当服务电话异常时,通过邮件、短信、电话等方式通知相关人员。监控平台也会收集异常堆栈。比如这次服务调用异常的原因,是超时了还是线程满了,都可以直接在监控平台上看到。同时生成一些监控报告,帮助我们更好地了解服务的性能,促进发展和改进。第二个是跟踪。我们参考Dapper,自己开发Trace平台,通过代码增强实现Dubbo调用链接的收集。TarceID、SpanID等相关调用链参数通过Dubbo的隐式传参传递。Trace可以了解到一个服务调用环节的耗时分析和瓶颈分析。Trace平台可以展示一次服务调用,经过了哪些节点,最耗时的节点在哪里,从而有针对性地进行性能优化。Trace还可以进行依赖分析,这些依赖是否合理,一些不合理的依赖是否可以通过一些业务手段或者其他手段来减少。Trace对异常链路进行监控告警,及时发现系统异常,帮助我们快速定位问题。同时打通了日志平台,可以通过TraceID快速获取关联的异常日志。三是健康检查。健康检查也是一个很重要的监控方面,可以更优雅的启动应用实例。我们结合自动部署平台来实现应用程序的健康检查。当服务启动时,可以通过Readiness接口判断应用所依赖的各种资源,包括数据库、消息队列等是否就绪。只有健康检查成功才会触发注册操作。同时,在程序运行过程中,Agent也会定时检查服务的运行状态。同时这些接口也用来实现更优雅的shutdown,只依赖于shutdownhook,在某些情况下可能并不可靠,比如shutdownhooks的执行顺序。应用发布时,首先调用离线接口,从注册中心注销所有注册服务。这个时候不会有新的流量进来,过一段时间再执行关机释放操作,实现更优雅的关机。考拉在服务测试方面的转型下面介绍一下考拉在服务测试方面的实践。业务测试分为接口测试、单链路压测、全链路压测、异常测试四个维度。接口测试通过接口测试可以验证对外提供的Dubbo服务是否正确,所以我们也有一个接口测试平台帮助QA更好的进行接口测试,包括编辑接口(入参、出参)、用例编辑和执行测试场景等单链路压测单链路压测主要是对单个功能进行压测。比如在上线一个重要的功能或者比较重要的界面之前,必须要通过性能测试指标才能上线。全链路压测考拉作为电商平台,在推广前会进行全链路压测,检测系统性能瓶颈,预估系统容量。比如检测检测系统各个服务的容量是否足够,需要扩展多少容量,限流的阈值应该多合适,都可以通过full给定一些合理的值-链路压力测试。异常测试将系统异常和服务异常注入到服务调用环节中的一些节点中,也可以获得它们的强度依赖关系。比如一个很重要的接口可以从Trace中获取调用链接,然后对调用链所依赖的各个服务节点进行异常注入。通过接口的性能,系统会判断接口的强度依赖,以改善这些不合理的强依赖。考拉在API网关方面的改造随着考拉作为服务的发展,我们开发了API网关。API网关可以作为对外流量的统一接口,提供路由转发、流量控制、日志监控等一些公共功能。.考拉的API网关通过泛化调用调用后台Dubbo服务。Dubbo原生泛化调用的性能比普通的API调用要差。因此,我们也对泛化调用的性能做了一些优化,即去掉了泛化调用返回结果时的一个对象转换。最终压测结果的泛化性能甚至优于正常的调用性能。考拉在多语言方面的转型考拉在业务发展过程中有大量的多语言需求。比如我们前端团队希望通过Node应用来调用Dubbo服务。对比易用性,选择了开源的jsonrpc方案,然后在后端Dubbo服务上暴露了双协议,包括Dubbo协议和jsonrpc协议。不过在实施过程中,也遇到了一些小问题。比如对于Dubbo的消费者来说,不管是哪种协议提供者,都是调用者。通过一个负载均衡策略,选择一个invoker进行调用,此时会导致原来的Java客户端选择一个jsonrpc协议的provider。这样如果他们的API版本不一致,可能会导致序列化异常,调用失败。因此,我们对Dubbo的部分调用逻辑进行了修改。比如Java客户端的消费者调用时,除非显示配置,否则默认使用Dubbo协议调用。另外,考拉还扩展了社区的jsonrpc的隐式传参功能,因为可以使用Dubbo的隐式传参功能来传递一些全链路参数。考拉在解决注册中心性能瓶颈方面的实践注册中心的瓶颈可能是大多数电商都会遇到的问题,考拉也不例外。我们目前有4000多个Dubbo服务实例在线,但是在ZooKeeper中注册了超过一百万个节点,包括服务注册URL和消费者订阅URL。Dubbo应用发布时的惊群效应,重复通知,消费者拉取带来的瞬时流量,可以把ZooKeeper集群的网卡塞满。ZooKeeper还有另一个问题。其强一致性模型导致CPU利用率低。高的。即使扩容,也无法解决ZooKeeper写性能的问题。ZooKeeper写入不可扩展,应用发布时有大量请求排队,导致接口性能急剧下降。显示的现象是应用程序启动很慢。因此,在今年年初,我们决定更换ZooKeeper注册中心。对比现有的一些开源注册中心,包括Consul、Eruka、etcd等,我们觉得它们不太适合单进程多服务的Dubbo。注册模式能否同时应对考拉未来的发展,也是一个问号。因此,我们决定开发一个自主开发的注册中心。我们目前正在迁移注册中心。我们使用的是双注册中心的迁移方案,即服务会同时注册到ZooKeeper注册中心和一个新的注册中心。不会有太大的影响。考拉新的注册中心改造方案和现在的社区差不多。例如,还完成了注册数据拆分。注册到注册中心的数据只包括IP、Port等关键数据,其他数据写入Redis。注册表实现使用去中心化架构,包括使用最终一致性来换取我们界面性能的改进。如果以后连接Dubbo,会考虑使用Nacos而不是ZooKeeper作为注册中心。未来规划考拉目前还在建设第二个机房,通过两个机房独立部署同一套系统,实现同城双活。对于双机房的场景,Dubbo会做一些修改,比如先在同一个机房??调用,类似即将到来的Dubbo2.7.0中的路由特性。Dubbo服务注册时,会读取系统环境变量的环境或机房标签,然后将这些机房标签注册到注册中心,然后消费端会进行优先路由,优先调用服务中的服务同一个电脑房。容器化也是我们正在规划的一个方向。随着服务流程的演进,服务的数量也越来越多。通过容器化和DevOps,可以提升测试、部署和运维的效率。今年ServiceMesh很火。通过ServiceMesh,将服务框架的注册与发布、路由与负载均衡、服务治理等能力降级为Sidecar,运行在独立的进程中。业务工程的解耦,帮助我们实现异构系统,支持多语言,也可以解决中间件升级难,各种依赖冲突的问题。业务端也可以更好的专注于业务的发展,这也是未来探索的一个方向。福利就在这里谈谈你在微服务架构实践中的感悟!欢迎在下方留言讨论,小编将选出5位评论最精彩的网友,送书《Spring 5开发大全》~活动截止日期为12月18日石正,特别感谢北大出版社赞助本次活动的书籍。迫不及待送书的朋友可以点击阅读原文直接购买。本书简介本书力求对Spring框架进行全面的介绍,涵盖Spring核心、测试、数据访问、Web开发、响应式编程、系统集成、微服务等共26章。百科全书”。同时,本书基于Spring5版本编写。除了Spring5版本的新特性外??,还介绍了REST服务、响应式Web开发、微服务设计、Spring等方面的前瞻技术。Boot、SpringCloud,每个知识点除了讲解Spring的理论知识外,还辅以大量的代码案例,理论联系实际,可操作性更强。本书主要面向Java开发人员,以及对以Spring为中心的JavaEE开发感兴趣的计算机科学专业的学生、软件开发人员和系统架构师。