5分钟搭建高性能HTTP反向代理,Go语言极简实现

你有没有遇到过这样的场景:本地开发时,前端需要调用后端接口,但跨域问题让人头疼;或者线上服务需要把不同路径的请求转发到不同端口,配置Nginx又嫌太重。其实,用Go语言自己写一个HTTP反向代理,代码不到50行,运行效率却吊打大多数配置方案。

今天我就带你手写一个生产可用的反向代理,支持路径规则转发、请求头透传、错误处理。就算你刚学Go两周,也能看懂。

核心思路

反向代理的核心是:接收客户端请求,根据规则把请求转发给后端真实服务,再把后端响应原样返回给客户端。Go标准库 net/http/httputil 里的 ReverseProxy 已经帮我们封装好了大部分逻辑,你只需要写一个路由匹配器就够了。

完整代码实现

下面是完整的Go代码,每一行都有中文注释,你直接复制就能跑。

package main

import (
    "log"
    "net/http"
    "net/http/httputil"
    "net/url"
    "strings"
)

// 定义一个映射表:路径前缀 -> 目标服务器地址
var routes = map[string]string{
    "/api/": "http://localhost:8081",   // 所有 /api/ 开头的请求转发到 8081
    "/web/": "http://localhost:8082",   // 所有 /web/ 开头的请求转发到 8082
}

// createProxy 根据目标地址创建一个反向代理处理器
func createProxy(target string) *httputil.ReverseProxy {
    // 解析目标URL,比如 "http://localhost:8081"
    targetURL, err := url.Parse(target)
    if err != nil {
        log.Fatalf("目标地址解析失败: %v", err)
    }
    // 新建反向代理实例
    proxy := httputil.NewSingleHostReverseProxy(targetURL)

    // 自定义错误处理:当后端服务挂掉时,返回友好的500页面
    proxy.ErrorHandler = func(w http.ResponseWriter, r *http.Request, err error) {
        log.Printf("代理错误: %v", err)
        http.Error(w, "后端服务暂时不可用,请稍后再试", http.StatusServiceUnavailable)
    }
    return proxy
}

// 路由分发处理器
func handler(w http.ResponseWriter, r *http.Request) {
    // 遍历路由表,寻找匹配的前缀
    for prefix, target := range routes {
        if strings.HasPrefix(r.URL.Path, prefix) {
            // 匹配成功,创建对应代理并转发请求
            proxy := createProxy(target)
            proxy.ServeHTTP(w, r)
            return
        }
    }
    // 没有匹配任何路由,返回404
    http.NotFound(w, r)
}

func main() {
    // 注册路由处理函数
    http.HandleFunc("/", handler)
    // 启动代理服务器,监听8888端口
    log.Println("反向代理已启动,监听端口 :8888")
    err := http.ListenAndServe(":8888", nil)
    if err != nil {
        log.Fatalf("服务器启动失败: %v", err)
    }
}

运行测试

  1. 先把代码保存为 proxy.go
  2. 确保你的后端服务已经在对应的端口上运行(比如8081和8082)。
  3. 终端执行 go run proxy.go
  4. 访问 http://localhost:8888/api/users,请求会被自动转发到 http://localhost:8081/users
  5. 访问 http://localhost:8888/web/index.html,请求被转发到 http://localhost:8082/index.html

进阶玩法

  • 负载均衡:可以把同一个路径映射到多个后端,用轮询或随机策略。
  • 请求头修改:在 ReverseProxyDirector 回调里修改 r.Header
  • HTTPS支持:用 http.ListenAndServeTLS 启动,或者在外面套一层Nginx。

这个代理占用的内存极小,启动速度毫秒级,特别适合微服务场景下的本地开发调试。如果你不想装Nginx或者用Docker,这个方案就是最轻量的选择。

类似文章