概要
原著者の許諾を得て翻訳・公開いたします。
- 英語記事: Ruby 2.6 adds write_timeout to Net::HTTP | BigBinary Blog
- 原文公開日: 2018/08/14
- 著者: Taha Husain
- サイト: BigBinary
Ruby 2.6先行チェック: Net::HTTPにwrite_timeoutが追加される(翻訳)
Ruby 2.6シリーズの記事です。Ruby 2.6.0-preview2は最近リリースされました。
Ruby 2.6より前は、Net::HTTP
で巨大なリクエストを作成するとリクエストを中断するまでハングし続けることがありました。この問題を修正するため、Ruby 2.6のNet::HTTP
クラスにwrite_timeout
属性とwrite_timeout=
メソッドが追加されました。write_timeout
のデフォルト値は60秒で、integerまたはfloatで指定できます。
同様に、Net::BufferedIO
クラスにもwrite_timeout
属性とwrite_timeout=
メソッドが追加されました。
write_timeout
で指定した秒数以内にレスポンスのチャンクが書き込まれなかった場合は、Net::WriteTimeout
例外が発生します。なお、WindowsシステムではNet::WriteTimeout
例外が発生しません。
コード例
# server.rb
require 'socket'
server = TCPServer.new('localhost', 2345)
loop do
socket = server.accept
end
Ruby 2.5.1の場合
# client.rb
require 'net/http'
connection = Net::HTTP.new('localhost', 2345)
connection.open_timeout = 1
connection.read_timeout = 3
connection.start
post = Net::HTTP::Post.new('/')
body = (('a' * 1023) + "\n") * 5_000
post.body = body
puts "Sending #{body.bytesize} bytes"
connection.request(post)
上の出力
$ RBENV_VERSION=2.5.1 ruby client.rb
Sending 5120000 bytes
Ruby 2.5.1では、プログラムが中断されるまでリクエストの処理が止まりません。
Ruby 2.6.0-devの場合
client.rbのNet::HTTP
インスタンスにwrite_timeout
を追加します。
# client.rb
require 'net/http'
connection = Net::HTTP.new('localhost', 2345)
connection.open_timeout = 1
connection.read_timeout = 3
# write_timeoutのタイムアウトは10秒
connection.write_timeout = 10
connection.start
post = Net::HTTP::Post.new('/')
body = (('a' * 1023) + "\n") * 5_000
post.body = body
puts "Sending #{body.bytesize} bytes"
connection.request(post)
上の出力
$ RBENV_VERSION=2.6.0-dev ruby client.rb
Sending 5120000 bytes
Traceback (most recent call last):
13: `from client.rb:17:in `<main>``
12: `from /net/http.rb:1479:in `request``
11: `from /net/http.rb:1506:in `transport_request``
10: `from /net/http.rb:1506:in `catch``
9: `from /net/http.rb:1507:in `block in transport_request``
8: `from /net/http/generic_request.rb:123:in `exec``
7: `from /net/http/generic_request.rb:189:in `send_request_with_body``
6: `from /net/protocol.rb:221:in `write``
5: `from /net/protocol.rb:239:in `writing``
4: `from /net/protocol.rb:222:in `block in write``
3: `from /net/protocol.rb:249:in `write0``
2: `from /net/protocol.rb:249:in `each_with_index``
1: `from /net/protocol.rb:249:in `each``
`/net/protocol.rb:270:in `block in write0`: Net::WriteTimeout (Net::WriteTimeout)`
Ruby 2.6.0では10秒後に上のプログラムがNet::WriteTimeout
例外で終了します(値はwrite_timeout
属性に設定)。