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