You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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_

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 19:43:00