SpringCloud eureka服務狀態監聽

一.前言

  近期因爲公司不一樣平臺項目之間的業務整合,須要作到相互訪問! 每一個平臺均有本身的註冊中心和服務,且註冊中心相互之間並無相互註冊!
  藉助spring的事件監聽,在eureka-server端監聽服務註冊,將全部服務的ip和port存放至redis庫,而後讓其餘平臺服務經過redis庫獲取ip和端口號,進而進行http調用.結構圖以下:
調用關係

二.事件解析

事件列表

 在 org.springframework.cloud.netflix.eureka.server.event包下會發現以下類:
事件列表
  • EurekaInstanceCanceledEvent: 服務下線事件
  • EurekaInstanceRegisteredEvent: 服務註冊事件
  • EurekaInstanceRenewedEvent: 服務續約事件
  • EurekaRegistryAvailableEvent: eureka註冊中心啓動事件
  • EurekaServerStartedEvent: eureka server啓動時間

源碼分析

  打開 org.springframework.cloud.netflix.eureka.server.InstanceRegistry類,會發現當eureka服務續約、註冊、取消等時,spring會publish不一樣的事件,對應的事件類就是上面的列表.
續約事件
@Override
    public boolean renew(final String appName, final String serverId,
            boolean isReplication) {
        log("renew " + appName + " serverId " + serverId + ", isReplication {}"
                + isReplication);
        List<Application> applications = getSortedApplications();
        for (Application input : applications) {
            if (input.getName().equals(appName)) {
                InstanceInfo instance = null;
                for (InstanceInfo info : input.getInstances()) {
                    if (info.getId().equals(serverId)) {
                        instance = info;
                        break;
                    }
                }
                // 發佈續約事件
                publishEvent(new EurekaInstanceRenewedEvent(this, appName, serverId,
                        instance, isReplication));
                break;
            }
        }
        return super.renew(appName, serverId, isReplication);
    }
註冊事件
@Override
    public void register(InstanceInfo info, int leaseDuration, boolean isReplication) {
        handleRegistration(info, leaseDuration, isReplication);
        super.register(info, leaseDuration, isReplication);
    }
    
        private void handleRegistration(InstanceInfo info, int leaseDuration,
            boolean isReplication) {
        log("register " + info.getAppName() + ", vip " + info.getVIPAddress()
                + ", leaseDuration " + leaseDuration + ", isReplication "
                + isReplication);
        // 發佈註冊事件
        publishEvent(new EurekaInstanceRegisteredEvent(this, info, leaseDuration,
                isReplication));
    }

事件監聽

  經過上面的源碼追溯,咱們已經獲得對應的事件類了,因此如今要作的僅僅是監聽對應的事件便可,至此已經完成了咱們所須要對事件監聽後的業務處理!
@Component
public class EurekaStateChangeListener {

    @Value("${iptable.platform}")
    private String platform;
    
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    private static Logger logger = LoggerFactory.getLogger(EurekaStateChangeListener.class);
    private static final String COLON = ":";

    @EventListener//(condition = "#event.replication==false")
    public void listen(EurekaInstanceCanceledEvent eurekaInstanceCanceledEvent) {
        // 服務斷線事件
        String appName = eurekaInstanceCanceledEvent.getAppName();
        String serverId = eurekaInstanceCanceledEvent.getServerId();
        Objects.requireNonNull(appName, "服務名不能爲空!");

        SetOperations<String, String> opsForSet = redisTemplate.opsForSet();
        opsForSet.remove((platform + appName).toLowerCase(), serverId);
        logger.info(">>>>>>> 失效服務:{},已被剔除!", serverId);
    }

    @EventListener//(condition = "#event.replication==false")
    public void listen(EurekaInstanceRegisteredEvent event) {
        // 服務註冊
        InstanceInfo instanceInfo = event.getInstanceInfo();
        String appName = instanceInfo.getAppName();
        Objects.requireNonNull(appName, "服務名不能爲空!");

        SetOperations<String, String> opsForSet = redisTemplate.opsForSet();
        opsForSet.add((platform + appName).toLowerCase(), instanceInfo.getIPAddr() + COLON + instanceInfo.getPort());
        logger.info(">>>>>>> 服務名:{},端口號:{},已緩存至redis", appName, instanceInfo.getPort());
    }

    @EventListener//(condition = "#event.replication==false")
    public void listen(EurekaInstanceRenewedEvent event) {
        // 服務續約
        logger.info(">>>>>>>>>>>>>>>Server續約:" + event.getServerId());
    }

    @EventListener
    public void listen(EurekaRegistryAvailableEvent event) {
        // 註冊中心啓動
        logger.info(">>>>>>>>>>>>>>>Server註冊中心:" + event);
    }

    @EventListener
    public void listen(EurekaServerStartedEvent event) {
        // Server啓動
        logger.info(">>>>>>>>>>>>>>>Server啓動:" + event);
    }
}

注意事項

  • [ ] 版本問題:
  當時項目組用的SpringCloud版本是Brixton.RELEASE,該版本有一個問題就是服務註冊和下線並不會出發對應的事件,因此致使一直監聽不到.解決的辦法也很簡單,只要升級版本便可,我已經升級到最新版本Finchley.RELEASE.
  傳送門, 點我
 
  • [ ] 重複監聽:

例如,在續約的時候,eureka會發出2條EurekaInstanceRenewedEvent事件,可是2條事件的屬性卻不同!一個事件的屬性replication爲true,另一個爲false.若是咱們只想處理replication=true的事件,以下配置便可:java

@EventListener(condition = "#event.replication==false")
    public void listen(EurekaInstanceRenewedEvent event) {
        // 服務續約
        logger.info(">>>>>>>>>>>>>>>Server續約:" + event.getServerId());
    }

GitHub代碼,點我git

相關文章
相關標籤/搜索