在springboot、springcloud成熟前,微服务已经在各互联网公司实践,比如dubbo等,这些实践中很大部分可能都采用的是thrift作为首选rpc框架,我们公司就使用thrift搭建了一套微服务系统,其中作为服务注册中心的配置服务,由于集群化的难度(直接采用zookeeper/eureka等框架,涉及修改的点太多了,对已有项目升级就是个问题;只做主备,又担心规模上来后,配置服务扛不住),一直是单点的,近期这个事情落在了我身上,既要集群化,又不能改动已有的其他服务,研究了当前已有的一些作为注册中心的框架,最终选定eureka,更好的地方是eureka是一个纯servlet应用,意味着可以集成到任何带有servlet容器的项目中,而且使用极为简单,下面就简单介绍下实现方案。
附上几个主要参考的很有价值的帖子:
从Eureka Client发起注册请求到Eureka Server处理的整个服务注册过程
写以上帖子的都是大神!!!
一、springboot拉起eureka
这个部分内容网上有很多帖子可以参考,都是注解和配置可以解决的,推荐几个帖子:
Spring Cloud构建微服务架构(六)高可用服务注册中心
Spring Cloud Eureka(四):Eureka 配置参数说明
其实就是在springboot启动类上加个注解@EnableEurekaServer,这里附点代码:
@SpringBootApplication
@ImportResource("classpath:spring/imbusiness-config.xml")
@EnableEurekaServer
public class ServiceConfigureApplication {
public static void main(String[] args) {
ApplicationContext applicationContext = SpringApplication.run(ServiceConfigureApplication.class, args);
SpringConfigLoad.setContext(applicationContext);
SpringConfigLoad.getBean(ConfigureServiceInit.class).run(args);
}
}
如此,eureka服务端已经OK了;
这里要保证不变动其他服务的逻辑,弃用eureka的客户端;但是,eureka是一个servlet应用,提供了rest风格的接口,这时就需要研究下eureka源码,获取其内部操作缓存的接口,直接调用其内部操作缓存的接口,而不走rest接口。
二、集成thrift旧服务
thrift框架开发服务,无非是实现其服务端,比如TThreadedSelectorServer,各项目都有自己的包装,这里不详述,但是无论怎么包装,都有启动的入口,比如我的实现是,将原有服务的启动操作都封装到一个bean类ConfigureServiceInit中,springboot启动时只需调用下封装的方法即可
SpringConfigLoad.getBean(ConfigureServiceInit.class).run(args);
三、融合原thrift服务与eureka
作为服务注册中心,主要提供的功能为注册、心跳、查询,对应eureka就是register、renew、getApplications三个接口,那么融合的方法就是在原有注册中心的注册接口中调用eureka的register,心跳方法中调用eureka的renew,查询则通过getApplications来获取,附上源码:
注册
PeerAwareInstanceRegistry registry = SpringConfigLoad.getBean(DefaultEurekaServerContext.class).getRegistry();
InstanceInfo.Builder builder = InstanceInfo.Builder.newBuilder();
builder.setAppName(registerConfigBean.getName());
builder.setIPAddr(registerConfigBean.getIp());
builder.setPort(registerConfigBean.getPort());
builder.setDataCenterInfo(new MyDataCenterInfo(DataCenterInfo.Name.MyOwn));
builder.setStatus(InstanceInfo.InstanceStatus.UP);
builder.setInstanceId(registerConfigBean.getIp() + ":" + registerConfigBean.getName() + ":" + registerConfigBean.getPort());
LeaseInfo.Builder leaseInfoBuilder = LeaseInfo.Builder.newBuilder();
leaseInfoBuilder.setDurationInSecs(15);
LeaseInfo leaseInfo = leaseInfoBuilder.build();
builder.setLeaseInfo(leaseInfo);
InstanceInfo instanceInfo = builder.build();
registry.register(instanceInfo,false);
心跳
PeerAwareInstanceRegistry registry = SpringConfigLoad.getBean(DefaultEurekaServerContext.class).getRegistry();
boolean rel = registry.renew(serviceConfig.getName(), serviceConfig.getIp() + ":" + serviceConfig.getName() + ":" + serviceConfig.getPort(), false);
查询
PeerAwareInstanceRegistry registry = SpringConfigLoad.getBean(DefaultEurekaServerContext.class).getRegistry();
Applications apps = registry.getApplications();
List<Application> it = apps.getRegisteredApplications();
通过研究eureka的启动流程,可以看到EurekaServerContext的初始化值为DefaultEurekaServerContext的实例,而DefaultEurekaServerContext是单例的,可以通过spring上下文获取到,该类有个成员变量PeerAwareInstanceRegistry registry提供了eureka所有接口,因此只需通过registry即可操作eureka的缓存来保存修改查询数据。
下图为工程实际运行结果:
四、集群
集群的实现就完全依赖eureka了,可参考下面的帖子,即可完成。
Spring Cloud构建微服务架构(六)高可用服务注册中心
最后,如上是本人的一点实践,如要投入生产环境,仍需完善,本方案提供出来以供参考,如有缺陷,烦请告知,这里先行感谢!