Gem 如何关闭 Faraday (Net::http) 在 readtime_out 时会重发请求的机制

cakejuju · 2016年10月01日 · 最后由 cakejuju 回复于 2016年10月02日 · 2346 次阅读

具体描述:

用 faraday 发送请求时,若服务端的响应时间超过了配置 faraday 对象的 readtime_out 时间,faraday 会再次发送请求,导致服务端收到两笔一样的请求。重发的动作在 http 的文档中并没有很清楚的说明,我是在项目运作过程中发现了这个情况,然后本地测试了一下 (用 faraday 调用自己的服务,服务端故意加了 sleep 时间)。

http 参数的文档链接

虽然说把 readtime_out 这个参数设置的足够大可以很大程度上避免这个问题。但在对端服务器性能很差的时候会导致线程阻塞的时间太长。所以就想找能否强制不让 faraday 去重发,但始终没有找到这个参数或者配置。后来尝试用 Net::http 包来直接做发送,发现还是有一样的问题。因为 faraday 其实也是调用了 Net::http 中的方法。。
 def start  # :yield: http
   raise IOError, 'HTTP session already opened' if @started
   if block_given?
     begin
       do_start
       return yield(self)
     ensure
       do_finish
     end
   end
   do_start
   self
 end

 def do_start
   connect
   @started = true
 end
 private :do_start

 def connect
   ....
end

上面为 http 类中的部分方法 net::http gem 的 github 链接。在请求出现 readtime_out 时 do_start 方法只调用一次,但 connect 方法确被调用了两次 (connect 方法较长,其中用 socket 来发请求),关键是始终没发现为什么会这样。。
uri = URI.parse(url + path)
http = Net::HTTP.new(uri.host, uri.port)
http.read_timeout = 60
http.open_timeout = 60
http.keep_alive_timeout = 0
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE 
这是我目前所使用的配置,keep_alive_timeout 可以忽略,本来以为是这个参数在作怪,因为 java 中有个 keep_ailve 的东东,但发现怎么设置也没用。
有熟悉 faraday 的朋友给出些建议吗?
def connection
  @connection ||= Faraday.new( ssl: { verify: false } ) do |conn|
    conn.request  :multipart
    conn.request  :url_encoded
    conn.request  :retry, max: 2, interval: 0.05,
                  interval_randomness: 0.5, backoff_factor: 2,
                  exceptions: [Faraday::TimeoutError, Timeout::Error]
    conn.response :logger
    conn.adapter  :typhoeus
    conn.options.open_timeout = 10
    conn.options.timeout = 10
  end
end

#1 楼 @mimosa 谢谢!按照你给的配置把 adapter 换成了 typhoeus,retry max 设置为 0,不会 resend 了。

huacnlee 关闭了讨论。 10月03日 10:26
需要 登录 后方可回复, 如果你还没有账号请 注册新账号