websocket 實現伺服器日誌實時反饋(linux 環境)
阿新 • • 發佈:2019-02-09
在我們線上專案中,版本迭代很多操作需要重新、關閉、開啟應用程式,這樣我們就需要登入伺服器去命令中操作。
如果我們定製開發一個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();
}
}