网络代理于网络转发区别
网络代理:
用户不直接连接服务器,网络代理去连接,获取数据后返回给用户
网络转发:
是路由器对报文的转发操作,中间可能对数据包修改
网络代理类型:
正向代理:
实现一个web浏览器代理:
代码实现一个web浏览器代理:
代码实现:
反向代理:
如何实现一个反向代理:
- 这个功能比较复杂,我们先实现一个简版的http反向代理。
- 代理接收客户端请求,更改请求结构体信息
- 通过一定的负载均衡算法获取下游服务地址
- 把请求发送到下游服务器,并获取返回的内容
- 对返回的内容做一些处理,然后返回给客户端
启动两个http服务(真是服务地址)
real_server
启动一个代理服务
代理服务 127.0.0.1:2002(此处代码并没有使用负载均衡算法,只是简单地固定代理到其中一个服务器)
reverse_proxy
用户访问127.0.0.1:2002 反向代理到 127.0.0.1:2003
http代理
上面演示的是一个简版的http代理,不具备一下功能:
- 错误回调及错误日志处理
- 更改代理返回内容
- 负载均衡
- url重写
- 限流、熔断、降级
用golang官方提供的ReverseProxy实现一个http代理
- ReverseProxy功能点
- ReverseProxy实例
- ReverseProxy源码实现
拓展ReverseProxy功能
- 4中负载轮训类型实现以及接口封装
- 拓展中间件支持:限流、熔断实现、权限、数据统计
用ReverseProxy实现一个http代理:
ReverseProxy修改返回的内容
重写
ReverseProxy补充知识:
特殊Header头:X-Forward-For、X-Real-Ip、Connection、TE、Trailer
第一代理取出标准的逐段传输头(HOP-BY-HOP)
X-Forward-For
- 记录最后直连实际服务器之前,整个代理过程
- 可能会被伪造
X-Real-Ip
- 请求实际服务器的IP
- 每过一层代理都会被覆盖掉,只需要第一代里设置转发
- 不会被伪造
代码实现:
第一层代理
第二层代理
View Code
实际服务器:
View Code
负载均衡策略:
- 随机负载
- 随机挑选目标服务器ip
- 轮询负载
- ABC三台服务器,ABCABC一次轮询
- 加权负载
- 给目标设置访问权重,按照权重轮询
- 一致性hash负载
- 请求固定的url访问固定的ip
随机负载:
random.go
random_test
轮询负载:
round_tobin
round_robin_test
加权负载均衡:
- Weight
- 初始化时对节点约定的权重
- currentWeight
- 节点临时权重,每轮都会变化
- effectiveWeight
- 节点有效权重,默认与Weight相同
- totalWeight
- 所有节点有效权重之和:sum(effectiveWeight)
- 1,currentWeight = currentWeight + effectiveWeight
- 2,选中最大的currentWeight节点为选中的节点
- 3,currentWeight = currentWeight-totalWeight(4+3+2=9)
计算方法如下:
第一次:
- currentWeight = currentWeight + effectiveWeight
- currentWeight {A=4+4,B=3+3,C=2+2} == {A=8,B=6,C=4}
- 选中最大的currentWeight节点为选中的节点
- A最大 此时作为节点
- currentWeight = currentWeight-totalWeight(4+3+2=9) 【选中的节点currentWeight = currentWeight-totalWeight】
- currentWeight {A=8-9,B=6,C=4} == {A=-1,B=6,C=4}
第二次:{A=-1,B=6,C=4} 开始
- currentWeight = currentWeight + effectiveWeight
- currentWeight {A=-1+4,B=6+3,C=4+2} == {A=3,B=9,C=6}
- 选中最大的currentWeight节点为选中的节点
- B最大 此时作为节点
- 选中的节点currentWeight = currentWeight-totalWeight(4+3+2=9)
- currentWeight {A=3,B=9-9,C=6} == {A=3,B=0,C=6}
。。。。。。。以此类推。。。。。。。。。
weight_tound_robin.go
test
一致性hash(ip_hash、url_hash)
为了解决平衡性:引入了虚拟节点概念(把个节点 均匀的覆盖到环上)
consistent_hash.go
test.go
工厂方法简单封装上述几种拒载均衡调用:
interface.go
factory.go
调用: