以下圖. server docker restart後, client端寫入的日誌丟失, 而且無報錯.
由於不支持時序圖, 把時序圖代碼嵌入在代碼裏.linux
```sequence client->server: log_data client->server: log_data server->server: docker restart server->client: fin client->server: log_data loss without error ```
看tcp狀態轉換圖, 能夠看到client收到了fin, 一直沒有recv, 一直卡在CLOSE_WAIT. 和實際的代碼是吻合的.
那麼, 爲何在server docker restart 引起CLOSE_WAIT後, client發消息仍然不報錯呢?
由於:docker
積壓信息以下:segmentfault
root@9eeaefa7fe57:/# netstat -nap | grep 27017 | grep 10.0.0 tcp 1 402 10.0.0.186:62281 10.0.0.16:27017 CLOSE_WAIT 4308/server root@9eeaefa7fe57:/# netstat -nap | grep 27017 | grep 10.0.0 tcp 1 70125 10.0.0.186:62281 10.0.0.16:27017 CLOSE_WAIT 4308/server
此時, 在elixir socket接口層面來看, 無論socket的狀態, 仍是發送, 都是ok的.api
iex(client@client.)25> socket |> :inet.port {:ok, 57395} iex(client@client.)26> socket |> :gen_tcp.send("aaa") :ok
若是主動close, 則會進入LAST_ACK狀態socket
iex(client@client.)27> socket |> :gen_tcp.close() :ok
root@9eeaefa7fe57:/# netstat -nap | grep 27017 | grep 10.0.0 tcp 1 70126 10.0.0.186:62281 10.0.0.16:27017 LAST_ACK -
若是代碼仍是隻發不收. 是檢測不到CLOSE_WAIT的. 顯然, 應用層心跳是一個解決方案. 那麼, 不使用心跳, 只發不收的狀況下, 何時才能檢測到錯誤呢?tcp