1. 程式人生 > >websocket 實現伺服器日誌實時反饋(linux 環境)

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();
    }
}