Package com.bj58.spat.gaea.client.loadbalance

Source Code of com.bj58.spat.gaea.client.loadbalance.Server

/*
*  Copyright Beijing 58 Information Technology Co.,Ltd.
*
*  Licensed to the Apache Software Foundation (ASF) under one
*  or more contributor license agreements.  See the NOTICE file
*  distributed with this work for additional information
*  regarding copyright ownership.  The ASF licenses this file
*  to you 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 com.bj58.spat.gaea.client.loadbalance;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import com.bj58.spat.gaea.client.communication.socket.CSocket;
import com.bj58.spat.gaea.client.communication.socket.ScoketPool;
import com.bj58.spat.gaea.client.communication.socket.ThreadRenameFactory;
import com.bj58.spat.gaea.client.configuration.loadbalance.ServerProfile;
import com.bj58.spat.gaea.client.loadbalance.component.ServerState;
import com.bj58.spat.gaea.client.utility.logger.ILog;
import com.bj58.spat.gaea.client.utility.logger.LogFactory;
import com.bj58.spat.gaea.protocol.sfp.v1.Protocol;

/**
* Server
*
* @author Service Platform Architecture Team (spat@58.com)
*/
public class Server {

    private static ILog logger = LogFactory.getLogger(Server.class);
    private String name;
    private String address;
    private int port;
    private int weight;
    private float weightRage;
    private ServerState state;
    private ScoketPool scoketpool;
    private int currUserCount;
    private int deadTimeout;
    private long deadTime;
    private boolean testing = false;
    private final ScheduledExecutorService scheduler;

    protected Server(ServerProfile config) {
        this.name = config.getName();
        this.address = config.getHost();
        this.port = config.getPort();
        this.weightRage = config.getWeithtRate();
        this.deadTimeout = config.getDeadTimeout();
        if (this.weightRage >= 0) {
            this.state = ServerState.Normal;
        } else {
            this.state = ServerState.Disable;
        }
        scheduler = Executors.newScheduledThreadPool(2,new ThreadRenameFactory("Async "+this.getName()+"-Server Thread"));
    }

    public Protocol request(Protocol p) throws Exception, Throwable {
        if (state == ServerState.Dead) {
          logger.warn("This proxy server is unavailable.state:" + state + "+host:" + address);
          throw new Exception("This proxy server is unavailable.state:" + state + "+host:" + address);
        }
       
        increaseCU();
        CSocket socket = null;
        try {
            try {
              socket = this.scoketpool.getSocket();
                byte[] data = p.toBytes(socket.isRights(),socket.getDESKey());
                socket.registerRec(p.getSessionID());
                socket.send(data)
            } catch (Throwable ex) {
                logger.error("Server get socket Exception", ex);
                throw ex;
            }finally {
              if(socket != null){
                socket.dispose();
              }
            }
            byte[] buffer = socket.receive(p.getSessionID(), currUserCount);
            Protocol result = Protocol.fromBytes(buffer,socket.isRights(),socket.getDESKey());
            if (this.state == ServerState.Testing) {
                relive();
            }
            return result;
        } catch (IOException ex) {
            logger.error("io exception", ex);
            if (socket == null || !socket.connecting()) {
                if (!test()) {
                    markAsDead();
                }
            }
            throw ex;
        } catch (Throwable ex) {
            logger.error("request other Exception", ex);
            throw ex;
        } finally {
            if (state == state.Testing) {
                markAsDead();
            }
            if (socket != null) {
                socket.unregisterRec(p.getSessionID());
            }
            decreaseCU();
        }
    }

    /**
     * Increase current user
     */
    private synchronized void increaseCU() {
        currUserCount++;
    }

    /**
     * Decrease current user
     */
    private synchronized void decreaseCU() {
        currUserCount--;
        if (currUserCount <= 0) {
            currUserCount = 0;
        }
    }

    /**
     * mark Server to dead
     * @throws IOException
     */
    private void markAsDead() throws Exception {
        logger.info("markAsDead server:" + this.state + "--server hashcode:" + this.hashCode() + "--conn count:" + this.scoketpool.count());
        if (this.state == ServerState.Dead) {
            logger.info("before markAsDead the server is dead!!!");
            return;
        }
        synchronized (this) {
            if (this.state == ServerState.Dead) {
                logger.info("before markAsDead the server is dead!!!");
                return;
            }
            logger.warn("this server is dead!host:" + address);
            this.setState(ServerState.Dead);
            this.deadTime = System.currentTimeMillis();
            this.scoketpool.destroy();
        }
    }
   
    /**
     * 设置当前重启服务
     * @param server
     * @throws Throwable
     * @throws Exception
     */
    public void createReboot() throws Exception, Throwable{
      synchronized(this){
        if (this.state == ServerState.Reboot) {
              logger.info("before markAsReboot the server is Reboot!");
                return;
            }
       
        logger.warn("this server is reboot! host:" + address);
        this.setState(ServerState.Reboot);//设置当前服务为重启状态
            this.setDeadTime(System.currentTimeMillis());
            /**
             * 如果当前连接处于重启状态则注销当前服务所有socket
             * 任务调度 3秒后执行
             */
            scheduler.schedule(new TimerJob(this), 3, TimeUnit.SECONDS);
      }
    }
   
    /**
     * 设置当前服务为正常状态
     */
    public void markAsNormal(){
      this.relive();
    }
   
    /**
     * relive Server if this Server is died
     */
    private void relive() {
        logger.info("this server is relive!host:" + address);
        if (this.state == ServerState.Normal) {
            return;
        }
        synchronized (this) {
            if (this.state == ServerState.Normal) {
                return;
            }
            logger.info("this server is relive!host:" + address);
            this.state = ServerState.Normal;
        }
    }

    private boolean test() {
        if (testing) {
            return true;
        }
        testing = true;
        boolean result = false;
        try {
            Socket socket = new Socket();
            socket.connect(new InetSocketAddress(this.address, this.port), 100);
            socket.close();
            result = true;
        } catch (Exception e) {
        } finally {
            logger.info("test server :" + this.address + ":" + this.port + "--alive:" + result);
            testing = false;
        }
        return result;
    }
   
    public boolean testing(){
      return this.test();
    }
   
    public long getDeadTime() {
        return deadTime;
    }

    public void setDeadTime(long deadTime) {
        this.deadTime = deadTime;
    }

    public String getName() {
        return name;
    }

    public String getAddress() {
        return address;
    }
   
    public int getCurrUserCount() {
        return currUserCount;
    }

    public int getPort() {
        return port;
    }

    public ScoketPool getScoketpool() {
        return scoketpool;
    }

    protected void setScoketpool(ScoketPool scoketpool) {
        this.scoketpool = scoketpool;
    }

    public ServerState getState() {
        return state;
    }

    protected synchronized void setState(ServerState state) {
        this.state = state;
    }

    public int getWeight() {
        return weight;
    }

    public float getWeightRage() {
        return weightRage;
    }

    public int getDeadTimeout() {
        return deadTimeout;
    }

    protected void setDeadTimeout(int deadTimeout) {
        this.deadTimeout = deadTimeout;
    }
   
    @Override
    public String toString() {
        return "Name:" + name + ",Address:" + address + ",Port:" + port + ",Weight:" + weight + ",State:" + state.toString() + ",CurrUserCount:" + currUserCount + ",ScoketPool:" + scoketpool.count();
    }
}
TOP

Related Classes of com.bj58.spat.gaea.client.loadbalance.Server

TOP
Copyright © 2015 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.