目 录CONTENT

文章目录

正向代理和反向代理实现

Sakura
2024-01-18 / 0 评论 / 0 点赞 / 18 阅读 / 8171 字 / 正在检测是否收录...

正向代理和反向代理实现

1. 两者基本概念

网络代理 : 控制和管理某个网络主机的访问

  1. 控制:客户端/服务端流量控制,黑/白名单,权限校验,URL重写

  2. 管理:流量控制,编解码,Header头转换,负载均衡,服务发现,连接池

访问流程:

  1. 用户访问代理服务器

  2. 请求通过网络代理完成转发等到目标服务器

  3. 目标服务器响应后再通过网络代理回传给用户

转发的区别在于

转发: 对 IP 分组进行发送

代理: 对下游服务器的访问控制 ( 源节点 , 目标节点 )

1.1 正向代理 (客户端代理)

功能:帮助客户访问无法访问的服务器资源,隐藏用户真实 IP ,浏览器 web代理,VPN

  • 帮助客户访问无法访问的服务器资源

用户 A 无法直接访问 google 服务器,这时即可以通过代理服务器,讲请求发送给代理服务器,由代理服务器代替用户 A 访问 google 服务器,代理服务器将结果返回给用户 A

  • 缓存数据

用户 A 通过代理服务器访问服务器上的某一份资源,代理服务器接收到数据后会一份数据到本地,如果用户 B 也想要同一份数据,就可以直接在代理服务器上获取

  • 隐藏用户真实 IP

用户 A 想要访问某台服务器,但是不想让服务器知道是他在访问,就可以让代理服务器代替用户 A 访问,“肉鸡”就是一台代理服务器

1.2 反向代理 (服务端代理)

为服务器做负载均衡,缓存,提供安全校验等

  • 保护服务器(隐藏服务器真实 IP)

为了保护真实的服务器,用户 A 只能通过访问代理服务器来请求真正的服务器,这样就保证了服务器的安全

  • 负载均衡

假设有 1000 个用户在对某个服务发送请求,代理服务器通过负载均衡算法,可以讲这些求求分发到不同的服务器去进行处理,从而提供服务处理效率,减小服务器的压力

微服务中的限流和认证都可以理解为是反向代理的功能

2. 正向代理实现

实现步骤

  1. 启动一个真实的下游服务器

  2. 代理服务器接受客户端请求,复制,封装

  3. 发送新请求到真实服务器,接收响应

  4. 处理响应并返回客户单

// 启动真实的http服务器
func HttpServer() {
	// 一: 设置不同路由对应的不同处理器
	// 第一种方式: HandleFunc
	http.HandleFunc("/ping", HandlerPing)

	// 二:启动监听
	addr := ":8080"
	log.Println("HTTP 服务器正在监听: ", addr)
	if err := http.ListenAndServe(addr, nil); err != nil {
		log.Fatalln(err)
	}
}

func HandlerPing(writer http.ResponseWriter, request *http.Request) {
	fmt.Fprintf(writer, "pong")
}
func ForwardProxyServer() {
	fmt.Println("正向代理服务器启动 :8080")
	http.Handle("/", &Pxy{})
	http.ListenAndServe("127.0.0.1:8080", nil)
}

// Pxy 定义一个类型,实现 Handler interface
type Pxy struct{}

// ServeHTTP 具体实现方法
func (p *Pxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
	fmt.Printf("Received request %s %s %s:\n", req.Method, req.Host, req.RemoteAddr)
	// 1. 代理服务器接收客户端请求,复制,封装成新请求
	outReq := &http.Request{}
	*outReq = *req
	if clientIP, _, err := net.SplitHostPort(req.RemoteAddr); err == nil {
		// XFF,用来识别通过HTTP代理或负载均衡方式连接到Web服务器的客户端最原始的IP地址的HTTP请求头字段
		if prior, ok := outReq.Header["X-Forwarded-For"]; ok {
			clientIP = strings.Join(prior, ", ") + ", " + clientIP
		}
		outReq.Header.Set("X-Forwarded-For", clientIP)
	}
	//fmt.Printf("req %s:\n", req.Header.Get("X-Forwarded-For"))
	//fmt.Printf("outReq %s:\n", outReq.Header.Get("X-Forwarded-For"))

	// 2. 发送新请求到下游真实服务器,接收响应
	transport := http.DefaultTransport
	res, err := transport.RoundTrip(outReq)
	if err != nil {
		rw.WriteHeader(http.StatusBadGateway)
		return
	}

	// 3. 处理响应并返回上游客户端
	for key, value := range res.Header {
		for _, v := range value {
			rw.Header().Add(key, v)
		}
	}
	rw.WriteHeader(res.StatusCode)
	io.Copy(rw, res.Body)
	res.Body.Close()
}

3. 反向代理实现

实现步骤

  1. 启动一个真实服务器: gateway/proxy/http_proxy/downstream_real_server.go

  2. 代理接收客户端请求,更改请求结构体信息

  3. 通过一定的负载均衡算法获取下游服务地址 // 3.把请求发送到下游服务器,并获取返回内容

  4. 对返回内容做一些处理,然后返回给客户端

// 1.启动真实的服务器
func RealHTTPServer() {
	// 初始化RealServer服务器结构体
	server := RealServer{Addr: "127.0.0.1:8001"}
	server.Run()
	select {}
}

func (r *RealServer) Run() {
	mux := http.NewServeMux()
	mux.HandleFunc("/sakura", r.HelloHandler)
	server := http.Server{
		Addr:         r.Addr,
		Handler:      mux,
		WriteTimeout: time.Second * 3,
	}
	go func() {
		fmt.Println("http服务器务已启动:", server.Addr)
		server.ListenAndServe()
	}()
}

type RealServer struct {
	Addr string
}

func (r *RealServer) HelloHandler(w http.ResponseWriter, req *http.Request) {
	// 拼接真实服务器地址
	URL := fmt.Sprintf("这是真实服务器,地址为: http://%s%s", r.Addr, req.URL.Path)
	w.Write([]byte(URL))
}
func CustomerReverseProxySever() {
	var port = "8081" // 当前代理服务器端口
	http.HandleFunc("/", handler)
	fmt.Println("反向代理服务器启动: " + port)
	http.ListenAndServe(":"+port, nil)
}

var (
	proxyAddr = "http://127.0.0.1:8001"
)

func handler(w http.ResponseWriter, r *http.Request) {
	fmt.Println("经过代理服务器地址")
	// 1.解析下游服务器地址,更改请求地址
	// 被代理的下游真实服务器地址.应该通过一定的负载均衡算法获取
	realServer, err := url.Parse(proxyAddr)
	r.URL.Scheme = realServer.Scheme // http
	r.URL.Host = realServer.Host     // 127.0.0.1:8001

	// 2.请求下游(真实服务器),并获取返回内容
	transport := http.DefaultTransport
	resp, err := transport.RoundTrip(r) // 得到下游服务器响应
	defer resp.Body.Close()
	if err != nil {
		log.Print(err)
		return
	}

	// 3.把下游请求内容做一些处理,然后返回给上游(客户端)
	for k, vv := range resp.Header { // 修改上游响应头
		for _, v := range vv {
			w.Header().Add(k, v)
		}
	}
	bufio.NewReader(resp.Body).WriteTo(w) // 将下游响应体写回上游客户端
}

4. 使用 ReverseProxy 实现反向代理

  • 使用 ReverseProxy 实现一个简易版的代理服务器

var (
	//代理服务器地址
	proxyAddr = "127.0.0.1:8081"
)


// 使用 ReverProxy 实现反向代理
func ReverseProxySever() {
	// 解析下游服务器的真实地址
	realServer := "http://127.0.0.1:8001"
	serverUrl, err := url.Parse(realServer)
	if err != nil {
		log.Fatalln("parse fail,")
	}
	proxy := httputil.NewSingleHostReverseProxy(serverUrl)
	log.Println("Starting proxy Server:", proxyAddr)
	// proxy 就相当于 handle
	http.ListenAndServe(proxyAddr, proxy)
}
  1. 启动代理服务器

  1. 启动真实服务器

  1. 使用代理服务器的地址访问真实服务器的路由

0

评论区