Wir verwenden HAProxy als Frontend zur Weiterleitung eingehender Anfragen an unsere Webserver, auf denen Apache+Passenger Instanzen laufen.

Probleme gab es bei der Einführung auf der HAProxy-Maschine selbst durch die (beabsichtigte) Weiterleitung von Webanfragen auf den lokal laufenden Apache-Server: trotz der forward_for Option im konfigurierten HAProxy-Backend nahm Rails alle eingehenden Anfragen als lokal an. Das Resultat waren freiliegende Exceptions, sogar bei solchen Trivialitäten wie dem RoutingError, der die Auslieferung der 404-Seite auslöst.

Wesley Moxam beschrieb dieses Problem 2008 in einem Blogartikel, aber unsere Konfiguration unterscheidet sich: HAProxy leitet Anfragen direkt an Passenger („mod_rails“) innerhalb von Apache-VHosts weiter, ohne dass ein weiterer (unnötiger) Apache-seitiger Proxymechanismus zum Setzen des X-HTTP-FORWARDED-FOR Headers zur Anwendung kommt. Die option forwardfor wie im erwähnten Artikel zu entfernen würde die nicht-lokalen Clusterknoten verwirren und war somit keine gangbare Alternative für unsere Konfiguration.

Ein zusätzliches und für Proxys keineswegs unbekanntes Problem war, dass die Rails-Applikationen hinter dem HAProxy niemals die tatsächliche Client-IP zu Gesicht bekamen: Request#remote_ip war immer die der HAProxy Instanz.

Das Heben der lokal laufenden Apache-Instanz auf das externe Netzwerkinterface und die damit verbundene Behandlung wie jeder andere Clusterknoten befreite uns von dem ersten Problem und ein Hinzufügen der HAProxy-IP zur Liste der TRUSTED_PROXIES war das Gegenmittel für das zweite (siehe nachfolgendes Code-Fragment als Initializer einer Rails 2.3.x Anwendung). Das HAProxy-Backend behält die Optionen option httpclose und option forwardfor.

# config/initializers/trusted_proxies.rb
# If your HAProxy is running at 209.85.149.104, set:
ActionController::Request.const_set("TRUSTED_PROXIES", /^209\.85\.149\.104$|^127\.0\.0\.1$|^(10|172\.(1[6-9]|2[0-9]|30|31)|192\.168)\./i)

Zugegeben, ich bin nicht ganz zufrieden damit, dieses Element der Netzwerkarchitektur direkt in die Rails-Applikation zu schreiben. Das Umziehen von Servern und das damit verbundene Ändern von IP-Adressen ist schmerzhaft genug und ich mag es nicht, eine weitere harte Abhängigkeit hinzuzufügen. Aber es funktioniert, und wir wollen hoffen, dass unser Loadbalancer so schnell nicht ausgetauscht werden muss.