Ruby 多线程服务器用 ab 测试提示 `write': Broken pipe (Errno::EPIPE)

tablecell · 2019年10月24日 · 最后由 tablecell 回复于 2019年10月26日 · 5249 次阅读

用 socket 写的多线程服务器

require 'socket' 
server = TCPServer.open('127.0.0.1', 8080) 
loop { 
    Thread.start(server.accept) do | client |
    loop{
        #puts client
        lines = []
        while line = client.gets and line !~ /^\s*$/
            lines << line.chomp
        end

        #puts lines
        resp = lines.join("\n")
        headers = ["HTTP/1.1 200 OK", 
                   "Date: tue, 14 dec 2019 10:48:45 GMT",   
                   "Server: ruby mtserver", 
                   "Content-Type: text/html; charset=utf-8", 
                   "Content-Length: #{resp.length}\r\n\r\n"].join("\r\n")
       # puts headers.size+resp.size
        client.puts headers   #send to the client
        client.puts resp
    }

    end
}

用 php 做客户端连接测试正常

<?php

$fp = pfsockopen("tcp://127.0.0.1",8080, $errno, $errstr);
$cnt = 1;
do {
    fputs($fp, "GET /?cnt=$cnt  HTTP/1.1\r\n");
    fputs($fp, "Host: 127.0.0.1:8080\r\n");
    fputs($fp, "Connection: keep-alive\r\n\r\n");
    echo fread($fp,226);
} while ($cnt++ < 9);

sleep(10);
fclose($fp);


用 ab 测试 ab -n 2000 -c 10 -k http://localhost:8080/ 提示 `write': Broken pipe (Errno::EPIPE)

#<Thread:0x0000000004bc5e40@mt_serv.rb:4 run> terminated with exception (report_on_exception is true):
Traceback (most recent call last):
        4: from mt_serv.rb:5:in `block (2 levels) in <main>'
        3: from mt_serv.rb:5:in `loop'
        2: from mt_serv.rb:21:in `block (3 levels) in <main>'
        1: from mt_serv.rb:21:in `puts'
mt_serv.rb:21:in `write': Broken pipe (Errno::EPIPE)

21 行 是 client.puts resp

响应太慢导致客户端超时,客户端断开连接

client.puts resp + headers

puts 应该事加 "\n",导致 length 是错的,客户端发了 close 帧,服务端还要再写一次,就报 broken 那个错了。

具体的楼主还是用 tcpdump 看一下。

curl 也能重现。

yfractal 回复

是 puts 的问题 改成 client.write 就好了

需要 登录 后方可回复, 如果你还没有账号请 注册新账号