使用Vert.x实现反向代理

原文发布在:使用Vert.x实现反向代理,欢迎使用 RSS 订阅获取最新更新。

1. 前言

在简单使用Pingora后,我在想既然rust, go都能写代理相关,那为什么不用Java写一个呢?

搜了搜原来用Vert.x实现反向代理这么简单,让我们快速开始吧。

如果你想下载示例代码,可以在这里找到:demo-vertx-reverse-proxy

2. 创建Vert.x项目

Vert.x项目的创建可以在官网找到:Create a new Vert.x application

要选择的依赖则是Vert.x Http Proxy

3. 根据Vert.x的教程开始

官网的教程:Vert.x Http Proxy

3.1 Vert.x Http Proxy

Vert.x Http Proxy 是基于 Vert.x 的反向代理,它旨在实现可重用的反向代理逻辑,以关注更高的问题。

该模块具有技术预览状态,这意味着 API 可以在版本之间更改。

3.2 使用 Vert.x Http Proxy

要使用 Vert.x Http Proxy,请在pom.xml或是其他依赖配置中增加: Maven:

xml 复制代码
<dependency>
    <groupId>io.vertx</groupId>
    <artifactId>vertx-http-proxy</artifactId>
    <version>4.1.8</version>
</dependency>

Gradle:

Gradle 复制代码
dependencies {
    compile 'io.vertx:vertx-http-proxy:4.1.8'
}

3.3 基本 Http 代理

为了使用 Vert.x Http Proxy 完成反向代理,你需要以下内容:

  1. 代理服务器使用 HttpProxy 实例处理出站请求并将其转发给源服务器。
  2. 源服务器处理来自代理服务器的请求并相应地处理响应。

现在,你已经有了总体概念,所以让我们深入实现并从源服务器开始,然后是带有 HttpProxy 的代理服务器:

3.4 源服务

这里可以跳过,因为源服务我们可以直接使用任意你能打开的网站的链接

当然我还是保留了完整步骤。

你只需创建监听端口 7070 的源服务器

Java 复制代码
  @Override
  public void start(Promise<Void> startPromise) throws Exception {
    HttpServer originServer = vertx.createHttpServer();

    originServer.requestHandler(req -> {
      req.response()
        .putHeader("content-type", "text/html")
        .end("<html><body><h1>I'm the target resource!</h1></body></html>");
    }).listen(7070);
  }

3.5 使用 HttpProxy 的代理服务器

使用 HttpProxy 实例创建侦听端口 8080 的代理服务器,该实例相应地处理反向代理逻辑。

java 复制代码
  @Override
  public void start(Promise<Void> startPromise) throws Exception {
    HttpClient proxyClient = vertx.createHttpClient();

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

    HttpServer proxyServer = vertx.createHttpServer();

    proxyServer.requestHandler(proxy).listen(8080);
  }

最后,所有向外发出的请求都将作为反向代理方便地转发给源服务器。

官方教程到这里就结束了,只是代理某个ip+端口的服务,但是如果想代理某个网站呢?

4. 代理网站

代理某个网站的话,我们需要其实需要代理的是那个网站url+443端口,以及信任网站的证书

所以我们的verticle实现需要改一下,这里我直接使用了自己的博客链接,你可以改为任意地址

java 复制代码
  @Override
  public void start(Promise<Void> startPromise) throws Exception {
    HttpClient proxyClient = vertx.createHttpClient(new HttpClientOptions().setSsl(true).setTrustAll(true));

    // 创建一个 HttpProxy 实例
    HttpProxy proxy = HttpProxy.reverseProxy(proxyClient);
    // 配置目标服务器和端口
    proxy.origin(443, "runnable.run");
    // 设置 HttpServer 监听请求
    HttpServer proxyServer = vertx.createHttpServer();

    proxyServer.requestHandler(req -> {
      // 在此给请求添加 Host 头部
      req.headers().set("Host", "runnable.run");

      // 通过 HttpClient 转发请求到目标服务器
      proxy.handle(req);
    }).listen(8080, res -> {
      if (res.succeeded()) {
        System.out.println("Proxy server is running on port 8080, http://localhost:8080");
        startPromise.complete();
      } else {
        startPromise.fail(res.cause());
      }
    });
  }

然后给服务增加一个main方法启动试试

java 复制代码
  public static void main(String[] args) {
    VertxOptions vertxOptions = new VertxOptions();
    Vertx vertx  = Vertx.vertx(vertxOptions);
    DeploymentOptions deploymentOptions = new DeploymentOptions();
    vertx.deployVerticle(new MainVerticle(), deploymentOptions);
  }

4.1 完整代码如下

java 复制代码
package run.runnable.demo_vertx_reverse_proxy;

import io.vertx.core.*;
import io.vertx.core.http.HttpClient;
import io.vertx.core.http.HttpClientOptions;
import io.vertx.core.http.HttpServer;
import io.vertx.httpproxy.HttpProxy;

public class MainVerticle extends AbstractVerticle {

  @Override
  public void start(Promise<Void> startPromise) throws Exception {
    HttpClient proxyClient = vertx.createHttpClient(new HttpClientOptions().setSsl(true).setTrustAll(true));

    // 创建一个 HttpProxy 实例
    HttpProxy proxy = HttpProxy.reverseProxy(proxyClient);
    // 配置目标服务器和端口
    proxy.origin(443, "runnable.run");
    // 设置 HttpServer 监听请求
    HttpServer proxyServer = vertx.createHttpServer();

    proxyServer.requestHandler(req -> {
      // 在此给请求添加 Host 头部
      req.headers().set("Host", "runnable.run");

      // 通过 HttpClient 转发请求到目标服务器
      proxy.handle(req);
    }).listen(8080, res -> {
      if (res.succeeded()) {
        System.out.println("Proxy server is running on port 8080, http://localhost:8080");
        startPromise.complete();
      } else {
        startPromise.fail(res.cause());
      }
    });
  }

  public static void main(String[] args) {
    VertxOptions vertxOptions = new VertxOptions();
    Vertx vertx  = Vertx.vertx(vertxOptions);
    DeploymentOptions deploymentOptions = new DeploymentOptions();
    vertx.deployVerticle(new MainVerticle(), deploymentOptions);
  }
}

启动之后,使用浏览器打开 http://localhost:8080 就会发现已经是博客的页面了。所以如果你把这个反向代理在香港服务器部署,链接替换为google就。。。

复制代码
相关推荐
lybugproducer1 小时前
创建型设计模式之:简单工厂模式、工厂方法模式、抽象工厂模式、建造者模式和原型模式
java·设计模式·建造者模式·简单工厂模式·工厂方法模式·抽象工厂模式·面向对象
南客先生1 小时前
马架构的Netty、MQTT、CoAP面试之旅
java·mqtt·面试·netty·coap
Minyy111 小时前
SpringBoot程序的创建以及特点,配置文件,LogBack记录日志,配置过滤器、拦截器、全局异常
xml·java·spring boot·后端·spring·mybatis·logback
百锦再1 小时前
Java与Kotlin在Android开发中的全面对比分析
android·java·google·kotlin·app·效率·趋势
武昌库里写JAVA2 小时前
39.剖析无处不在的数据结构
java·vue.js·spring boot·课程设计·宠物管理
画个大饼3 小时前
Go语言实战:快速搭建完整的用户认证系统
开发语言·后端·golang
Nelson_hehe5 小时前
Java基础第四章、面向对象
java·语法基础·面向对象程序设计
Thomas_YXQ5 小时前
Unity3D Lua集成技术指南
java·开发语言·驱动开发·junit·全文检索·lua·unity3d
ShiinaMashirol6 小时前
代码随想录打卡|Day27(合并区间、单调递增的数字、监控二叉树)
java·算法
东阳马生架构7 小时前
Nacos简介—3.Nacos的配置简介
java