@Override
	public void onResourceUpdated(ServiceEventKey svcEventKey, RegistryCacheValue oldValue,
			RegistryCacheValue newValue) {
		if (newValue.getEventType() == ServiceEventKey.EventType.SERVICE) {
			if (oldValue instanceof ServicesByProto && newValue instanceof ServicesByProto) {
				LOG.debug("receive service={} change event", svcEventKey);
				Set<String> oldServiceInfoSet = ((ServicesByProto) oldValue).getServices().stream()
						.map(i -> i.getNamespace() + "::" + i.getService()).collect(Collectors.toSet());
				Set<String> newServiceInfoSet = ((ServicesByProto) newValue).getServices().stream()
						.map(i -> i.getNamespace() + "::" + i.getService()).collect(Collectors.toSet());

				Sets.SetView<String> addServiceInfoSetView = Sets.difference(newServiceInfoSet, oldServiceInfoSet);
				Sets.SetView<String> deleteServiceInfoSetView = Sets.difference(oldServiceInfoSet, newServiceInfoSet);

				if (addServiceInfoSetView.isEmpty() && deleteServiceInfoSetView.isEmpty()) {
					return;
				}
				LOG.info("Service status is update. Add service of {}. Delete service of {}", addServiceInfoSetView, deleteServiceInfoSetView);

				// Trigger reload of gateway route cache.
				this.publisher.publishEvent(new HeartbeatEvent(this, INDEX.getAndIncrement()));
			}
		}
		else if (newValue.getEventType() == ServiceEventKey.EventType.INSTANCE) {
			if (oldValue instanceof ServiceInstancesByProto && newValue instanceof ServiceInstancesByProto) {
				LOG.debug("receive service instances={} change event", svcEventKey);
				ServiceInstancesByProto oldIns = (ServiceInstancesByProto) oldValue;
				ServiceInstancesByProto newIns = (ServiceInstancesByProto) newValue;
				if ((CollectionUtils.isEmpty(oldIns.getInstances()) && !CollectionUtils.isEmpty(newIns.getInstances())) ||
						(!CollectionUtils.isEmpty(oldIns.getInstances()) && CollectionUtils.isEmpty(newIns.getInstances()))) {
					LOG.info("Service status of {} is update.", newIns.getService());

					// Trigger reload of gateway route cache.
					this.publisher.publishEvent(new HeartbeatEvent(this, INDEX.getAndIncrement()));
				}
			}
		}
	}
@Test
	public void testOnResourceUpdated() {
		PolarisServiceStatusChangeListener polarisServiceStatusChangeListener = new PolarisServiceStatusChangeListener();
		polarisServiceStatusChangeListener.setApplicationEventPublisher(publisher);

		// Service update event
		ServiceEventKey serviceUpdateEventKey = new ServiceEventKey(
				new ServiceKey(NAMESPACE_TEST, SERVICE_PROVIDER), ServiceEventKey.EventType.SERVICE);
		ServiceInfo serviceInfo = new ServiceInfo();
		serviceInfo.setNamespace(NAMESPACE_TEST);
		serviceInfo.setService(SERVICE_PROVIDER);
		// Need update
		ServicesByProto oldServices = new ServicesByProto(Collections.emptyList());
		ServicesByProto newServices = new ServicesByProto(Collections.singletonList(serviceInfo));
		polarisServiceStatusChangeListener.onResourceUpdated(serviceUpdateEventKey, oldServices, newServices);
		verify(publisher, times(1)).publishEvent(any(ApplicationEvent.class));
		// No need update
		oldServices = new ServicesByProto(Collections.singletonList(serviceInfo));
		newServices = new ServicesByProto(Collections.singletonList(serviceInfo));
		polarisServiceStatusChangeListener.onResourceUpdated(serviceUpdateEventKey, oldServices, newServices);
		verify(publisher, times(1)).publishEvent(any(ApplicationEvent.class));


		// Instance update event
		ServiceEventKey instanceUpdateEventKey = new ServiceEventKey(
				new ServiceKey(NAMESPACE_TEST, SERVICE_PROVIDER), ServiceEventKey.EventType.INSTANCE);
		DefaultInstance instance = new DefaultInstance();
		instance.setNamespace(NAMESPACE_TEST);
		instance.setService(SERVICE_PROVIDER);
		instance.setHost(HOST);
		instance.setPort(PORT);
		try {
			Field instances = ServiceInstancesByProto.class.getDeclaredField("instances");
			instances.setAccessible(true);

			// Need update
			ServiceInstancesByProto oldInstances = new ServiceInstancesByProto();
			instances.set(oldInstances, Collections.emptyList());
			ServiceInstancesByProto newInstances = new ServiceInstancesByProto();
			instances.set(newInstances, Collections.singletonList(instance));
			polarisServiceStatusChangeListener.onResourceUpdated(instanceUpdateEventKey, oldInstances, newInstances);
			verify(publisher, times(2)).publishEvent(any(ApplicationEvent.class));

			// No need update
			oldInstances = new ServiceInstancesByProto();
			instances.set(oldInstances, Collections.singletonList(instance));
			newInstances = new ServiceInstancesByProto();
			instances.set(newInstances, Collections.singletonList(instance));
			polarisServiceStatusChangeListener.onResourceUpdated(instanceUpdateEventKey, oldInstances, newInstances);
			verify(publisher, times(2)).publishEvent(any(ApplicationEvent.class));
		}
		catch (NoSuchFieldException | IllegalAccessException e) {
			Assertions.fail("Exception encountered.", e);
		}
	}