解密JavaChassis3:易扩展的多种注册中心支持
本文解密了JavaChassis3提供易扩展的多种注册中心支持的背景和技术细节。
本文分享自华为云社区《JavaChassis3技术解密:易扩展的多种注册中心支持》,作者:liubao68。
JavaChassis的早期版本依赖于ServiceCenter,提供了很多差异化的竞争力:
- 接口级别转发。通过注册中心管理微服务的每个版本的元数据,特别是契约数据。结合契约数据,能够实现版本级别的路由能力。比如一个微服务存在v1和v2两个版本,其中v1版本存在接口op1,op2,v2版本存在接口op1,op2,op3,在灰度场景,JavaChassis能够自动将op3的访问转发到v2版本,将op1,op2的访问在v1,v2版本做负载均衡。
- 基于version-rule的实例选择。客户端能够配置version-rule,比如last,2.0+等。这样客户端能够根据实际情况,筛选实例的版本。
JavaChassis过度依赖ServiceCenter,为产品的发展带来了一些瓶颈。JavaChassis的生态推广依赖于ServiceCenter的生态推广,不利于JavaChassis被更多用户使用。随着云的发展,越来越多的客户也期望一套代码,能够在不同的云环境运行,有些云产商未提供ServiceCenter运行环境,那么用户选择JavaChassis就会存在顾虑。
基于上述原因,JavaChassis简化了注册发现的依赖,定义了简单容易实现的接口,并基于Nacos提供了实现,未来还会提供zookeeper等实现。JavaChassis采用了一系列新的设计模式,保证了在降低注册中心功能依赖的前提下,不降低应用自身的可靠性。
接口级别转发的替代方案
依赖于Service Center,JavaChassis提供了接口级别转发。JavaChassis3首先做的一个变化是删除了对于接口级别转发的支持。这样对于注册中心的依赖复杂度至少可以降低70%。然而灰度场景依然对很多业务比较重要,JavaChassis3使用灰度发布解决这个问题。使用灰度发布的好处是不用依赖注册中心提供版本元数据管理能力,只需要每个实例具备版本号等简单元数据信息。
servicecomb:
#enablerouterforedgeservice
router:
type:router
routeRule:
business:|
-precedence:2
match:
apiPath:
prefix:"/business/v2"
route:
-weight:100
tags:
version:2.0.0
-precedence:1
match:
apiPath:
prefix:"/business/v1/dec"
route:
-weight:50
tags:
version:1.1.0
-weight:50
tags:
version:2.0.0
注册发现接口及其实现
JavaChassis3只需要使用Discovery接口就能够提供新的注册发现支持。JavaChassis会调用findServiceInstances查询实例,如果后续实例发生变更,注册中心实现通过InstanceChangedListener通知JavaChassis.
/**
*Thisisthecoreservicediscoveryinterface.<br/>
*/
publicinterfaceDiscovery<DextendsDiscoveryInstance>extendsSPIEnabled,SPIOrder,LifeCycle{
interfaceInstanceChangedListener<DextendsDiscoveryInstance>{
/**
*CalledbyDiscoveryImplementationswheninstancelistchanged.
*@paramregistryNameNameofthecallingdiscoveryimplementation
*@paramapplicationMicroserviceapplication
*@paramserviceNameMicroservicename
*@paramupdatedInstancesThelatestupdatedinstances.
*/
voidonInstanceChanged(StringregistryName,Stringapplication,StringserviceName,List<D>updatedInstances);
}
Stringname();
/**
*Ifthisimplementationenabledforthismicroservice.
*/
booleanenabled(Stringapplication,StringserviceName);
/**
*Findallinstances.
*
*LifeCycle:Thismethodiscalledanytimeafter<code>run</code>.
*
*@paramapplicationapplication
*@paramserviceNamemicroservicename
*@returnallinstancesmatchthecriteria.
*/
List<D>findServiceInstances(Stringapplication,StringserviceName);
/**
*DiscoverycancallInstanceChangedListenerwheninstancegetchanged.
*/
voidsetInstanceChangedListener(InstanceChangedListener<D>instanceChangedListener);
}
JavaChassis3通过Registration来管理注册,注册过程分为init、run、destroy简单的生命周期,可以在init准备注册的数据,run执行注册,destroy则在注册失败或者系统停止的时候执行。
/**
*Thisisthecoreserviceregistrationinterface.<br/>
*/
publicinterfaceRegistration<RextendsRegistrationInstance>extendsSPIEnabled,SPIOrder,LifeCycle{
Stringname();
/**
*getMicroserviceInstance</br>
*
*LifeCycle:Thismethodiscalledanytimeafter<code>run</code>.
*/
RgetMicroserviceInstance();
/**
*updateMicroserviceInstancestatus</br>
*
*LifeCycle:Thismethodiscalledanytimeafter<code>run</code>.
*/
booleanupdateMicroserviceInstanceStatus(MicroserviceInstanceStatusstatus);
/**
*addingschemastoMicroservice</br>
*
*LifeCycle:Thismethodiscalledafter<code>init</code>andbefore<code>run</code>.
*/
voidaddSchema(StringschemaId,Stringcontent);
/**
*addingendpointstoMicroserviceInstance</br>
*
*LifeCycle:Thismethodiscalledafter<code>init</code>andbefore<code>run</code>.
*/
voidaddEndpoint(Stringendpoint);
/**
*addingpropertytoMicroserviceInstance</br>
*
*LifeCycle:Thismethodiscalledafter<code>init</code>andbefore<code>run</code>.
*/
voidaddProperty(Stringkey,Stringvalue);
}
注册发现的组合
JavaChassis3可以独立实现多个Discovery和Registration,达到向多个注册中心注册和从多个注册中心发现实例的作用。每个实例根据实例ID唯一来标识。如果实例ID相同,会被认为是同一个实例,如果不同,则会认为是不同的实例。在JavaChassis3技术解密:注册中心分区隔离中聊到了,JavaChassis要求每次实例注册(新的进程),生成唯一的实例ID,以解决注册分区隔离带来的实例假下线问题。Discovery和Registration都包含了JavaChassis定义的基础信息。
/**
*Standardinformationusedformicroserviceinstanceregistrationanddiscovery.
*/
publicinterfaceMicroserviceInstance{
/**
*Environment(Required):Usedforlogicseparationofmicroserviceinstance.Only
*microserviceinstancewithsameenvironmentcandiscoveryeachother.
*/
StringgetEnvironment();
/**
*Application(Required):Usedforlogicseparationofmicroserviceinstance.Only
*microserviceinstancewithsameapplicationcandiscoveryeachother.
*/
StringgetApplication();
/**
*ServiceName(Required):Uniqueidentifierformicroservice.
*/
StringgetServiceName();
/**
*ServiceNameAlias(Optional):Uniqueidentifierformicroservice.
*Thisaliasisusedbyregistryimplementationtosupportrename
*ofamicroservice,e.g.oldconsumersuseoldservicenamecan
*findarenamedmicroserviceservice.
*/
StringgetAlias();
/**
*ServiceVersion(Required):versionofthismicroservice.
*/
StringgetVersion();
/**
*Datacenterinfo(Optional).
*/
DataCenterInfogetDataCenterInfo();
/**
*ServiceDescription(Optional)
*/
StringgetDescription();
/**
*ServiceProperties(Optional)
*/
Map<String,String>getProperties();
/**
*ServiceSchemas(Optional):OpenAPIinformation.
*/
Map<String,String>getSchemas();
/**
*Serviceendpoints(Optional).
*/
List<String>getEndpoints();
/**
*Microserviceinstanceid(Required).Thisidcanbegeneratedwhenmicroserviceinstanceisstarting
*orassignedbyregistryimplementation.
*
*Whenmicroserviceinstanceisrestarted,thisidshouldbechanged.
*/
StringgetInstanceId();
/**
*Microserviceserviceid(Optional).Thisisusedforservicecenter,otherimplementationsmaynot
*supportserviceid.
*/
defaultStringgetServiceId(){
return"";
}
}
在实现注册发现的时候,需要保证该接口定义的基础信息能够注册到注册中心,查询实例的时候,能够获取到这些信息。
客户故事:不把鸡蛋放到同一个篮子里面,是技术选型里面很重要的考量。解决方案的开放性和可替代性、云服务的可替代性,是很多客户都关注的问题。对于一个开源的技术框架,JavaChassis早期的版本虽然设计上也支持不同的注册中心扩展,但是实现难度很高,不自觉的把客户使用其他注册中心替换servicecenter的要求变得不可行。提供更加简化的注册发现实现,虽然减少了少量有有竞争力的功能特性,但是极大降低了客户选型的顾虑。
更多推荐
所有评论(0)