apache httpdでフォワードプロキシを運用していたのですが、稀に"No buffer space available"というエラーが出て、ネットワーク全体が死んでしまう問題が起きていました。発生すると、SSHログインすら不可能になります。
ServersMan@VPSのコンパネからOSを再起動すれば解消するのですが、さすがにまずいので調査しました。
問題の発生を確認したのは、プロキシ経由で大きなファイルをダウンロードしている場合だけでした。また、ダウンロード速度が速い場合に発生しやすいようでした。
さらにOS再起動で解消することから、VPSアカウントに対する制限が発動したわけではなさそうです。
クライアントは、WindowsとLinuxの両方で発生しました。サーバ側の問題であることは間違いなさそうです。
エラー内容と原因の切り分けから、ダウンロード速度とアップロード速度のギャップによる問題を疑いました。対向サーバからのダウンロードが速すぎるため、プロキシクライアントへのデータ転送が追いつかず、送信バッファが足りなくなるというストーリーです。
この仮定が正しければ、ダウンロード側の帯域制限で解消できるはずです。
類似の情報が多くないのは、SSHポートフォワーディングも一因になっているからだと考えました。トンネルによる暗号化と認証は必須なので、切り分けはやりませんでした。
httpdにmod_bwというモジュールがあるのですが、意図するような帯域制限ができませんでした。フォワードプロキシでは動作しないのかもしれません。
httpd2.4系に乗り換えるのもあれなので、squid (3.1.10)を使うことにしました。
設定はこんな感じ。シンプルでいいですね。
# /etc/squid/squid.conf
acl manager proto cache_object
acl localhost src 127.0.0.1/32 ::1
acl to_localhost dst 127.0.0.0/8 0.0.0.0/32 ::1
acl SSL_ports port 443
acl Safe_ports port 80 # http
acl Safe_ports port 21 # ftp
acl Safe_ports port 443 # https
acl CONNECT method CONNECT
http_access allow manager localhost
http_access deny manager
http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports
http_access deny to_localhost
http_access allow localhost
http_access deny all
http_port 127.0.0.1:99999
visible_hostname unkown
forwarded_for off
request_header_access X-FORWARDED-FOR deny all
request_header_access Via deny all
request_header_access Cache-Control deny all
hierarchy_stoplist cgi-bin ?
cache_mem 32 MB
cache_dir ufs /var/spool/squid 128 16 256
coredump_dir /var/spool/squid
shutdown_lifetime 1 seconds
delay_pools 1
delay_class 1 1
delay_access 1 allow all
delay_parameters 1 500000/500000 #500KB/s = 4.0Mbps
外部公開の必要がないので、http_port
で127.0.0.1を指定しています。念のため、allow localhostとdeny allも設定。
プロキシの使用を悟られたくないので、forwarded_for
やrequest_header_access
なども設定しました。
メモリを節約するため、cache_mem 32 MB
を明記。
shutdown_lifetime 1 seconds
を明記しないと、再起動に30秒かかります。ちょいハマり。
最下部の4行が帯域制限です。500KB/sとしました。
帯域制限付きのsquidに移行してからは、"No buffer space available"は一度も発生していません。仮定は当たっていたようです。
餅は餅屋。
書いていて気付いたんですが、帯域制限無しのsquidでエラーが再現するかどうか確認するべきでした。もしかするとhttpdのせいかもね(おい