springboot向服務發現consul註冊多個節點(SmartLifecycle)

一個服務正常情況下,應該只會註冊一個節點,但是出於某些原因,需要把多個節點合併爲一個節點,但是不能影響到其它節點的調用,除非去通知服務調用人員,改一下調用接口.但是要把所有調用端都改完,還是得花些時間的…
這裏就是以最小時間成本,合併服務.

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;
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章