目录
- 1.长连接网关的必要性
- 2. 设计目标
- 2.1 技术挑战
- 2.2 技术目标
- 3. 方案选型
- 3.1 网关IP地址的选择
- 3.1.1 使用httpDNS服务
- 3.1.2 自建http server作为IP config server
- 3.1.3 最佳方案
- 3.2 高并发收发设计
- 3.2.1 C10K问题
- 3.2.2 方案探索
- 双协程监听channel实现全双工 + 一个定时器
1.长连接网关的必要性
在之前讲解关于消息可用性时,我们讲解过推拉结合(push & pull),而长连接网关的出现就是为了实现push模式,即主动及时地将消息发送到客户端,当然,收发平凡的业务场景也是我们选择长连接的原因之一。
2. 设计目标
2.1 技术挑战
- 客户端如何选择网关IP进行连接
- 网关服务器如何设计才能获取最大的并发力度,保证消息的低延迟,高吞吐?
- 作为一个有状态服务,服务端需要维护哪些状态,并尽可能减少状态维护占用内存量
- 业务层如何感知自身连接到哪一台网关,并进行消息下行分发,如何减少消息扇出?
- 某些场景下,客户端断开,如何进行快速重连,减少对用户体验的影响
- 如何实现对于网关的过载保护?
- 将网关服务中台化,适应多种业务场景的接入
- 多数据中心部署
2.2 技术目标
3. 方案选型
3.1 网关IP地址的选择
3.1.1 使用httpDNS服务
HTTPDNS(HTTP-based DNS)是一种基于HTTP协议的域名解析服务,它允许客户端通过HTTP请求获取域名对应的IP地址。传统的DNS解析通常是基于UDP协议的,而HTTPDNS则是通过HTTP协议来获取域名解析结果,具有更灵活的部署和使用方式。
下面是HTTPDNS的一般工作流程:
- 客户端发送HTTP请求到HTTPDNS服务器,请求包含需要解析的域名。
- HTTPDNS服务器接收到请求后,解析域名并返回对应的IP地址给客户端。
- 客户端收到IP地址后,将其用于访问目标服务器
使用httpDNS的优点有很多,包括根据网络状态和距离动态返回IP地址,负载均衡等,对于我们来说,最重要的是其安全性,可以防止DNS劫持:
-
DNS劫持
DNS劫持是一种网络攻击,通过篡改DNS(Domain Name System)解析结果,将合法的域名解析到错误的IP地址上,从而将用户的请求重定向到恶意网站或者错误的服务器上。这种攻击可以在用户不知情的情况下进行,对网络安全构成潜在威胁。DNS劫持的实施方式通常有以下几种:
-
本地Hosts文件劫持: 攻击者可以修改用户计算机上的Hosts文件,将某些合法域名解析到恶意的IP地址上。当用户访问这些域名时,计算机会优先使用Hosts文件中的解析结果,从而将用户重定向到攻击者控制的网站。
-
路由器劫持: 攻击者可以篡改路由器的DNS设置,将合法域名解析到错误的IP地址上。当用户连接到这个被篡改的路由器时,所有通过该路由器进行的DNS解析都会受到影响,导致用户访问的网站被重定向到恶意站点。
-
DNS服务器劫持: 攻击者可以攻击DNS服务器,篡改其解析结果,将合法域名解析到错误的IP地址上。当用户使用受影响的DNS服务器进行域名解析时,会收到错误的解析结果,从而被重定向到攻击者控制的网站。
DNS劫持可能会导致以下问题:
- 用户访问到恶意网站,泄露个人信息或遭受其他安全威胁。
- 用户被导向到错误的服务器上,导致网络访问速度变慢或者服务不稳定。
- 网站的流量被劫持到恶意网站上,造成业务损失或者名誉受损。
-
-
HTTPDNS防御DNS劫持机制
HTTPDNS主要通过将DNS解析的过程移至HTTP协议下来防范DNS劫持。
它的基本原理是将域名解析请求发送到HTTP服务器,由服务器返回域名对应的IP地址。相比传统的DNS解析,HTTPDNS的主要优势在于可以避免受到DNS劫持的影响,提高解析的准确性和可靠性。
HTTPDNS防范DNS劫持的方法主要包括以下几点:
-
HTTPS加密通信: HTTPDNS通常采用HTTPS协议与HTTPDNS服务器进行通信,确保通信过程中的数据传输安全和完整性,防止数据被篡改或窃取。
-
服务器认证: HTTPDNS服务器可以使用SSL证书进行身份认证,客户端在与服务器建立连接时验证证书的有效性,确保连接到的是合法的HTTPDNS服务器,防止中间人攻击。
-
多地域多IP解析: HTTPDNS通常会返回多个地域的IP地址,并且这些IP地址会根据网络环境的不同进行动态调整和优化。即使某个地域的IP地址受到了劫持,仍然可以通过其他地域的IP地址来提供正常的解析服务。
-
实时监控和切换: HTTPDNS服务商会对服务器的IP地址进行实时监控,一旦发现IP地址受到劫持或异常,会立即切换到备用IP地址,保证服务的可用性和稳定性。
-
缓存策略: HTTPDNS客户端通常会采用缓存策略,将解析结果缓存到本地,避免频繁地向服务器发送解析请求,降低网络延迟和提高解析速度。同时,客户端会定期更新缓存,获取最新的IP地址信息。
-
3.1.2 自建http server作为IP config server
- 为什么需要自建IP CONFIG
虽然HTTPDNS有一定的调度策略来帮助我们选择网关地址,但是毕竟其是一个通用的服务,不能只对我们的长连接场景来进行针对性的调度
自建http server一方面提供了更高的可靠性,同时可以基于业务场景做出智能调度策略。
3.1.3 最佳方案
我们将HTTPDNS与自建http server 同时使用,HTTPDNS保障localDNS劫持问题,自建http server保障有效的调度。
- 业务流程
3.2 高并发收发设计
3.2.1 C10K问题
在十多年前,互联网并不发达的时候,就有人提出了著名的C10K问题:
- C10K问题指的是支持同时连接到服务器的客户端数量达到10,000个的挑战。在网络编程中,这是一个重要的问题,特别是对于服务器需要处理大量并发连接的场景,比如Web服务器、聊天服务器等。C10K问题的挑战主要来自于服务器需要同时处理大量的客户端连接请求,而传统的同步I/O模型无法有效地应对这种高并发的需求。在传统的同步I/O模型中,每个连接都需要一个独立的线程或进程来处理,当连接数量很大时,会消耗大量的系统资源,导致性能下降甚至系统崩溃
显然,在如今的互联网场景下,C10K已经不是所追求的目标,C100K,C1000K是更加现实的需求,但是,C10K问题的提出确实大大推进了服务器设计的发展进程。
3.2.2 方案探索
双协程监听channel实现全双工 + 一个定时器
- 一个线程监听accept
- 使用accept返回的连接socket创建连接,同时对这个sock穿件两个协程分别收发消息
- 当发现某个sock有数据到来,使用read channel将消息上报给线程池,分配线程进行处理
- 服务端设置飞行队列,存储回复消息,每发送一个消息时创建一个协程,建立一个定时器,并在等待client ack时阻塞
优点:
- 实现简单 (以上实现可参考开源方案 goim)
- go协程十分轻量,通过水平拓展可以达到百万连接
缺点:
- 内存开销大,难以突破 C10M瓶颈
- 协程多,协程调度开销大,延迟拉高
- 一个协程4K内存,几万长连接下内存占用超64G机器极限,OOM风险高
- 每个下行消息都需要1 goruntinue + 1 timer ,push场景下容易OOM
在下一篇文章中,我们将接续介绍更多的实现方案,以长连接所需要维护的信息有哪些