一个服务正常情况下,应该只会注册一个节点,但是出于某些原因,需要把多个节点合并为一个节点,但是不能影响到其它节点的调用,除非去通知服务调用人员,改一下调用接口.但是要把所有调用端都改完,还是得花些时间的…
这里就是以最小时间成本,合并服务.
spring知识整理之服务发现
这里以consul为例,其它服务发现Eureka/k8s的api应该也都是类似的作法
基于 spring cloud /consul服务发现
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
.... 略
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
定义一个类,添加节点的详细信息
节点id
节点名称
设置健康检查地址
等等
除了节点id,其它其它的信息都可以重复
@Component
public class MultipleConsulNode implements CommandLineRunner {
@Autowired
private ConsulDiscoveryProperties properties;
@Autowired
private HeartbeatProperties heartbeatProperties;
@Autowired
private AutoServiceRegistrationProperties autoServiceRegistrationProperties;
@Autowired
ConsulServiceRegistry ConsulServiceRegistry;
@Autowired
AnnotationConfigServletWebServerApplicationContext js_context;
@Autowired(required = false)
private TtlScheduler ttlScheduler;
@Autowired
private ConsulAutoConfiguration consulAutoConfiguration;
@Autowired
private DisposableBeanAdapterSub disposableBeanAdapter;
public static List<Map<String,Object>> regs = new ArrayList<>();
static {
Map<String,Object> rej1 = new HashMap<>();
rej1.put("before","service1");
rej1.put("service_name","service1-micros");
regs.add(rej1);
Map<String,Object> rej2 = new HashMap<>();
rej2.put("before","service2");
rej2.put("service_name","service2-micros");
regs.add(rej2);
}
@Override
public void run(String... args) throws Exception {
registration();
}
private void registration(){
Integer agentPort = Integer.parseInt(properties.getInstanceId().substring(properties.getInstanceId().lastIndexOf("-") + 1));
//构造client
ConsulClient client = consulAutoConfiguration.consulClient(consulAutoConfiguration.consulProperties());
ConsulDiscoveryProperties jsProperties = new ConsulDiscoveryProperties(new InetUtils(new InetUtilsProperties()));
for(Map<String,Object> bean : regs) {
bean.put("client", client);
BeanUtils.copyProperties(properties, jsProperties);
jsProperties.setServiceName(bean.get("service_name").toString());
jsProperties.setPort(agentPort);
ConsulServiceRegistry consulService = new ConsulServiceRegistry(client, properties, ttlScheduler, heartbeatProperties);
bean.put("consulService", consulService);
//生成节点信息
NewService service = new NewService();
String appName = ConsulAutoRegistration.getAppName(jsProperties, js_context.getEnvironment());
String id = bean.get("before").toString() + ConsulAutoRegistration.getInstanceId(jsProperties, js_context);
service.setId(id);
if (!jsProperties.isPreferAgentAddress()) {
service.setAddress(jsProperties.getHostname());
}
service.setName(ConsulAutoRegistration.normalizeForDns(appName));
service.setTags(ConsulAutoRegistration.createTags(jsProperties));
if (jsProperties.getPort() != null) {
service.setPort(jsProperties.getPort());
// we know the port and can set the check
ConsulAutoRegistration.setCheck(service, autoServiceRegistrationProperties, jsProperties, js_context, heartbeatProperties);
}
ConsulRegistration reg = new ConsulRegistration(service, jsProperties);
bean.put("consulRegistration", reg);
//注册节点
consulService.register(reg);
}
disposableBeanAdapter.start();
}
}
删除节点,这里要做到自动删除,也要依赖springboot启动和注销顺序触发的事件去删除
@Component
public class DisposableBeanAdapterSub implements SmartLifecycle {
private Logger log = LoggerFactory.getLogger(this.getClass());
private AtomicBoolean running = new AtomicBoolean(false);
@Override
public boolean isAutoStartup() {
return false;
}
@Override
public void stop(Runnable callback) {
callback.run();
if(this.running.compareAndSet(true, false) ) {
//当服务停止时,需要把服务发现列表删除注销当前服务
for(Map<String,Object> bean : MultipleConsulNode.regs) {
ConsulServiceRegistry consulService = (ConsulServiceRegistry) bean.get("consulService");
ConsulRegistration consulRegistration = (ConsulRegistration) bean.get("consulRegistration");
consulService.deregister(consulRegistration);
}
}
}
@Override
public void start() {
this.running.compareAndSet(false, true);
}
@Override
public void stop() {
}
@Override
public boolean isRunning() {
//return false;
return this.running.get();
}
@Override
public int getPhase() {
//执行顺序在这里设置,类似aop,filter的执行链原理,0=启动时最先执行,停止最后执行
return 1;
}
}