服务管理与通信,基础原理分析

本文涉及的产品
传统型负载均衡 CLB,每月750个小时 15LCU
网络型负载均衡 NLB,每月750个小时 15LCU
应用型负载均衡 ALB,每月750个小时 15LCU
简介: 阅读源码最重要的是耐着心情慢慢看,并随手画下核心流程,实际上如果有一定的编程经验,不管是阅读什么工程的源码,只要用心去分析单点的实现原理,都算不上过度复杂。

一、基础简介

服务注册发现是微服务架构中最基础的能力,下面将从源码层面分析实现逻辑和原理,在这之前要先来看下依赖工程的基础结构,涉及如下几个核心组件:

01-1.png

  • commons:服务组件的抽象声明,本文只分析注册发现与负载均衡;
  • nacos:当下常用的注册中心组件,用来进行服务管理;
  • feign:服务间通信交互组件,在服务请求时涉及负载均衡的策略;
  • ribbon:在服务间通信请求时,提供多种负载均衡的策略实现;

在熟悉工程依赖之间的结构时,还要明白服务间交互的流程和原理,这样在分析源码设计时,有一个清晰的思路与轮廓;如何实现下面的服务交互模式,在阅读源码工程时,围绕如下两个核心逻辑:

01-2.png

  • 注册发现:注册时如何上报服务的信息数据,这些数据以怎样的方式管理;
  • 负载均衡:当请求的服务同时存在多个时,以什么样的策略选择执行请求的服务;

在这里先简单的聊一下个人在阅读源码工程时的基本思路,比如微服务组件:通常从配置参数作为切入口,观察基于参数构建的核心对象,再重点分析对象的管理模式,以及适配的扩展能力,最后结合项目的应用场景即可:

01-3.png

阅读源码最重要的是耐着心情慢慢看,并随手画下核心流程,实际上如果有一定的编程经验,不管是阅读什么工程的源码,只要用心去分析单点的实现原理,都算不上过度复杂,但是组件通常为了复用能力,会去适配多种复杂的场景,这样势必要采用抽象的封装和设计模式,源码工程的复杂度自然就会相应提高,这个话题后续会细聊。

二、服务注册

1、服务配置

首先从Nacos配置参数开始,这里只设置服务发现的两个参数:1Nacos注册中心的服务端地址,2在服务的元数据中加载分支号;然后来具体的看源码流程:

01-4.png

在配置参数加载的过程中,有很多缺省的默认值,所以需要关注最终会提供的参数信息,来判断是否需要自定义设置,另外AutoConfig配置要重点看实例化的对象;断点的流程可以按照如下的方式做设置,这里陈列的是在配置加载阶段的几个核心节点:

  • 参数:NacosDiscoveryProperties#getNacosProperties
  • 配置:NacosServiceAutoConfiguration#nacosServiceManager
  • 构建:NacosServiceManager#buildNamingService

01-5.png

NamingService是Nacos服务管理接口,涉及注册、查询、撤销、检查等多个方法,即对应的是Nacos服务端的相应API请求,在注册执行的阶段会细说用法。

2、注册构建

看完服务配置之后再看注册配置,对于配置中复杂的设计,需要重点关注两个信息:ConditionalOn和matchIfMissing,这样很容易发现默认加载:

  • 配置:NacosServiceRegistryAutoConfiguration#nacosServiceRegistry
  • 注册:NacosServiceRegistry#register
  • 实例:NacosServiceRegistry#getNacosInstanceFromRegistration

01-6.png

在构建服务注册的核心类NacosServiceRegistry时,通过服务的登记信息转换为注册的实例化对象,然后通过NamingService接口方法,上报实例化对象;需要注意的是,虽然这里只看了Nacos中的相关API,但实际上API实现了诸多spring-cloud-commons包中声明的接口,比如Registration、ServiceInstance等。

3、执行上报

通常微服务的注册中心组件,都是基于server-client架构和部署方式,客户端需要根据自身启动状态去上报或者撤销注册,服务端负责统一维护注册数据:

  • 实现:NacosNamingService#registerInstance
  • 执行:NamingProxy#registerService
  • 接口:InstanceController#register

01-7.png

在最终执行服务注册时,其动作本质就是请求Nacos服务端的一个Post方法,并将配置数据上报,例如:IP地址、端口、元数据、权重等;这样客户端注册逻辑执行完成,然后再看服务端数据可视化界面,就可以看到注册的客户端服务。

01-8.png

至于Nacos服务端是如何管理这些注册数据的,参考部署版本的nacos-naming模块源码,阅读上报接口和页面中的列表加载的实现即可;注意在初始的配置文件中,加入的branch分支参数也在元数据结构中。

在NamingService接口中,涉及多个服务管理的方法,在执行原理上基本相同就不在赘述,这样注册中心的Client端和Server端就形成了通信机制,接下来再看Client端之间的通信。

三、服务通信

1、基础配置

Feign在配置方面比较复杂,提供了多个场景下的适配能力,这里只以两个常见的参数作为切入点:1通信超时时间,2Http选型(采用默认值);

01-9.png

  • 参数:FeignClientProperties#getConfig
  • 注解:FeignClientsRegistrar#registerFeignClients
  • 配置:FeignAutoConfiguration#feignContext
  • 构建:FeignClientFactoryBean#getTarget

01-10.png

这里要重点关注的是注解的扫描和注册以及容器管理,要理解Feign的上下文环境需要明白上文中描述的服务间交互原理,然后参考FeignClientFactoryBean工厂类中构建逻辑。

2、通信逻辑

虽然Feign注解的方式可以简化开发,但是在具体执行的时候还是Http的请求响应模式,这里可以参考LoadBalancerFeignClient类中的execute方法:

  • 配置:FeignRibbonClientAutoConfiguration
  • 通信构建:LoadBalancerFeignClient#execute
  • 负载均衡:AbstractLoadBalancerAwareClient#executeWithLoadBalancer

01-11.png

不管是Feign组件还是Spring框架,默认的负载均衡策略都是采用Ribbon的实现方式,在上述流程中配置和负载均衡命令都依赖Ribbon组件,接下来看服务选择策略。

四、负载均衡

1、命令构建

这里构建了调用负载均衡接口的命令,ILoadBalancer接口中提供服务管理的相关方法,其中最核心的就是chooseServer方法,然后结合具体的策略规则实现服务的选择的功能:

  • 命令构建:LoadBalancerCommand.Builder#build
  • 负载容器:LoadBalancerContext#getServerFromLoadBalancer
  • 选择接口:ILoadBalancer#chooseServer

01-12.png

2、策略规则

Ribbon组件中负载均衡的策略有好几种规则,比如随机选择、Key匹配、权重倾斜等;在工作中常用的就是默认规则即RoundRobinRule,以及基于Key设计的灰度模式,简单做法就是服务启动时在元数据中添加的分支号作为匹配的标识;

  • 规则设置:BaseLoadBalancer#setRule
  • 随机策略:RoundRobinRule#choose
  • 过滤策略:PredicateBasedRule#choose

01-13.png

现在回到流程的开始看,通过Nacos组件进行服务注册和管理,通过Feign组件基于Ribbon负载均衡策略做服务通信,如果单看各节点组件的逻辑还比较容易理解,但是通过Spring框架做组件之间的协作调度时,复杂程度明显提高;

如果是刚开始阅读源码的阶段,可以只关注相应流程的核心逻辑,选择性忽略细节的实现原理,当然重点还是要多读读Spring的设计,这样时间久了自然会有很多收获。

五、参考源码

编程文档:
https://gitee.com/cicadasmile/butte-java-note

应用仓库:
https://gitee.com/cicadasmile/butte-flyer-parent
相关实践学习
部署高可用架构
本场景主要介绍如何使用云服务器ECS、负载均衡SLB、云数据库RDS和数据传输服务产品来部署多可用区高可用架构。
负载均衡入门与产品使用指南
负载均衡(Server Load Balancer)是对多台云服务器进行流量分发的负载均衡服务,可以通过流量分发扩展应用系统对外的服务能力,通过消除单点故障提升应用系统的可用性。 本课程主要介绍负载均衡的相关技术以及阿里云负载均衡产品的使用方法。
相关文章
|
网络架构 网络协议 网络安全
带你读《计算机网络问题与解决方案:一种构建弹性现代网络的创新方法》之三:网络传输建模
本书分为三个主要部分,涵盖了数据传输、控制平面,以及具体设计(或者更确切地说是技术)场景。
|
2月前
|
消息中间件 算法 Java
C++实时通信优化技术探究
C++实时通信优化技术探究
30 3
|
2月前
|
负载均衡 网络协议 中间件
掌握 SOME/IP :访问进程数据 构建高效通信系统的关键技术
掌握 SOME/IP :访问进程数据 构建高效通信系统的关键技术
132 1
|
2月前
|
缓存 网络协议 数据库连接
【底层服务/编程功底系列】「网络通信体系」深入探索和分析TCP协议的运输连接管理的核心原理和技术要点
【底层服务/编程功底系列】「网络通信体系」深入探索和分析TCP协议的运输连接管理的核心原理和技术要点
39 0
|
8月前
|
网络协议 Java Linux
网络分层:构建信息交流的桥梁
在这篇文章中,我们将继续探讨网络分层的重要性和每个层次的功能。网络分层的优势在于每个层次的功能清晰明确,使得网络的设计和维护更加简化和灵活。网络分层的设计和实现使得我们能够在全球范围内进行高效的通信和信息交流。通过理解每个层次的功能和作用,我们可以更好地理解和解决网络中出现的问题
网络分层:构建信息交流的桥梁
|
12月前
|
存储 开发框架 缓存
数据流动的精妙之道——UniApp中的数据通信与状态管理解析
数据流动的精妙之道——UniApp中的数据通信与状态管理解析
|
关系型数据库 调度 语音技术
呼叫系统的技术实现原理和运作流程
呼叫系统的技术实现原理和运作流程
240 0
呼叫系统的技术实现原理和运作流程
|
存储 缓存 算法
能量收集通信 | 带你读《5G系统关键技术详解》之五
本书深入介绍了 5G 无线网络的协议、网络架构和技术,包括无线接入网络、移动边 缘计算、全双工、大规模 MIMO、毫米波、NOMA、物联网、M2M 通信、D2D 通信、 移动数据分流、干扰抑制技术、无线资源管理、可见光通信和智能数据定价等关键主题。
能量收集通信 | 带你读《5G系统关键技术详解》之五
|
机器学习/深度学习 编解码 5G
前传感知的协作传输和接收之上行链路 | 带你读《5G系统关键技术详解》之十二
本节说明了上行链路和下行链路 C-RAN 的波束成形 设计技术,并将 C-RAN 用户的理论可实现速率表征为前传容量限制的函数。
前传感知的协作传输和接收之上行链路   | 带你读《5G系统关键技术详解》之十二
|
人工智能 运维 算法