web-dev-qa-db-ja.com

WebサーバーとしてのHAProxy

HAProxyは、背後に他のWebサーバー(Apache、NGINXなど)がなくてもWebサーバーとして機能できますか?私はそのような構成について言われましたが、情報の正確性についてはわかりません。

5
i486

いいえ、HAProxyはWebサーバーではないため、Webサーバーのように動作することはできません。 HAProxyスターターガイド、HAProxyとは何か から:

HAProxyはWebサーバーではありません:

起動中に、chroot jail内で自身を隔離し、その権限をドロップします。これにより、一度起動されると、単一のファイルシステムアクセスが実行されなくなります。そのため、Webサーバーに変えることはできません。 ApacheやNginxなどの優れたオープンソースソフトウェアがあり、HAProxyをそれらの前にインストールして、負荷分散と高可用性を実現できます。

6

「いいえ、そうするように設計されていません」という受け入れられた答えは正しいです。

しかし、ソフトウェアがそれであるので、もしそれをやりたければ、ハッキングの回避策があります。

リクエストをカスタムバックエンドにポイントするACLが必要です。この例では、robots.txtを提供したいとします。

frontend port80
    acl is_robotstxt path /robots.txt
    use_backend robots if is_robotstxt
backend robots
    mode http
    errorfile 503 /etc/haproxy/errors/robots.http

このバックエンドにはサーバーが定義されていないため、/ robots.txtが要求され、haproxyがそれを使用すると、503エラーが発生します。 503エラーが/etc/haproxy/errors/robots.httpを処理するように指定します。これは、完全なHTTP出力ヘッダーとすべてを幸運にも指定します。

そのファイルに、

HTTP/1.0 200 Found
Cache-Control: no-cache
Connection: close
Content-Type: text/plain

Content here

したがって、503エラーになるはずの内容は、実際には200 Foundの返信、コンテンツ、およびすべてです。

これを行うことは実際には推奨されず、多くの制限が伴うことに注意してください。最も明らかなのは、この方法でバックエンドごとに1つのファイルしか提供できないことです。それほど明らかではありませんが、このファイルはhaproxyのBUFSIZE内に収まらなければならないことです。BUFSIZEは通常8または16kBです。また、Haproxyは、この方法で提供されるファイルに対していかなる種類のサニタイズも行っていません。そのため、正しいヘッダーを適切な方法で提供することができます。クライアントが\ nではなく\ r\nを必要とする場合は、処理する必要があります。

選択したWebサーバーのコピーをセットアップし、「静的資産バックエンド」haproxyをルーティングできるようにするだけの方がはるかに優れています。

6
semi

まず第一に-これは重要です-HA-ProxyはWebサーバーではありません。これは、今までに明らかになっているはずです。ただし、LUAを介してファイルを提供する方法があります。私は次の解決策を思いつきました:

HAプロキシ構成:

lua-load /etc/haproxy/lua/load-file.lua

...

backend lua-load-file
  http-request set-header X-LUA-LOADFILE-DOCROOT /etc/haproxy/docroot
  http-request use-service lua.load-file

ご覧のとおり、load-file.luaというluaファイルをロードします。そのファイルの内容は次のとおりです。

core.register_service("load-file", "http", function(applet)
  local docroot
  local location
  local file
  local retval
  local response
  local extension

  if(applet.path == nil or applet.headers["x-lua-loadfile-docroot"] == nil or applet.headers["x-lua-loadfile-docroot"][0] == "") then
    retval = 500
    response = "Internal Server Error"
  else
    docroot = applet.headers["x-lua-loadfile-docroot"][0]
    location = applet.path
    if(location == "" or location == "/") then
      location = "/index.html"
    end
    file = io.open(docroot .. location, "r")
    if(file == nil) then
      retval = 404
      response = "File Not Found"
    else
      retval = 200
      response = file:read("*all")
      file:close()
    end
  end

  extension = string.match(location, ".(%w+)$")
  if       extension == "css"  then applet:add_header("content-type", "text/css")
    elseif extension == "gif"  then applet:add_header("content-type", "image/gif")
    elseif extension == "htm"  then applet:add_header("content-type", "text/html")
    elseif extension == "html" then applet:add_header("content-type", "text/html")
    elseif extension == "ico"  then applet:add_header("content-type", "image/x-icon")
    elseif extension == "jpg"  then applet:add_header("content-type", "image/jpeg")
    elseif extension == "jpeg" then applet:add_header("content-type", "image/jpeg")
    elseif extension == "js"   then applet:add_header("content-type", "application/javascript; charset=UTF-8")
    elseif extension == "json" then applet:add_header("content-type", "application/json")
    elseif extension == "mpeg" then applet:add_header("content-type", "video/mpeg")
    elseif extension == "png"  then applet:add_header("content-type", "image/png")
    elseif extension == "txt"  then applet:add_header("content-type", "text/plain")
    elseif extension == "xml"  then applet:add_header("content-type", "application/xml")
    elseif extension == "Zip"  then applet:add_header("content-type", "application/Zip")
  end

  applet:set_status(retval)
  if(response ~= nil and response ~= "") then
    applet:add_header("content-length", string.len(response))
  end
  applet:start_response()
  applet:send(response)
end)

基本的に、このコードは、クエリ文字列に基づいてファイルシステム内の指定されたドキュメントルートの場所からファイルを読み取り、通常のWebサーバーが行うのと同じように適切なHTTP応答を生成します。スクリプトがdocument-rootを必要とするのは、HTTPヘッダーX-LUA-LOADFILE-DOCROOTを介して設定する必要があるためです。このヘッダーは、例に示すようにhaproxy設定を介して設定されています。さらに、コードは非常に基本的なmimetypeの処理も行います。必要に応じてリストを拡張します。誰かがこれが役に立つことを願っています。

乾杯!

3
Christian