基于springBoot+websocket 实时推送服务日志

  1. 背景
    根据运维提出的需求,服务发生异常时,每次都登录服务器查看日志有些费时费力
  2. websocket
    服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息
  3. 引入依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
    <version>2.3.0.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-websocket</artifactId>
    <version>5.1.4.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-messaging</artifactId>
    <version>5.1.4.RELEASE</version>
</dependency>
  1. 注入 websocket 配置
package cn.caojiantao.tutorials.websocket;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

@Configuration
public class WebSocketConfig {

    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}
  1. 编写 socket handle 处理器
package com.yy.websocket;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.io.InputStream;

@ServerEndpoint("/log")
@Component
public class LogWebSocketHandle {
	
	private Process process;
	private InputStream inputStream;
	
	/**
	 * 新的WebSocket请求开启
	 */
	@OnOpen
	public void onOpen(Session session) {
		try {
			// 执行tail -f命令
			process = Runtime.getRuntime().exec("tail -f /var/log/syslog");
			inputStream = process.getInputStream();
			
			// 一定要启动新的线程,防止InputStream阻塞处理WebSocket的线程
			TailLogThread thread = new TailLogThread(inputStream, session);
			thread.start();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * WebSocket请求关闭
	 */
	@OnClose
	public void onClose() {
		try {
			if(inputStream != null)
				inputStream.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		if(process != null)
			process.destroy();
	}
	
	@OnError
	public void onError(Throwable thr) {
		thr.printStackTrace();
	}
}
package com.yy.websocket;

import javax.websocket.Session;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class TailLogThread extends Thread {
	
	private BufferedReader reader;
	private Session session;
	
	public TailLogThread(InputStream in, Session session) {
		this.reader = new BufferedReader(new InputStreamReader(in));
		this.session = session;
	}
	
	@Override
	public void run() {
		String line;
		try {
			while((line = reader.readLine()) != null) {
				// 将实时日志通过WebSocket发送给客户端,给每一行添加一个HTML换行
				session.getBasicRemote().sendText(line + "
"
); } } catch (IOException e) { e.printStackTrace(); } } }
  1. 前端建立 websocket 连接
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>WebSocket 实时日志</title>
</head>
<body>
<div class="content" style="height: 200px;"></div>
<script>
    let ws = new WebSocket("ws://127.0.0.1:8088/logs");

    ws.onopen = function() {
        ws.send("Hello WebSockets!");
    };

    ws.onmessage = function(evt) {
        let content = document.getElementsByClassName('content')[0];
        content.innerText = content.innerText + evt.data.replace(/ /g, '\xa0\xa0');
    };
</script>
</body>
</html>

你可能感兴趣的:(springBoot,springBoot,websocket)