Go实现网关服务
前言
基本功能
支持多种协议代理:tcp/http/websocket/grpc
支持多种负载均衡策略:轮询/加权轮询/一致性Hash
支持下游服务发现:主动探测/自动服务发现
支持横向扩容:加机器就能解决高并发
借助网关处理高可用、高并发
限流:请求QPS限制
熔断:错误率达阈值服务熔断
降级:确保核心业务可用
权限认证:拦截没有权限的用户
计算机网络基础
OSI七层网络协议与TCP/IP协议

经典协议与数据包
数据包

在物理层传输的是以太网帧,它由以太网首部(主要包含机器mac信息等)和IP数据包构成。
在网络层传输的是IP数据包,它由IP首部和TCP段构成。
在传输层传输的是TCP段,它由TCP首部和应用数据构成。如果应用数据过大则会进行拆包,那么需要在应用数据中数据的包定义起点、终点。
在应用层传输的是应用数据,它由应用头部和用户数据构成。
HTTP协议
HTTP协议是明文传输的。
如下是HTTP的请求报文和响应报文

Websocket握手协议
基于HTTP协议实现,完成连接后以二进制流方式进行传输

Websocket数据包

三次握手与四次挥手
三次握手

四次挥手

抓包分析三次握手和四次挥手
命令:tcpdump -n -S -i eth0 host www.baidu.com and tcp port 80

为什么关闭方要等待2MSL?
保证连接可靠关闭
保证所有数据都传输完成
为什么会大量close_wait?
并发请求数太多导致的
被动关闭方未及时释放端口资源导致
close_wait一般出现在被动关闭方
TCP流量控制
流量控制来控制通讯双方数据发送的频率
由于通讯双方网速不同。任一方数据发送过快都会导致对方消息处理不过来,一般会先把数据放到缓存区中。如果缓冲区满了,发送方还在疯狂发送数据,数据包将会被丢弃。因此我们需要控制发送频率,TCP则是通过流量控制来控制发送频率。

TCP拥塞控制
拥塞控制用来调节网络的负载
接收方网络资源繁忙,因未及时响应ACK导致发送方重传大量数据,将是的网络更加拥堵。拥塞控制可以动态调整窗口大小,不只是依赖缓冲区大小确定窗口。
慢启动和拥塞避免

在慢启动阶段从1开始以2倍扩大的方式指数增长至慢启动阈值,接着进入拥塞避免加法增大(每次增大1),如果遇到网络拥塞的情况则会直接将窗口置为1,慢启动阈值置为原来的一般,继续进入慢启动阶段。
快速重传和快速恢复

最开始仍然采用慢启动和拥塞避免算法。不同的是在收到3个重复ACK执行快重传,快重传(乘法减小)是将拥塞窗口降为原来的一半,将拥塞避免的阈值也降为原来的一半,接着进入快速恢复阶段。快速恢复对数据进行重传,重传完毕后,进入拥塞避免(加法增大)。
为啥会出现粘包、拆包,如何处理?

应用程序写入的数据大于套接字缓冲区大小,将会发生拆包。
进行MSS(最大报文长度)大小的TCP分段,当TCP报文长度 - TCP头部长度 > MSS时将发生拆包。
应用程序写入的数据小于套接字缓存区大小,网卡将应用多次写入的数据发送到网络上,将发送粘包。
接收方法不及时读取套接字缓冲区数据,将发生粘包。
如何获取完整的应用数据报文?
使用带消息头的协议,头部写入包长度,然后读取包内容。
设置定长消息,每次读取定长内容,长度不够时空位补固定字符。
设置消息边界,服务端从网络流中按消息边界分离出消息内容,一般使用
在应用层我们还可以直接选择如
protobuf、json等协议。
基于go实现TCP、UDP、HTTP服务器与客户端
TCP
服务端
客户端
UDP
服务端
客户端
HTTP
服务端
客户端
net包阅读(有一定难度,建议看完如Gin等库实现后再看)
网络代理
网络代理和网络转发的区别
网络代理
用户不直接连接服务器,网络代理去连接。获取数据后返回给用户。
用户通过代理请求信息,请求通过网络代理完成转发到达目的服务器,目标服务器响应后再通过网络代理回传给用户。

网络转发
是路由器对报文的转发操作,中间可能对数据包修改。

网络代理类型
正向代理
是一种客户端的代理技术,帮助客户端访问无法访问的服务资源,可以隐藏用户真实IP。比如:浏览器web代理、VPN等。
正向代理示例:实现一个简单的浏览器代理
反向代理
是一种服务端的代理技术,帮助服务器做负载均衡、缓存、提供安全校验等,可以隐藏服务器的真实IP。比如:LVS技术、nginx等

反向代理示例:简单的服务器代理
代理
服务器
演示
HTTP代理
功能:
错误回调及错误日志处理
更改代理返回内容
负载均衡
URL重写
限流、熔断、降级
数据统计
权限认证
ReverseProxy功能点
支持更改内容
错误信息回调
支持自定义负载均衡
URL重写功能
连接池
支持Websocket服务(后续介绍)
支持HTTPS代理(后续介绍)
在net/http/httputil下定义了ReverseProxy
基于ReverseProxy实现简易的HTTP代理
ReverseProxy更改内容支持
特殊的Header头
"X-Forwarded-For": 标记客户端地址每个方向服务器代理的IP
"X-Real-IP": 我的实际请求的标记
"Connection": 标记连接是关闭、长连接等状态
"TE": 标记传输类型是什么
"Trailer": 允许发送方在消息后面添加的一些源信息
拓展ReverseProxy功能
负载均衡
随机负载:随机挑选目标服务器IP
轮询负载:遍历服务器列表
加权负载:给目标设置访问权重,按权重轮询(参考Nginx的负载均衡)

一致性Hash负载:请求固定URL访问指定IP
HTTPS代理
Websocket代理
TCP代理
中间件(可以参考Gin)
洋葱结构的原理
go中间件数据传递
中间件实现
中间件一般都封装在路由上,路由是URL请求分发的的管理器。
基于数据构建中间件,使用灵活,控制方便。基于链表实现不仅复杂,且难以调用。
责任链模式(基于链表构建)
方法切片模式(基于数组构建)
方法组装
构建中间件路由
构建URL的中间件方法数组
使用use方法整合路由与方法数组

方法调用
构建方法请求逻辑
封装
http.Handler接口与http.Server整合

中间件的意义
提高复用、隔离业务。将公共逻辑剥离

调用清晰、组合随意

参考
限流和熔断降级
限流
高并发系统的三大利器:缓存、降级、限流
缓存:提升业务系统访问速度和增大处理容量,为相应业务增加缓存。
降级:当服务器压力剧增时,根据业务策略降级,以此释放服务资源保证业务正常。
限流:通过对并发限速,以达到拒绝服务、排队或等待、降级等处理。
限流原理
漏桶限流:每次请求时计算桶流量,超过阈值则降级请求。

令牌桶限流:每次请求时从令牌桶里取出令牌,取不到则降级请求。

网关集成限流
熔断降级
熔断器是当依赖的服务已经出现故障时,为了保证自身服务的正常运行不再访问依赖的服务,防止雪崩效应。
降级是当服务器压力剧增时,根据业务策略降级,以此释放服务资源保证业务正常。
熔断器的三个状态
服务关闭:服务正常,维护失败率统计,达到失败率阈值时,转到开启状态。
开启状态:调用fallback函数,一段时间后,进入半开启状态。
半开启状态:尝试恢复服务,失败率高于阈值,进入开启状态,低于阈值,进入关闭状态。
熔断降级原理

网关集成熔断降级
选择go类库:hystrix-go
Websocket
WebSocket协议

请求URL如ws://127.0.0.1:2002/echo,以ws开头表示协议是websocket
Websocket数据传输协议

Connection Header头意义
标记请求发起方与第一代理的状态
决定当前事物完成后,是否关闭网络
Connection: keep-alive 不关闭网络
Connection: close 关闭网络
Connection: Upgrade 协议升级
Websocket代理服务器
HTTP、HTTPS、HTTP2
HTTPS与HTTP的区别
HTTPS是HTTP协议的安全版本,HTTP协议的数据传输是明文的,是不安全的,HTTPS使用了SSL/TLS协议进行了加密处理
HTTP默认端口是80,HTTPS默认端口是443。
HTTPS请求流程:

HTTP2和HTTP
HTTP2采用二进制格式而非文本格式。
HTTP2使用一个连接实现多路复用。
HTTP2压缩了报头,降低了开销。
HTTP2让服务器可以将响应主动“推送”到客户端缓存。
HTTP2和HTTPS的关系
HTTP2代表多路复用的传输协议
HTTPS代表HTTP服务器使用了加密传输
一个启用HTTPS的服务器不一定使用HTTP2
但是使用HTTP2的服务器必须启动HTTPS(浏览器强制)
HTTP2的补充
HTTP2设计目标
大多数情况下的感知延迟要有实质上改进
解决HTTP1.1中“队首阻塞”问题
并行操作无需与服务器建立多个连接
保持HTTP1.1的语义,只是标准拓展非替代
HTTP2基本概念
流:流是连接中的一个虚拟信道,可以承载双向的消息
消息:是指逻辑上的HTTP消息,比如请求、响应等
帧:HTTP2通信的最小单位,没个帧包含帧首部,至少会标识出当前帧所属的流,承载着特定类型的数据。
HTTP2多路复用
HTTP2首部压缩
HTTP2协议磋商
询问服务器是否支持HTTP2,不支持则将为HTTP1.1
发起带有HTTP2 Upgrade首部的HTTP1.1请求
服务端拒绝升级,通过HTTP1.1返回响应
服务器接受HTTP2升级,切换到新分帧
TCP代理
四层负载均衡和七层负载均衡
路由转发客户端和服务器之间有一次三次握手
反向代理客户端和服务端之间有两次三次握手
四层负载均衡(路由转发)

NAT作用于内核运行的
七层负载均衡(反向代理)

代理是用户程序运行的。代理的数据会进入程序buffer中
gRPC透明代理
数据库表整理与创建
设计原则:数据库三大范式
列不可再分:如服务名、服务描述等属性不可再进一步拆分了。
属性完全依赖于主键:服务名依赖于服务ID
属性直接依赖于主键
E-R图
最后更新于
这有帮助吗?