本文分享自华为云社区《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的要求变得不可行。提供更加简化的注册发现实现,虽然减少了少量有有竞争力的功能特性,但是极大降低了客户选型的顾虑。

点击关注,第一时间了解华为云新鲜技术~   

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐