有三种事件的类型:
- InstanceAddedEvent
- InstanceRemovedEvent
- ServiceChangedEvent
一个事件发布器:AbstractEventListener
它实现了ApplicationEventPublisherAware接口会注入进一个事件发布器,同时启动一个定时任务,每十秒执行一次,主要是通过连接注册中心去监听服务的上下线和改变,然后发布相应的事件,去触发监听该事件的的事件监听器。
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package org.hzero.register.event.listener;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.PropertyFilter;
import com.alibaba.fastjson.serializer.SerializerFeature;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import org.hzero.register.event.config.RegisterEventListenerProperties;
import org.hzero.register.event.event.InstanceAddedEvent;
import org.hzero.register.event.event.InstanceRemovedEvent;
import org.hzero.register.event.util.MD5Util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
public abstract class AbstractEventListener implements ApplicationEventPublisherAware {
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractEventListener.class);
private DiscoveryClient discoveryClient;
private RegisterEventListenerProperties properties;
private ApplicationEventPublisher publisher;
private ScheduledExecutorService scheduler;
public AbstractEventListener() {
}
public void setDiscoveryClient(DiscoveryClient discoveryClient) {
this.discoveryClient = discoveryClient;
}
public void setProperties(RegisterEventListenerProperties properties) {
this.properties = properties;
}
public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
this.publisher = publisher;
this.start();
}
private void start() {
this.scheduler = new ScheduledThreadPoolExecutor(1, (r) -> {
return new Thread(r, "register-event-scheduler");
});
this.scheduler.scheduleAtFixedRate(new AbstractEventListener.PollTask(), 0L, this.properties.getPollInterval(), TimeUnit.SECONDS);//定时任务
}
static class CustomPropertyPreFilter implements PropertyFilter {
private String[] excludes;
public CustomPropertyPreFilter(String... excludes) {
this.excludes = excludes;
}
public boolean apply(Object object, String name, Object value) {
String[] var4 = this.excludes;
int var5 = var4.length;
for(int var6 = 0; var6 < var5; ++var6) {
String exclude = var4[var6];
if (exclude == null) {
return true;
}
if (exclude.equals(name)) {
return false;
}
}
return true;
}
}
class PollTask implements Runnable {
private AbstractEventListener.CustomPropertyPreFilter filter = new AbstractEventListener.CustomPropertyPreFilter(new String[]{"leaseInfo", "lastDirtyTimestamp", "lastUpdatedTimestamp"});
private String cacheMD5 = "";
private Set<String> serviceCache = new HashSet();
private Map<String, Set<String>> instanceMapCache = new HashMap();
private int serviceDownCount = 0;
private Map<String, AtomicInteger> instanceDownCountMap = new HashMap();
PollTask() {
}
public void run() {
Set<String> services = this.serviceCache;
Map<String, Set<String>> instanceMap = this.instanceMapCache;
String MD5 = this.cacheMD5;
try {
long start = System.currentTimeMillis();
services = new HashSet(AbstractEventListener.this.discoveryClient.getServices());
if (((Set)services).isEmpty()) {
++this.serviceDownCount;
if (this.serviceDownCount > AbstractEventListener.this.properties.getMaxServiceDownTimes()) {
this.publishServiceChangedEvent(this.serviceCache, (Set)services, instanceMap, new HashMap(0));//发布事件
return;
}
return;
}
this.serviceDownCount = 0;
Map<String, ServiceInstance> serviceInstanceMap = new HashMap(16);
instanceMap = (Map)((Set)services).stream().collect(Collectors.toMap((service) -> {
return service;
}, (service) -> {
List<ServiceInstance> serviceInstances = AbstractEventListener.this.discoveryClient.getInstances(service);
AtomicInteger count = (AtomicInteger)this.instanceDownCountMap.computeIfAbsent(service, (k) -> {
return new AtomicInteger(0);
});
if (serviceInstances.isEmpty()) {
if (count.incrementAndGet() > AbstractEventListener.this.properties.getMaxInstanceDownTimes()) {
return Collections.emptySet();
} else {
Set<String> instances = (Set)this.instanceMapCache.get(service);
return instances == null ? Collections.emptySet() : instances;
}
} else {
count.set(0);
return (Set)serviceInstances.stream().map((serviceInstance) -> {
String json = JSON.toJSONString(serviceInstance, this.filter, new SerializerFeature[0]);
serviceInstanceMap.put(json, serviceInstance);
return json;
}).collect(Collectors.toSet());
}
}));
MD5 = MD5Util.encrypt(instanceMap.toString());
if (this.cacheMD5.equals(MD5)) {
return;
}
this.publishServiceChangedEvent(this.serviceCache, (Set)services, instanceMap, serviceInstanceMap);
long end2 = System.currentTimeMillis();
AbstractEventListener.LOGGER.debug("getList and publish event cost : " + (end2 - start) + "ms");
} catch (Throwable var12) {
AbstractEventListener.LOGGER.error("pollTask throw exception :", var12);
} finally {
this.serviceCache = (Set)services;
this.instanceMapCache = instanceMap;
this.cacheMD5 = MD5;
}
}
private void publishServiceChangedEvent(Set<String> oldServices, Set<String> newServices, Map<String, Set<String>> instanceMap, Map<String, ServiceInstance> serviceInstanceMap) {
this.compareAndExecute(oldServices, newServices, this::publishInstanceRemovedEvent, this::publishInstanceAddedEvent);
Iterator var5 = oldServices.iterator();
while(var5.hasNext()) {
String service = (String)var5.next();
Set<String> oldInstanceSet = (Set)this.instanceMapCache.get(service);
Set<String> newInstanceSet = (Set)instanceMap.get(service);
if (!oldInstanceSet.equals(newInstanceSet)) {
this.compareAndExecute(oldInstanceSet, newInstanceSet, (removedInstanceSet) -> {
Iterator var4 = removedInstanceSet.iterator();
while(var4.hasNext()) {
String serviceInstanceJson = (String)var4.next();
try {
AbstractEventListener.this.publisher.publishEvent(new InstanceRemovedEvent(this, service, (ServiceInstance)serviceInstanceMap.get(serviceInstanceJson)));
} catch (Throwable var7) {
AbstractEventListener.LOGGER.error("publishEvent error", var7);
}
}
}, (addedInstanceSet) -> {
Iterator var4 = addedInstanceSet.iterator();
while(var4.hasNext()) {
String serviceInstanceJson = (String)var4.next();
try {
AbstractEventListener.this.publisher.publishEvent(new InstanceAddedEvent(this, service, (ServiceInstance)serviceInstanceMap.get(serviceInstanceJson)));
} catch (Throwable var7) {
AbstractEventListener.LOGGER.error("publishEvent error", var7);
}
}
});
}
}
}
private void compareAndExecute(Set<String> set1, Set<String> set2, FunctionX f1, FunctionX f2) {
if (set1 == null) {
set1 = new HashSet();
}
if (set2 == null) {
set2 = new HashSet();
}
Set<String> oldTmp = new HashSet((Collection)set1);
Set<String> newTmp = new HashSet((Collection)set2);
oldTmp.removeAll((Collection)set2);
newTmp.removeAll((Collection)set1);
if (!oldTmp.isEmpty()) {
f1.apply(oldTmp);
}
if (!newTmp.isEmpty()) {
f2.apply(newTmp);
}
}
private void publishInstanceAddedEvent(Set<String> addedServices) {
Iterator var2 = addedServices.iterator();
while(var2.hasNext()) {
String service = (String)var2.next();
List<ServiceInstance> serviceInstances = AbstractEventListener.this.discoveryClient.getInstances(service);
Iterator var5 = serviceInstances.iterator();
while(var5.hasNext()) {
ServiceInstance serviceInstance = (ServiceInstance)var5.next();
try {
AbstractEventListener.this.publisher.publishEvent(new InstanceAddedEvent(this, service, serviceInstance));
} catch (Throwable var8) {
AbstractEventListener.LOGGER.error("publishEvent error", var8);
}
}
}
}
private void publishInstanceRemovedEvent(Set<String> removedServices) {
Iterator var2 = removedServices.iterator();
while(var2.hasNext()) {
String service = (String)var2.next();
List<ServiceInstance> serviceInstances = AbstractEventListener.this.discoveryClient.getInstances(service);
Iterator var5 = serviceInstances.iterator();
while(var5.hasNext()) {
ServiceInstance serviceInstance = (ServiceInstance)var5.next();
try {
AbstractEventListener.this.publisher.publishEvent(new InstanceRemovedEvent(this, service, serviceInstance));
} catch (Throwable var8) {
AbstractEventListener.LOGGER.error("publishEvent error", var8);
}
}
}
}
}
}