我是蒼王,如下是我這個系列的相關文章,有興趣能夠參考一下,能夠給個喜歡或者關注個人文章。 [Android]如何作一個崩潰率少於千分之三噶應用app--章節列表web
這一張很是經典的心跳策略圖示 算法
如今通常的心跳策略,都是從客戶端發送一個ping信號給服務器,告訴服務器是長鏈接存活。 服務器會返回一個pong信號給客戶端,讓其更新心跳線程時間。若是超時沒有接收到信號,那麼客戶端考慮重連機制。bash
這裏說一下okhttp有提供了WebSocket的封裝,咱們的應用也是使用了WebSocket,那就直接看一下WebSocket對pingpong的封裝服務器
public Builder() { …… //這裏默認的ping的時間間隔爲0,由於okhttp也能夠有如http短鏈接 pingInterval = 0; } Builder(OkHttpClient okHttpClient) { …… //builder函數提供封裝 this.pingInterval = okHttpClient.pingInterval; } //設置間隔 public Builder pingInterval(long interval, TimeUnit unit) { pingInterval = checkDuration("interval", interval, unit); return this; } 複製代碼
在RealWebSocket中啓動循環發送ping信號微信
public void initReaderAndWriter(String name, Streams streams) throws IOException { synchronized (this) { this.streams = streams; this.writer = new WebSocketWriter(streams.client, streams.sink, random); this.executor = new ScheduledThreadPoolExecutor(1, Util.threadFactory(name, false)); if (pingIntervalMillis != 0) { //循環定時任務 executor.scheduleAtFixedRate( new PingRunnable(), pingIntervalMillis, pingIntervalMillis, MILLISECONDS); } if (!messageAndCloseQueue.isEmpty()) { runWriter(); // Send messages that were enqueued before we were connected. } } reader = new WebSocketReader(streams.client, streams.source, this); } private final class PingRunnable implements Runnable { PingRunnable() { } @Override public void run() { //寫入ping信號 writePingFrame(); } } void writePingFrame() { WebSocketWriter writer; int failedPing; synchronized (this) { if (failed) return; writer = this.writer; //是否等待pong信號 failedPing = awaitingPong ? sentPingCount : -1; //等待ping計數 sentPingCount++; //等待pong awaitingPong = true; } //ping失敗,長鏈接失效 if (failedPing != -1) { failWebSocket(new SocketTimeoutException("sent ping but didn't receive pong within " + pingIntervalMillis + "ms (after " + (failedPing - 1) + " successful ping/pongs)"), null); return; } try { //寫入空支付到websocket頭部 writer.writePing(ByteString.EMPTY); } catch (IOException e) { failWebSocket(e, null); } } 複製代碼
在RealWebSocket的call中執行loopReader監聽讀取接收到的信息websocket
/** Receive frames until there are no more. Invoked only by the reader thread. */ public void loopReader() throws IOException { //監聽信息 while (receivedCloseCode == -1) { // This method call results in one or more onRead* methods being called on this thread. reader.processNextFrame(); } } void processNextFrame() throws IOException { //讀取頭部 readHeader(); if (isControlFrame) { //讀取頭部信息體 readControlFrame(); } else { readMessageFrame(); } } 複製代碼
讀取到是頂部信息markdown
private void readControlFrame() throws IOException { if (frameLength > 0) { source.readFully(controlFrameBuffer, frameLength); if (!isClient) { controlFrameBuffer.readAndWriteUnsafe(maskCursor); maskCursor.seek(0); toggleMask(maskCursor, maskKey); maskCursor.close(); } } switch (opcode) { //讀取ping信號 case OPCODE_CONTROL_PING: frameCallback.onReadPing(controlFrameBuffer.readByteString()); break; //讀取pong信號 case OPCODE_CONTROL_PONG: frameCallback.onReadPong(controlFrameBuffer.readByteString()); break; //讀取到關閉鏈接信號 case OPCODE_CONTROL_CLOSE: int code = CLOSE_NO_STATUS_CODE; String reason = ""; long bufferSize = controlFrameBuffer.size(); if (bufferSize == 1) { throw new ProtocolException("Malformed close payload length of 1."); } else if (bufferSize != 0) { code = controlFrameBuffer.readShort(); reason = controlFrameBuffer.readUtf8(); String codeExceptionMessage = WebSocketProtocol.closeCodeExceptionMessage(code); if (codeExceptionMessage != null) throw new ProtocolException(codeExceptionMessage); } frameCallback.onReadClose(code, reason); closed = true; break; default: throw new ProtocolException("Unknown control opcode: " + toHexString(opcode)); } } 複製代碼
讀取到pong信號,等待pong置爲false架構
@Override public synchronized void onReadPong(ByteString buffer) { // This API doesn't expose pings. receivedPongCount++; awaitingPong = false; } 複製代碼
這就是使用OkHttp的WebSocket keepAlive的流程,而基本的okhttp的socket鏈接也是經過相似發送這種pingpong信號來維持,之須要設置維護的時間。 而後keepAlive的經驗之前的經驗值是59秒,微信的大神的方案是經過記錄socket鏈接和斷開時間,適配出最適當的發送長連接時間,有興趣能夠本身實驗寫一個算法。 微信的智能心跳方案app
這邊作IM的應用的,說一下這邊方案,僅供參考。 手機進入後臺後十秒後主動關閉長鏈接,經過推送來維護消息,這裏有個問題就是國內的Umeng推送可達率你們懂的,小米和華爲還好點,若是是其餘山寨機,到8.0後後臺很難保活了。若是是國外FCM送達率是很是高的,若是是最推國外平臺,直接依靠推送也很是可靠。dom