以下图. 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