websocket 实现服务器日志实时反馈(linux 环境)

在我们线上项目中,版本迭代很多操作需要重新、关闭、开启应用程序,这样我们就需要登录服务器去命令中操作。

如果我们定制开发一个web程序去控制项目的重启与关闭,这样就需要在web界面中实时反馈重启与关闭时的日志反馈信息,这样如果出现异常方便我们及时处理。如果要实时反馈的话,这里提供解决方案是使用websocket + sh 命令

tail 这样来实时获取日志文件里面信息,java 获取到对应流信息并输出到websocket 中 反馈给客户端
这里使用的是Spring Boot websocket

package cn.jiangzeyin.socket;

import cn.jiangzeyin.system.log.SystemLog;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.io.InputStream;

/**
 * Created by jiangzeyin on 2017/9/8.
 */
@ServerEndpoint("/log")
@Component
public class LogWebSocketHandle implements TailLogThread.Evn {

    private Process process;
    private InputStream inputStream;
    private TailLogThread thread;

    /**
     * 新的WebSocket请求开启
     */
    @OnOpen
    public void onOpen(Session session) {
        try {
            SystemLog.LOG().info("创建 socket id  " + session.getId());
            // 执行tail -f命令
            process = Runtime.getRuntime().exec("tail -f /test/run.log");
            inputStream = process.getInputStream();
            // 一定要启动新的线程,防止InputStream阻塞处理WebSocket的线程
            thread = new TailLogThread(inputStream, session, this);
            Thread thread_ = new Thread(thread);
            thread_.start();
        } catch (IOException e) {
            SystemLog.ERROR().error("打开异常", e);
        }
    }

    @OnMessage
    public void onMessage(String message, Session session) {
        SystemLog.LOG().info("客户端消息:" + message);
    }

    /**
     * WebSocket请求关闭
     */
    @OnClose
    public void onClose() {
        try {
            if (inputStream != null)
                inputStream.close();
        } catch (Exception e) {
            SystemLog.ERROR().error("关闭异常", e);
        }
        if (process != null)
            process.destroy();
        if (thread != null)
            thread.stop();
        SystemLog.LOG().info(" socket 关闭");
    }

    @OnError
    public void onError(Throwable thr) {
        onClose();
        SystemLog.ERROR().error("socket 异常", thr);
    }

    @Override
    public void onError() {
        onClose();
    }
}
package cn.jiangzeyin.socket;

import cn.jiangzeyin.system.log.SystemLog;

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

/**
 * Created by jiangzeyin on 2017/9/8.
 */
public class TailLogThread implements Runnable {

    private BufferedReader reader;
    private Session session;
    private boolean run = true;
    private Evn evn;

    public TailLogThread(InputStream in, Session session, Evn evn) {
        this.reader = new BufferedReader(new InputStreamReader(in));
        this.session = session;
        this.evn = evn;

    }

    public void stop() {
        run = false;
    }

    @Override
    public void run() {
        String line;
        int errorCount = 0;
        try {
            while (run && (line = reader.readLine()) != null) {
                // 将实时日志通过WebSocket发送给客户端,给每一行添加一个HTML换行
                try {
                    session.getBasicRemote().sendText(line + "<br>");
                } catch (Exception e) {
                    SystemLog.ERROR().error("发送消息失败", e);
                    errorCount++;
                    if (errorCount == 10) {
                        SystemLog.LOG().info("失败次数超过10次,结束本次事件");
                        if (evn != null)
                            evn.onError();
                        break;
                    }
                }
            }
        } catch (IOException e) {
            SystemLog.ERROR().error("读取异常", e);
        }
        SystemLog.LOG().info("结束本次读取地址事件");
    }

    public interface Evn {
        void onError();
    }
}

版权声明:本文为jiangzeyin_原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。