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

服务管理与通信基本原理解析

时间:2023-03-22 12:20:47 科技观察

涉及轻微源码展示,大家可以放心参考!1.基本介绍服务注册发现是微服务架构中最基本的能力。下面将从源码层面分析实现逻辑和原理。在此之前,我们首先要看一下依赖项目的基础架构,其中涉及到以下几个核心组件:commons:服务组件的抽象声明。本文只分析注册发现和负载均衡;nacos:一个常用的注册中心组件,用于服务管理;feign:服务之间的通信和交互组件,涉及服务请求中的负载均衡策略;ribbon:服务间通信请求时,提供多种负载均衡策略;在熟悉项目依赖结构的同时,还要了解服务间交互的过程和原则,这样在分析源码设计和大纲时思路清晰;如何实现下面的服务交互方式,在阅读源码项目时,围绕着以下两个核心逻辑:注册发现:注册时如何上报服务信息数据,这些数据是如何管理的;负载均衡:当请求同时有多个服务时,采用什么样的策略来选择请求的服务;这里简单说一下个人在阅读源码项目时的基本思路,比如微服务组件:通常以配置参数为切入点,观察基于参数构建的核心对象,然后着重分析管理对象的模式和适配的扩展能力,最后结合项目的应用场景:阅读源码最重要的是耐心慢慢地阅读源码,随便画出核心流程。其实如果你有一定的编程经验,不管你看什么项目源码,只要仔细分析单点的实现原理,都不会太复杂。但是,组件通常会适应多种复杂的方法以实现可重用性。场景化,所以需要采用抽象封装和设计模式,源码项目的复杂度自然会相应增加。稍后将详细讨论该主题。二、服务注册1、服务配置首先启动Nacos配置参数。这里只设置了两个服务发现的参数:1.Nacos注册中心的服务器地址,2.加载服务元数据中的分支号;然后详细看源码过程:在加载配置参数的过程中,有很多默认的默认值,所以需要注意最后会提供的参数信息,以确定是否需要自定义设置。另外,AutoConfig配置应该关注实例化对象;断点流程可以设置如下。下面是配置加载阶段的几个核心节点:参数:NacosDiscoveryProperties#getNacosProperties配置:NacosServiceAutoConfiguration#nacosServiceManager构建:NacosServiceManager#buildNamingServiceNamingService是Nacos服务管理接口,涉及注册、查询、注销、校验等方法,即对应到Nacos服务端对应的API请求,具体使用方法会在注册执行阶段详细说明。2、注册与构建看完服务配置再看注册配置。对于配置中复杂的设计,需要重点关注两个信息:ConditionalOn和matchIfMissing,所以很容易找到默认加载:服务注册的核心类NacosServiceRegistry,将服务的注册信息转化为注册的实例化对象,然后通过NamingService接口方法上报实例化对象;需要注意的是,这里虽然只使用了Nacos的相关API,但实际上该API实现了很多在spring-cloud-commons包中声明的接口,比如Registration、ServiceInstance等。3.执行和上报通常微服务的注册中心组件都是基于server-client的架构和部署方式。客户端需要根据自己的启动状态来上报或者注销注册,服务端负责统一维护注册数据:action本质是向Nacos服务器请求一个Post方法,上报配置数据,如:IP地址、端口、元数据、权重等;这样,客户端注册逻辑执行完后,再看服务端数据可视化界面,就可以看到注册的客户端服务了。至于nacos服务器是如何管理这些注册数据的,可以参考nacos-naming模块部署版本的源码,阅读页面中上报接口和列表加载的实现;注意在初始配置文件中,添加的branch分支参数也在元数据结构中。在NamingService接口中,多个服务管理涉及的方法在执行原理上基本相同,不再赘述。这样,注册中心的客户端和服务器就形成了一个通信机制。接下来,我们将查看客户端之间的通信。三、服务通信1、基础配置Feign配置较为复杂,提供多场景适配能力。这里只使用两个常用参数作为入口:1.通信超时时间,2.Http选择(使用默认值));参数:FeignClientProperties#getConfig注解:FeignClientsRegistrar#registerFeignClients配置:FeignAutoConfiguration#feignContext构建:FeignClientFactoryBean#getTarget这里重点介绍注解的扫描注册和容器管理。要理解Feign的脉络,需要先理解上面描述的服务交互原理,然后再参考FeignClientFactoryBean工厂类中的构造逻辑。2.通信逻辑Feign注解方式虽然可以简化开发,但是在具体执行时仍然是Http请求响应方式。这里可以参考LoadBalancerFeignClient类中的execute方法:Configuration:FeignRibbonClientAutoConfiguration通讯构造:LoadBalancerFeignClient#executeLoadBalancer:AbstractLoadBalancerAwareClient#无论executeWithLoadBalancer是Feign组件还是Spring框架,默认的负载均衡策略都是使用Ribbon实现的。上述过程中,配置和负载均衡命令都依赖于Ribbon组件。接下来看服务选择策略。4.负载均衡1.命令构建这里构建了调用负载均衡接口的命令。ILoadBalancer接口中提供了服务管理的相关方法,其核心是chooseServer方法,再结合具体的策略规则实现服务选择的功能:命令Build:LoadBalancerCommand.Builder#buildLoadcontainer:LoadBalancerContext#getServerFromLoadBalancerSelection接口:ILoadBalancer#chooseServer2,policyrulesRibbon组件中的负载均衡策略有几种规则,比如随机选择,Key匹配,权重倾斜等;工作中常用的默认规则是RoundRobinRule,基于Key设计的灰度模式。简单的方法是在服务启动时在元数据中添加分支号作为匹配标识;rulesetting:BaseLoadBalancer#setRuleRandomstrategy:RoundRobinRule#chooseFilterstrategy:PredicateBasedRule#choose现在回到流程的开头,使用Nacos组件进行服务注册和管理,使用Feign组件进行基于Ribbon负载均衡的服务通信战略。如果只看各个节点组件的逻辑更容易理解,但是通过Spring框架进行组件间的协同调度,复杂度明显增加;如果是刚开始阅读源码,可以只关注对应流程的核心逻辑,选择性忽略细节的实现原理。当然,重点还是多看Spring的设计。久而久之,自然会有不少收获。5.参考源码编程文档:https://gitee.com/cicadasmile/butte-java-note应用仓库:https://gitee.com/cicadasmile/butte-flyer-parent