JavaWeb服务实现心跳检测(双机热备)

JavaWeb服务心跳检测(双机热备)

实现JavaWeb服务的双机热备操作,这里通过WebSocket方式,设置每个一段时间发送TCP报文,通过报文接收的结果来限制主从服务的运行。

1.主服务心跳发送端代码

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

import javax.annotation.Resource;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONObject;

/** 
* @author 作者 : xxxxx
* @version 创建时间:2021年8月22日 上午9:18:24 
* 心跳检测-----主服务器发送send服务
*/
public class HeartSend implements ServletContextListener  {

    private SocketThread socketThread;
    
    public void contextDestroyed(ServletContextEvent arg0) { 
    	
    }  
   
    @Override 
    public void contextInitialized(ServletContextEvent arg0) {  
        if(null==socketThread)  
        {  
         //新建线程类  
         socketThread=new SocketThread(null);  
         //启动线程  
         socketThread.start();  
        }  
    }   
}


class SocketThread extends Thread {
	private ServerSocket serverSocket = null;  
       
    public SocketThread(ServerSocket serverScoket){  
        try {  
            if(null == serverSocket){  
                this.serverSocket = new ServerSocket(9998);  
            }  
        } catch (Exception e) {  
            System.out.println("SocketThread创建socket服务出错");  
            e.printStackTrace();  
        }  
   
    }  
       
    public void run(){  
        try {  
            if(serverSocket==null){
                return;
            }else if(serverSocket.isClosed()){
            	return;
            }
            Socket socket = serverSocket.accept();  
            if(null != socket && !socket.isClosed()){     
                //处理接受的数据  
                Thread t1 = new Thread(new SocketOperate(socket));  
                t1.start();  
            }else{
            	return;
            }
        }catch (Exception e) {  
            System.out.println("SocketThread创建socket服务出错");  
            e.printStackTrace();  
             
        }  
    }  
       
    public void closeSocketServer(){  
       try {  
            if(null!=serverSocket && !serverSocket.isClosed())  
            {  
             serverSocket.close();  
            }  
       } catch (IOException e) {  
        e.printStackTrace();  
       }  
     }  
       
}


class SocketOperate implements Runnable {  
     private Socket socket;   
     public SocketOperate(Socket socket) throws IOException {  
         this.socket = socket;  
     }  
    
     @Override 
     public void run() {  
         try {  
        	 ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
             while(true){ 
    				Thread.sleep(5000); // 每5秒钟发送一次心跳检测信息
    				JSONObject jobject = new JSONObject();
    				jobject.put("type", "heart");
    				jobject.put("message", "主服务器发送心跳检测信息!");
    				oos.writeObject(jobject);
    				oos.flush();
             }
         } catch (Exception e) {  
        	 e.printStackTrace();  
         } finally{
        	 try {
 				socket.close();
 			 } catch (IOException e) {
 				e.printStackTrace();
 			 }
         }
     }  
     
 }

通过启动一个线程方式实现socket方式每个5秒钟发送一次心跳信息,供监听端接收

2.从服务心跳接收端代码:

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Properties;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.apache.ibatis.javassist.bytecode.stackmap.TypeData.ClassName;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONObject;

/** 
* @author 作者 : xxxxx
* @version 创建时间:2021年8月22日 下午3:47:33 
* 心跳检测 ----从服务器监听listen服务
*/
public class HeartListen implements ServletContextListener {
	public static String heartStatus = "error";  //从服务器是否能够发送告警标识(error不能发送,success能够发送)
	
	private static Socket socket;
	public static boolean connect_state = false;
	private static SocketThread1 socketThread;
	
	private static Properties prop = PropertiesUtils.getProperties("db.properties");
    public static String HostHeardIp = prop.getProperty("HostHeardIp");//获取主服务器地址
	
	@Override
	public void contextDestroyed(ServletContextEvent arg0) {
		
	}

	@Override
	public void contextInitialized(ServletContextEvent arg0) {
		while(!connect_state){
			connect(); // 连接主程序
			try {
				Thread.sleep(3000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	
	//连接主服务器地址
	private static void connect(){
		try {
			//新建线程类  
	         socketThread=new SocketThread1(socket);  
	         //启动线程  
	         socketThread.start();  
		} catch (Exception e) {
			e.printStackTrace();
			connect_state = false;
		}
	}
	
	//实现服务连接断掉之后的重连接
	public static void reconnect(){
		while(!connect_state){
			connect();
			try {
				Thread.sleep(3000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

}

class SocketThread1 extends Thread
{ 
    private Socket socket;
    public SocketThread1(Socket socket){  
        this.socket = socket;
    }  
       
    public void run(){  
        try {  
        	socket = new Socket(HeartListen.HostHeardIp,9998);
			new Thread(new ClientListen(socket)).start(); // 从服务器接收信息
    		new Thread(new ClientHeart(socket)).start(); // 检测主从服务器连接状态
			HeartListen.connect_state = true;
        }catch (Exception e) {  
        	//设置告警的全局变量
        	HeartListen.heartStatus = "success";
        	System.out.println("SocketThread创建socket服务出错"); 
            HeartListen.connect_state = false;
            
        }  
    }  
}

//从服务器接收信息
class ClientListen implements Runnable{
	private Socket socket;
	ClientListen(Socket socket){
		this.socket = socket;
	}
	
	@Override
	public void run() {
		//接收发送过来的信息
		try {
			ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
			//判断接收过来的信息,做后面的操作
			while(true){
				Object obj = ois.readObject();
				//判断接收信息,做后续操作
				if(obj == null || "".equals(obj)){ // 将配置文件中的状态置为1 (从服务器定时为1才发送定时信息)
					//设置告警的全局变量
		        	HeartListen.heartStatus = "success";
					System.out.println("主程序发送心跳--失败--");
				}else{ // 将配置文件中的状态值为0
					//设置告警的全局变量
		        	HeartListen.heartStatus = "error";
					System.out.println("主程序发送心跳--成功--");
				}
				
			}
						
		} catch (Exception e) {
			//设置告警的全局变量
        	HeartListen.heartStatus = "success";
			System.out.println("主程序发送心跳--失败---");
			e.printStackTrace();
		}finally{
			try {
				socket.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
}

//从服务器发送心跳检测信息(目的:当主从服务器断开连接后,尝试重连)
class ClientHeart implements Runnable{
	private Socket socket;
	ClientHeart(Socket socket){
		this.socket = socket;
	}
	@Override
	public void run() {
		try {
			ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
			while(true){
				JSONObject object = new JSONObject();
				object.put("type", "heart");
				object.put("message", "判断主从服务器连接心跳检测");
				oos.writeObject(object);
				oos.flush();
			}
			
		} catch (IOException e) {
			e.printStackTrace();
			try {
				socket.close();
				HeartListen.connect_state = false;
				HeartListen.reconnect();
			} catch (IOException e1) {
				e1.printStackTrace();
			}
		}
	}
	
}

我这边通过接收端中全局参数HeartStatus变量来控制从服务中各个功能的运行,HostHeardIp变量是从配置文件中获取安装主服务的服务器IP地址。ClientHeart类用来判断主程序是否需要重连操作。

3.配置文件配置类监听

在src\main\webapp\WEB-INF此目录下的web.xml文件中配置发送类和接收类监听:

<listener>
	<listener-class>cn.com.test.heart.HeartListenlistener-class>
listener>
<listener>
	<listener-class>cn.com.test.heart.HeartSendlistener-class>
listener>

(参考地址:https://blog.csdn.net/u013510614/article/details/109851112?utm_source=app)

你可能感兴趣的:(javaWeb,java)