如何在Javalin中启用Proxy Protocol适配Hetzner负载均衡器?
Javalin适配Hetzner负载均衡Proxy Protocol的配置方案
问题根源
启用Proxy Protocol后,Hetzner负载均衡会在每个HTTP请求前附加一段Proxy Protocol格式的前置报文。Javalin默认使用的Jetty服务器未启用该协议的解析逻辑,会把这段前置报文误判为HTTP请求的一部分,导致HTTP解析失败,抛出Bad Message 400, reason: Illegal character SPACE=' '错误。
解决步骤
Javalin基于Jetty开发,需通过配置Jetty的ProxyProtocolConnectionFactory来支持Proxy Protocol,以下是两种常见场景的配置方式:
1. Java代码配置(自定义Jetty服务器)
import io.javalin.Javalin; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.server.proxy.ProxyProtocolConnectionFactory; import org.eclipse.jetty.server.HttpConnectionFactory; public class JavalinProxyProtocolExample { public static void main(String[] args) { // 初始化Jetty服务器 Server jettyServer = new Server(); // 创建ProxyProtocol连接工厂,必须放在HTTP连接工厂之前 ProxyProtocolConnectionFactory proxyConnFactory = new ProxyProtocolConnectionFactory(); HttpConnectionFactory httpConnFactory = new HttpConnectionFactory(); // 配置服务端口并添加连接器 ServerConnector connector = new ServerConnector(jettyServer, proxyConnFactory, httpConnFactory); connector.setPort(8080); // 替换为你的服务监听端口 jettyServer.addConnector(connector); // 初始化Javalin并绑定自定义Jetty服务器 Javalin app = Javalin.create(config -> { config.server(() -> jettyServer); }).start(); // 测试路由:获取真实客户端IP app.get("/", ctx -> { // 通过Jetty提供的属性获取真实客户端IP String realClientIp = ctx.req().getAttribute("javax.servlet.request.remoteAddr").toString(); ctx.result("真实客户端IP: " + realClientIp); }); } }
2. Kotlin代码配置(自定义Jetty服务器)
import io.javalin.Javalin import org.eclipse.jetty.server.Server import org.eclipse.jetty.server.ServerConnector import org.eclipse.jetty.server.proxy.ProxyProtocolConnectionFactory import org.eclipse.jetty.server.HttpConnectionFactory fun main() { val jettyServer = Server() val proxyConnFactory = ProxyProtocolConnectionFactory() val httpConnFactory = HttpConnectionFactory() val connector = ServerConnector(jettyServer, proxyConnFactory, httpConnFactory).apply { port = 8080 // 替换为你的服务监听端口 } jettyServer.addConnector(connector) val app = Javalin.create { config -> config.server { jettyServer } }.start() app.get("/") { ctx -> val realClientIp = ctx.req().getAttribute("javax.servlet.request.remoteAddr") as String ctx.result("真实客户端IP: $realClientIp") } }
验证要点
- 确保Hetzner负载均衡已启用Proxy Protocol
- 服务监听端口与负载均衡配置的后端端口一致
- 重启服务后,通过负载均衡访问即可正常获取客户端IP,不再出现400错误
内容的提问来源于stack exchange,提问作者Lvkas_
相关产品推荐
相关产品推荐

