/* * Copyright 2008-2009 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.hasor.registry.client; import io.netty.util.Timeout; import io.netty.util.TimerTask; import net.hasor.registry.RsfCenterRegister; import net.hasor.registry.RsfCenterResult; import net.hasor.registry.RsfCenterSettings; import net.hasor.registry.domain.client.ConsumerPublishInfo; import net.hasor.registry.domain.client.ProviderPublishInfo; import net.hasor.registry.domain.client.PublishInfo; import net.hasor.rsf.InterAddress; import net.hasor.rsf.RsfBindInfo; import net.hasor.rsf.RsfContext; import net.hasor.rsf.domain.RsfServiceType; import net.hasor.rsf.utils.StringUtils; import net.hasor.rsf.utils.TimerManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.List; import java.util.Set; import static net.hasor.registry.RegistryConstants.Center_Ticket; /** * 负责维护RSF客户端服务在注册中心上的信息。 * @version : 2016年2月18日 * @author 赵永春(zyc@hasor.net) */ class RegistryClientManager implements TimerTask { protected Logger logger = LoggerFactory.getLogger(getClass()); private final RsfContext rsfContext; private final TimerManager timerManager; private final RsfCenterRegister centerRegister; // public RegistryClientManager(RsfContext rsfContext) { this.rsfContext = rsfContext; RsfCenterSettings settings = this.rsfContext.getAppContext().getInstance(RsfCenterSettings.class); ClassLoader loader = rsfContext.getClassLoader(); this.timerManager = new TimerManager(settings.getHeartbeatTime(), "RsfCenterBeatTimer", loader); this.centerRegister = rsfContext.getRsfClient().wrapper(RsfCenterRegister.class); } @Override public void run(Timeout timeout) { try { this.run(); } catch (Exception e) { logger.error(e.getMessage(), e); } this.timerManager.atTime(this); } private void run() throws Exception { if (!this.rsfContext.isOnline()) { return; } List<RsfBindInfo<?>> needBeat = new ArrayList<RsfBindInfo<?>>(); // 需要心跳 List<RsfBindInfo<?>> needRegister = new ArrayList<RsfBindInfo<?>>();// 需要注册 List<RsfBindInfo<?>> needRepair = new ArrayList<RsfBindInfo<?>>(); // 需要重新注册 // //1.对所有服务进行分类 List<String> serviceIDs = rsfContext.getServiceIDs(); List<RsfBindInfo<?>> iterator = new ArrayList<RsfBindInfo<?>>(serviceIDs.size()); for (String serviceID : serviceIDs) { iterator.add(rsfContext.getServiceInfo(serviceID)); } for (RsfBindInfo<?> domain : iterator) { // .如果是工作隐藏模式下那么不参与注册 if (domain == null || domain.isShadow()) { continue; } // - String ticketInfo = (String) domain.getMetaData(Center_Ticket); if (StringUtils.isEmpty(ticketInfo)) { needRegister.add(domain);//需要新注册 } else { needBeat.add(domain);//服务需要进行心跳 } } // //2.服务注册 for (RsfBindInfo<?> domain : needRegister) { this.onlineService(domain); } // //3.服务心跳 if (!needBeat.isEmpty()) { for (RsfBindInfo<?> domain : needBeat) { String serviceID = domain.getBindID(); String registerID = (String) domain.getMetaData(Center_Ticket); try { RsfCenterResult<Boolean> beatResult = this.centerRegister.serviceBeat(registerID, serviceID); if (beatResult == null || !beatResult.isSuccess()) { needRepair.add(domain); if (beatResult == null) { logger.error("serviceBeat failed -> beatResult is null , serviceID ={} ,registerID ={}", serviceID, registerID); } else { logger.error("serviceBeat failed -> error , serviceID ={} ,registerID ={} ,errorCode ={} ,errorMessage ={}", // serviceID, registerID, beatResult.getErrorCode(), beatResult.getErrorMessage()); } continue; } // logger.info("serviceBeat complete -> serviceID ={} ,registerID ={}", serviceID, registerID); } catch (Exception e) { logger.error("serviceBeat error -> serviceID ={} ,registerID ={} , error = {}", serviceID, registerID, e.getMessage(), e); } } } // //4.重新注册服务 for (RsfBindInfo<?> domain : needRepair) { domain.removeMetaData(Center_Ticket); onlineService(domain); } } // // /**同步从注册中心解除注册*/ public synchronized void offline() { logger.info("rsfCenterBeat-> received online signal."); List<String> serviceIDs = rsfContext.getServiceIDs(); for (String serviceID : serviceIDs) { RsfBindInfo<Object> serviceInfo = rsfContext.getServiceInfo(serviceID); if (serviceInfo != null) { this.offlineService(serviceInfo); } } } /**解除服务注册*/ public void offlineService(RsfBindInfo<?> domain) { if (domain == null || !this.rsfContext.isOnline()) { return; } // String serviceID = domain.getBindID(); String registerID = (String) domain.getMetaData(Center_Ticket); try { // // .解除服务注册 if (StringUtils.isBlank(registerID)) { logger.warn("deleteService -> service is not registered, serviceID={}", serviceID); return; } // RsfCenterResult<Boolean> result = this.centerRegister.unRegister(registerID, serviceID); if (result != null && result.isSuccess()) { logger.info("deleteService -> complete.", serviceID); } else { if (result == null) { logger.error("deleteService -> failed , serviceID={} ,result is null.", serviceID); } else { logger.error("deleteService -> failed , serviceID={} ,errorCode={} ,errorMessage={}.", // serviceID, result.getErrorCode(), result.getErrorMessage()); } } } catch (Exception e) { logger.error("deleteService -> failed , serviceID={} ,error={}", domain.getBindID(), e.getMessage(), e); } } // /**服务上线(所有服务都上线)*/ public synchronized void online() { logger.info("rsfCenterBeat-> received online signal."); List<String> serviceIDs = rsfContext.getServiceIDs(); for (String serviceID : serviceIDs) { RsfBindInfo<Object> serviceInfo = rsfContext.getServiceInfo(serviceID); if (serviceInfo != null) { this.onlineService(serviceInfo); } } } /**注册服务到中心*/ public void onlineService(RsfBindInfo<?> domain) { if (domain == null || !this.rsfContext.isOnline()) { return; } try { // .注册服务(提供者/消费者) RsfCenterResult<String> registerInfo = null; if (RsfServiceType.Provider == domain.getServiceType()) { // ProviderPublishInfo info = fillTo(domain, new ProviderPublishInfo()); info.setQueueMaxSize(this.rsfContext.getSettings().getQueueMaxSize()); info.setSharedThreadPool(domain.isSharedThreadPool()); registerInfo = this.centerRegister.registerProvider(info); logger.info("publishService service {} register to center -> {}", domain.getBindID(), registerInfo); } else if (RsfServiceType.Consumer == domain.getServiceType()) { // ConsumerPublishInfo info = fillTo(domain, new ConsumerPublishInfo()); info.setClientMaximumRequest(this.rsfContext.getSettings().getMaximumRequest()); info.setMessage(domain.isMessage()); registerInfo = this.centerRegister.registerConsumer(info); logger.info("receiveService service {} register to center -> {}", domain.getBindID(), registerInfo); } // // .同步拉取地址数据 if (registerInfo != null && registerInfo.isSuccess()) { domain.setMetaData(Center_Ticket, registerInfo.getResult()); pullAddress(domain);//更新地址池 } } catch (Exception e) { logger.error("service {} register to center error-> {}", domain.getBindID(), e.getMessage(), e); } } // /** 拉地址 */ private void pullAddress(RsfBindInfo<?> domain) { if (RsfServiceType.Consumer != domain.getServiceType()) { return;/*只有Consumer才需要pull地址*/ } // .拉地址3次尝试 String serviceID = domain.getBindID(); String registerID = (String) domain.getMetaData(Center_Ticket); String protocol = this.rsfContext.getDefaultProtocol(); logger.info("pullAddress[{}] '{}' 1st.", protocol, serviceID); RsfCenterResult<List<String>> providerResult = this.centerRegister.pullProviders(registerID, serviceID, protocol); if (providerResult == null || !providerResult.isSuccess()) { logger.warn("pullAddress[{}] '{}' 2st.", protocol, serviceID); providerResult = this.centerRegister.pullProviders(registerID, serviceID, protocol); if (providerResult == null || !providerResult.isSuccess()) { logger.error("pullAddress[{}] '{}' 3st.", protocol, serviceID); providerResult = this.centerRegister.pullProviders(registerID, serviceID, protocol); } } // if (providerResult == null || !providerResult.isSuccess()) { if (providerResult == null) { logger.error("pullAddress[{}] {} failed at 3st. -> result is null.", protocol, serviceID); } else { logger.error("pullAddress[{}] {} failed at 3st. -> errorCode ={} ,errorMessage = {}", // protocol, serviceID, providerResult.getErrorCode(), providerResult.getErrorMessage()); } // InterAddress callBackAddress = this.rsfContext.publishAddress(protocol); String callBackTo = callBackAddress.toHostSchema(); logger.info("pullAddress[{}] {} failed try async request pullProviders. callBack is {}", protocol, serviceID, callBackTo); RsfCenterResult<Boolean> result = this.centerRegister.requestPushProviders(registerID, serviceID, protocol, callBackTo); if (result == null || !result.isSuccess()) { if (result == null) { logger.error("asyncPullAddress[{}] {} failed -> result is null.", protocol, serviceID); } else { logger.error("asyncPullAddress[{}] {} failed -> errorCode ={} ,errorMessage = {}", // protocol, serviceID, result.getErrorCode(), result.getErrorMessage()); } } else { logger.info("asyncPullAddress[{}] {} successful -> waiting for the center pull providers.", protocol, serviceID); } return; } // // .准备服务提供者列表 List<String> providerList = providerResult.getResult(); List<InterAddress> newHostSet = new ArrayList<InterAddress>(); if (providerList != null && !providerList.isEmpty()) { for (String providerAddress : providerList) { try { newHostSet.add(new InterAddress(providerAddress)); } catch (Throwable e) { logger.error("pullAddress[{}] '" + providerAddress + "' formater error ->" + e.getMessage(), protocol, e); } } } else { logger.warn("pullAddress[{}] already up-to-date. pull empty.", protocol); } // // .更新服务提供者地址列表 try { this.rsfContext.getUpdater().appendAddress(serviceID, newHostSet); } catch (Throwable e) { logger.error("pullAddress[{}] -> appendAddress failed ,serviceID={} ,message={}.", protocol, serviceID, e.getMessage(), e); } } private <T extends PublishInfo> T fillTo(RsfBindInfo<?> eventData, T info) { // Set<String> protocols = this.rsfContext.runProtocols(); if (protocols == null || protocols.isEmpty()) { throw new IllegalStateException("not running any protocol, please check the configuration."); } StringBuilder addressList = new StringBuilder(""); if (RsfServiceType.Provider == eventData.getServiceType()) { // - 提供者需要上报所有地址 for (String protocol : protocols) { InterAddress interAddress = this.rsfContext.publishAddress(protocol); String rsfURL = interAddress.toHostSchema(); this.logger.info("rsfContext -> doStart , bindAddress : {}", rsfURL); if (addressList.length() > 0) { addressList.append(','); } addressList.append(rsfURL); } } else { // - 订阅者仅上报默认协议地址 String protocol = this.rsfContext.getDefaultProtocol(); InterAddress interAddress = this.rsfContext.publishAddress(protocol); String rsfURL = interAddress.toHostSchema(); addressList.append(rsfURL); } // info.setBindID(eventData.getBindID()); info.setBindGroup(eventData.getBindGroup()); info.setBindName(eventData.getBindName()); info.setBindVersion(eventData.getBindVersion()); info.setBindType(eventData.getBindType().getName()); info.setClientTimeout(eventData.getClientTimeout()); info.setSerializeType(eventData.getSerializeType()); info.setTargetList(addressList.toString()); return info; } }