双机热备份Heartbeat sender and receiver实现

我们开发过程中如果要实现双机热备份,为了及时获取两台Server之间的连接状态,需要通过”心跳“机制来实现, 以下是 HeartBeatSendService 和 HeartBeatReceiveService的实现,可供参考:

HeartBeatRes.java: 用于作为封装heartbeat message的类

public class HeartBeatRes {
	private byte opModeStatus;
	private String sysVersion;

	public byte getOpModeStatus() {
		return opModeStatus;
	}

	public void setOpModeStatus(byte opModeStatus) {
		this.opModeStatus = opModeStatus;
	}

	public String getSysVersion() {
		return sysVersion;
	}

	public void setSysVersion(String sysVersion) {
		this.sysVersion = sysVersion;
	}
}

HeartBeatSendService.java: 负责发送heartbeat message, 每秒发送一次

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

@Service
public class HeartBeatSendService {
	private DatagramSocket datagramSocket ;
	private String remoteHost;
	private int remotePort;
	private static int SEND_MESSAGE_INTERVAL = 1000;
	private Gson gson = new GsonBuilder().create();
	private SendThread sendThread;
	private boolean isStop = false;
	private Logger logger = LoggerFactory.getLogger(HeartBeatSendService.class);
	
    public static final byte SYSTEM_OPMODE_STATUS_STANDBY = 0;
    public static final byte SYSTEM_OPMODE_STATUS_ACTIVE = 1;
	
	
	public void start(String remoteHost, int remotePort, int localPort){
		try {
			isStop = false;
			this.stop();
			datagramSocket = new DatagramSocket(localPort);
			this.remoteHost = remoteHost;
			this.remotePort = remotePort;

			sendThread = new SendThread();
			sendThread.setName("HeartBeat Send Thread");
			sendThread.start();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public void stop() {
		if (datagramSocket != null) {
			datagramSocket.close();
		}
		
		if(sendThread != null){
			sendThread.stopThread();
			sendThread = null;
		}
	}
	
	public class SendThread extends Thread {
		public void stopThread(){
			isStop = true;
			 // Wake up the thread
            synchronized (this) {
                this.notify();
            }
		}
		
		public void run(){
			while(!isStop){
				try {
					Thread.sleep(SEND_MESSAGE_INTERVAL);  //控制每秒发一次
				} catch (InterruptedException e) {
					logger.error(e.getMessage(), e);
				}
				
				try {
					HeartBeatRes res = new HeartBeatRes();
					res.setOpModeStatus(SYSTEM_OPMODE_STATUS_ACTIVE);
					res.setSysVersion("1.0");
					String message = gson.toJson(res);
					byte[] bs = message.getBytes();
					DatagramPacket packet = new DatagramPacket(bs, bs.length, InetAddress.getByName(remoteHost), remotePort);
					datagramSocket.send(packet);
					logger.debug("Send 1+1 heartbeat message:{}  length:{} to remote server:{}", new String(bs),  String.valueOf(packet.getLength()),  remoteHost.toString());
				} catch (Throwable e) {
					logger.error(e.getMessage(), e);
				}
			}
		}
		
	}
	
}

HeartBeatReceiveService.java: : 负责接收heartbeat message

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.altai.ac.care.data.exception.NotFoundException;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

@Service
public class HeartBeatReceiveService{
	@Autowired
	private ReplicationService repService;
	private Logger logger = LoggerFactory.getLogger(HeartBeatReceiveService.class);
	
	private DatagramSocket socket;
	private ReceiveThread recvThread;
	private Gson gson = new GsonBuilder().create();
	private static short SO_TIMEOUT = 3000;
	
	private boolean isStop = false;
	private int soTimeout = SO_TIMEOUT;
	
	public void start(int localPort){
		try {
			isStop = false;
			
			this.stop();
			socket = new DatagramSocket(localPort);
			socket.setSoTimeout(soTimeout);  // 用于设置Socket Timeout, 如果3s没收到message, 认为两台server是断连接了
			recvThread = new ReceiveThread();
			recvThread.start();
			
		} catch (SocketException e) {
			e.printStackTrace();
		}
	}
	
	
	public void stop() {
		if (socket != null) {
			socket.close();
		}
		
		if (recvThread != null) {
			recvThread.stopThread();
			recvThread = null;
		}
	}
	
	
	private void parseData(DatagramPacket datagramPacket) throws IOException, NotFoundException, InterruptedException{
		byte[] data = datagramPacket.getData();
		int length = datagramPacket.getLength();
		String jsonData = new String(data, 0, length);
		HeartBeatRes heartBeatRes = gson.fromJson(jsonData, HeartBeatRes.class);
		// 正常收到数据, 两台server是通的
        // 收到的message可根据需要处理

	}

	public class ReceiveThread extends Thread{
		public void stopThread(){
			isStop = true;
			 // Wake up the thread
            synchronized (this) {
                this.notify();
            }
		}
		
		public void run() {
			while (!isStop) {
				try {
					byte[] content = new byte[1024];
					DatagramPacket datagramPacket = new DatagramPacket(content, content.length);
					if (socket != null) {
						socket.receive(datagramPacket);
						parseData(datagramPacket);
					}
				} catch (Throwable e) {
					// socket timeout handler
                    // 可以处理两台server 未连接等情况
				}
			}
		}
	}
	

}

以上代码在源码基础上做了些修改, 没有细测, 理解即可! ^_^

你可能感兴趣的:(JAVA)