在走读源码前,本人带着以下几个疑问进行走读Seata源码:
1、Seata如何支持多种配置平台?
Seata作为一个分布式事务中间件,配置中心已经支持多种,例如:Nacos、etcd、apollo 等。
2、Seata-Server配置集群时,TM RM 如何进行负载均衡?
Seata的TM、RM与Seata-Server进行相互通讯时,如何得知Seata-Server有效的通讯地址?如何做到有效的负载均衡?
一、Seata配置中心核心逻辑
1.1 通过Java SPI实现扩展配置中心
Seata配置中心采用Java SPI逻辑来进行扩展不同的配置中心实现。
其中Configuration定义获取配置的相关方法,每个不同的配置平台实现方式均基于Configuration进行实现;
ConfigurationProvider定义Configuration实现类,通过此类进行扩展实现SPI。
在Seata中进行配置META-INF\services中的io.seata.config.ConfigurationProvider配置相关所有的实现类:
io.seata.config.custom.CustomConfigurationProvider
io.seata.config.apollo.ApolloConfigurationProvider
io.seata.config.nacos.NacosConfigurationProvider
io.seata.config.zk.ZookeeperConfigurationProvider
io.seata.config.consul.ConsulConfigurationProvider
io.seata.config.etcd3.EtcdConfigurationProvider
io.seata.config.springcloud.SpringCloudConfigurationProvider
通过EnhanceServiceLoader中Load相关实现类,将实现类缓存到本地中,在进行获取配置信息,通过LoadLevel中配置的name信息进行获取实现类。
1.2、如何实现配置中心更新变化监听
定义通用的ConfigurationChangeListener,在每个不同的配置中心实现的过程中通过Listener传递对应的配置更改信息。
1.3、其他思考:如何自行实现SPI
基于Java的ServiceLoader进行扩展实现,具体实现方式可以参考以下方式:
ServiceLoader<A> serviceLoader = ServiceLoader.load(A.class);
Iterator<A> serviceLoaderIterator = serviceLoader.iterator();
while (serviceLoaderIterator.hasNext()) {
A a = serviceLoaderIterator.next();
applicationContext.getAutowireCapableBeanFactory().autowireBean(a);
processorList.add(a);
}
二、Seata注册中心核心逻辑
2.1 注册中心存在的必要性
Seata注册中心记录了服务和服务地址的映射关系。在分布式架构中,服务会注册到这里,当服务需要调用其它服务时,就到这里找到服务的地址,进行调用。比如Seata Client端(TM、RM),发现Seata Server(TC)集群的地址,彼此通信。
客户端获取到对应的Seata-Server集群信息后,可以通过LoadBalance进行通讯。
2.2 注册中心核心实现逻辑(继续Java SPI)
Seata注册中心主要基于RegistryFactory、RegistryService来进行扩展实现。
SPI配置信息如下图所示:
2.3 Loadbalance实现逻辑
Seata支持多种负载均衡算法,包括:随机、最小活跃等;
负载均衡基于LoadBalanceFactory、LoadBalance进行扩展实现。
2.4 注册中心配置关键
在Seata-Client配置注册执行时,有几个关键性属性需要配置正确。
default为seata-server集群的名称
seata.service.vgroup-mapping.my_test_tx_group=default1
以Nacos为例:
seata.registry.type=nacos
seata.registry.nacos.username=nacos
seata.registry.nacos.password=nacos
# seata-server启动的应用程序,需要与 Seata-Server(TC端)的应用程序名称
seata.registry.nacos.application=seata-server
# seata-server(TC端)注册到nacos的应用GROUP名称
seata.registry.nacos.group=SEATA_GROUP
seata.registry.nacos.client-application=demo1
seata.registry.nacos.server-addr=127.0.0.1:8848
三、总结
Seata在实现Config、Registry模块时,都是基于SPI模式进行扩展实现。通过SPI可以独立的实现扩展相关模块。在Dubbo中也有大量的扩展类通过SPI实现。