9

Python用の優れたリクエストライブラリを使用して、RESTAPI用の非常にシンプルなクライアントを作成しました。ロードバランサーを介してクライアントを実行すると、すべてがうまく機能します。ロードバランサーは、アイドル状態のtcp接続を正常に検出し、それらを強制終了します。クライアントに、プラットフォーム(Linux)のデフォルトとは異なるいくつかの異なるtcpキープアライブオプションを使用したいと思います。しかし、新しいソケットにいくつかのデフォルトオプションを選択したいことをソケットライブラリに伝える簡単な方法がわかりません。

socket.create_connectionを直接使用する場合、これはデコレータで行うのに十分簡単ですが、リクエストの場合のように、実際の呼び出しがサードパーティのライブラリに埋め込まれている場合に、その装飾された呼び出しをどのように利用できるようにするかわかりません。

前もって感謝します

4

4 に答える 4

12

新しいバージョンurllib3(1.8.3以降、2014年6月23日リリース)は、設定ソケットオプションをサポートしています。

requestsカスタムアダプタを作成することにより、(2.4.0以降、2014-08-29でリリース)からこれらのオプションを設定できます。

class HTTPAdapterWithSocketOptions(requests.adapters.HTTPAdapter):
    def __init__(self, *args, **kwargs):
        self.socket_options = kwargs.pop("socket_options", None)
        super(HTTPAdapterWithSocketOptions, self).__init__(*args, **kwargs)

    def init_poolmanager(self, *args, **kwargs):
        if self.socket_options is not None:
            kwargs["socket_options"] = self.socket_options
        super(HTTPAdapterWithSocketOptions, self).init_poolmanager(*args, **kwargs)

SO_KEEPALIVE次に、このアダプタをカスタムソケットオプション(設定など)が必要なセッションにマウントできます。

adapter = HTTPAdapterWithSocketOptions(socket_options=[(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)])
s = requests.session()
s.mount("http://", adapter)
s.mount("https://", adapter)
于 2016-02-08T20:28:37.190 に答える
6

requestsを使用しますurllib3。これは、標準ライブラリhttp.client(またはhttplib、2.xの場合は)を使用します。これは、を呼び出しますsocket.create_connection

したがって、これらのライブラリの1つをフォークするか、その場でモンキーパッチを適用する必要があります。

それを行う最も簡単な場所はおそらくにあります。これは簡単に交換できる簡単http.client.connectなラッパーだからです。socket.create_connection

orig_connect = http.client.HTTPConnection.connect
def monkey_connect(self):
    orig_connect(self)
    self.sock.setsockopt(…)
http.client.HTTPConnection.connect = monkey_connect

httplib2.xを使用している場合は、上記の代わりに使用するのと同じくらい簡単http.clientですが、それを確認することをお勧めします。

于 2013-03-01T00:27:59.583 に答える
1

別の利用可能な代替手段は、TCPKeepAliveAdapterを使用するrequests_toolbeltです

背後にあるのは、リクエストHTTPAdapterのソケットを設定し、たとえばOSXの特異性を考慮に入れることです。

https://toolbelt.readthedocs.io/en/latest/adapters.html#tcpkeepaliveadapter

import requests
from requests_toolbelt.adapters.socket_options import TCPKeepAliveAdapter

session = requests.Session()
keep_alive = TCPKeepAliveAdapter(idle=120, count=20, interval=30)
session.mount('https://region-a.geo-1.compute.hpcloudsvc.com', keep_alive)
session.post('https://region-a.geo-1.compute.hpcloudsvc.com/v2/1234abcdef/servers',
             # ...
           )
于 2021-08-06T15:43:16.723 に答える
0

FireFox、Chrome、Edge、Safariなどのすべてのブラウザは、確立されたTCP接続が確立されたままであることを確認するために、頻繁にTCPキープアライブを使用し、接続が切断された場合に再接続します。確立されたTCP接続には、キープアライブがどのように機能するかを決定する3つの構成可能なプロパティがあります。Linuxでは次のようになります。

  1. tcp_keepalive_time(デフォルトは7200秒)
  2. tcp_keepalive_probes(デフォルトは9)
  3. tcp_keepalive_intvl(デフォルトは75秒)

Pythonリクエストは、ソケットでTCPキープアライブを有効にすることはありません(Linuxでは、デフォルトでTCPキープアライブはソケットで有効になっていないため、アプリケーションで有効にする必要があります)。Pythonリクエストは、各OSのデフォルトのソケットオプションを使用するため、HTTP 1.1持続的接続の場合、接続がアイドル状態のままである場合に確立された接続がドロップされるかどうかはわかりません。接続が切断された場合、次のソケット書き込みがいつ発生するかしかわかりません。デフォルトよりも低いtcp_keepalive_timeを使用すると、ドロップされたアイドル接続の診断に役立ちます。tcp_keepalive_intvlは、2つのキープアライブ間の間隔です。

以下のコードでは、ユーザー定義のHTTPAdapterを使用して、基になるurllib3を介してソケットオプションを設定するリクエスト推奨の方法を使用しています。(socket.SOL_SOCKET、socket.SO_KEEPALIVE、1)はキープアライブを有効にし、他の2つはtcp_keepalive_timeとtcp_keepalive_intvlを10秒に設定しています。

TCPキープアライブはプラットフォームに依存することを忘れないでください。このコードはLinux専用です。

import requests, socket
from requests.adapters import HTTPAdapter

class HTTPAdapterWithSocketOptions(HTTPAdapter):
    def __init__(self, *args, **kwargs):
        self.socket_options = kwargs.pop("socket_options", None)
        super(HTTPAdapterWithSocketOptions, self).__init__(*args, **kwargs)

    def init_poolmanager(self, *args, **kwargs):
        if self.socket_options is not None:
            kwargs["socket_options"] = self.socket_options
        super(HTTPAdapterWithSocketOptions, self).init_poolmanager(*args, **kwargs)

KEEPALIVE_INTERVAL = 10
adapter = HTTPAdapterWithSocketOptions(socket_options=[(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1),
(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, KEEPALIVE_INTERVAL), (socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, KEEPALIVE_INTERVAL)])
s = requests.Session()
s.mount("http://", adapter)
s.mount("https://", adapter)
于 2021-05-04T03:32:21.630 に答える