net.hasor.registry.client.RegistryClientManager.java Source code

Java tutorial

Introduction

Here is the source code for net.hasor.registry.client.RegistryClientManager.java

Source

/*
 * 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 : 2016218
 * @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;
    }
}