Web 与 HTTP 服务
你当前正在浏览历史版本 Vert.x 4.1.8 的文档。 访问本页面的 最新版本。

Vert.x Web Proxy 反向代理

Preview

Vert.x Web Proxy 基于 Vert.x Http Proxy 提供了一个专门处理反向代理逻辑的路由 Handler。

本模块处于 技术预览 (Tech Preview) 阶段,这意味着 API 在后续版本间可能会发生变更。

使用 Vert.x Web Proxy

若要在项目中使用 Vert.x Web Proxy,请将以下依赖项添加到构建描述文件的 dependencies 配置节中:

  • Maven(在 pom.xml 中):

<dependency>
 <groupId>io.vertx</groupId>
 <artifactId>vertx-web-proxy</artifactId>
 <version>4.5.35</version>
</dependency>
  • Gradle(在 build.gradle 文件中):

dependencies {
 compile 'io.vertx:vertx-web-proxy:4.5.35'
}

基础 Web 反向代理

使用 Vert.x Web Proxy 实现反向代理需要以下两部分:

  1. 代理服务器 (Proxy Server):处理前端传入的客户端请求,并通过 ProxyHandler 将其转发给 源站服务器 (Origin Server)。

  2. 源站服务器 (Origin Server):处理来自 代理服务器 的请求并返回相应响应。

了解整体概念后,接下来我们先实现 源站服务器,然后使用 ProxyHandler 构建 代理服务器:

源站服务器(后端服务)

创建 源站服务器 并通过 Vert.x Web 的 Router 处理业务请求。以下示例中源站服务器监听 7070 端口:

HttpServer backendServer = vertx.createHttpServer();

Router backendRouter = Router.router(vertx);

backendRouter.route(HttpMethod.GET, "/foo").handler(rc -> {
  rc.response()
    .putHeader("content-type", "text/html")
    .end("<html><body><h1>我是目标源站资源!</h1></body></html>");
});

backendServer.requestHandler(backendRouter).listen(7070);

代理服务器

创建监听 8080 端口的前端 代理服务器:

HttpServer proxyServer = vertx.createHttpServer();

Router proxyRouter = Router.router(vertx);

proxyServer.requestHandler(proxyRouter);

proxyServer.listen(8080);

使用 ProxyHandler

最关键的一步是将 代理服务器 收到的请求路由并转发给 源站服务器。你需要创建一个指定目标的 HttpProxy 实例并搭配 ProxyHandler 使用:

HttpClient proxyClient = vertx.createHttpClient();

HttpProxy httpProxy = HttpProxy.reverseProxy(proxyClient);
httpProxy.origin(7070, "localhost");

proxyRouter
  .route(HttpMethod.GET, "/foo").handler(ProxyHandler.create(httpProxy));

或者你也可以直接在 ProxyHandler 中指定源站目标:

HttpClient proxyClient = vertx.createHttpClient();

HttpProxy httpProxy = HttpProxy.reverseProxy(proxyClient);

proxyRouter
  .route(HttpMethod.GET, "/foo")
  .handler(ProxyHandler.create(httpProxy, 7070, "localhost"));

配置完成后,发往代理服务器 /foo 的请求将作为反向代理无缝转发到后端源站。

BodyHandler 与 ProxyHandler 不兼容。 绝对不能在同一路由或此代理路由的前置拦截中挂载 BodyHandler(因为 BodyHandler 会提前消费并缓冲请求体,导致反向代理流式转发中断):

router.post().handler(BodyHandler.create()); // 切勿这样配置
router.route("/product").handler(ProxyHandler.create(productServiceProxy));

router.route("/product")
  .handler(BodyHandler.create()) // 切勿这样配置
  .handler(ProxyHandler.create(productServiceProxy));

为多个目标源站配置 ProxyHandler

若需要将 代理服务器 请求分别路由至不同的 源站服务器,只需为每个源站分别创建 HttpProxy 实例并独立指定后端即可:

HttpClient proxyClient = vertx.createHttpClient();

HttpProxy httpProxy1 = HttpProxy.reverseProxy(proxyClient);
httpProxy1.origin(7070, "localhost");

HttpProxy httpProxy2 = HttpProxy.reverseProxy(proxyClient);
httpProxy2.origin(6060, "localhost");

proxyRouter
  .route(HttpMethod.GET, "/foo").handler(ProxyHandler.create(httpProxy1));

proxyRouter
  .route(HttpMethod.GET, "/bar").handler(ProxyHandler.create(httpProxy2));