今天系统的讲一下TCP的负载均衡、高可用、可扩展架构。Web服务器负载平衡、高可用性和可扩展架构是如何实现的?在互联网架构中,web-server访问一般使用nginx作为反向代理来实现负载均衡。整个架构分为三层:上游调用层,一般是浏览器或者APP;中间的反向代理层,nginx;下游真实访问集群、web-server,常用的web-server有tomcat、apache;整个接入流程是怎样的?什么?浏览器向daojia.com发起请求;DNS解析daojia.com为外网IP(1.2.3.4);浏览器通过外网IP(1.2.3.4)访问nginx;nginx实现了一种负载均衡策略,常见的策略有roundquery、random、ip-hash等;nginx将请求转发给内网IP(192.168.0.1)的web-server;由于http连接短和web应用的无状态特性,理论上任何http请求落在所有web-server上都应该正常处理。画外音:如果一定要落在一个上,说明架构可能不合理,难以横向扩展。问题是tcp是有状态连接。客户端和服务器建立连接后,客户端发起的请求必须落在同一个tcp-server上。这个时候怎么做负载均衡,怎么保证横向扩展?方案一:单机方式tcp-server单机tcp-server显然可以保证请求的一致性:client向tcp.daojia.com发起tcp请求;DNS将tcp.daojia.com解析为外网IP(1.2.3.4);网络IP(1.2.3.4)向tcp-server发起请求;这个解决方案的缺点是什么?无法保证高可用性。方案二:集群方式tcp-server通过搭建tcp-server集群保证高可用,客户端实现负载均衡:客户端配置三个tcp-server外网IP:tcp1/tcp2/tcp3.daojia。com;客户端以“随机”的方式选择tcp-server,假设是tcp1.daojia.com;通过DNS解析tcp1.daojia.com;(4)通过外网IP连接真实的tcp-server;如何保证高可用?如果client发现某个tcp-server连接不上,就会选择另外一个。这个解决方案有什么缺点?每次连接前都需要多做一次DNS访问:DNS劫持难以防范;DNS访问多一次意味着连接时间变长,这种不足在手机端更加明显;如何解决DNS问题?直接在客户端配置IP就可以解决以上两个问题,这也是很多公司的做法,俗称“IP直通车”。“IP直通车”有哪些新问题?IP在客户端硬编码,负载均衡在客户端实现。扩展性很差:如果原IP发生变化,不会实时通知客户端;如果增加了新的IP,即使tcp-sever扩容,也不会实时通知客户端;如果负载均衡策略发生变化,则需要升级客户端;方案三:服务器实现负载均衡。只有将复杂的策略下沉到服务器,才能从根本上解决扩展性问题。增加一个http接口,把客户端的“IP配置”和“平衡策略”放在服务器上是一个很好的解决方案:在客户端访问tcp-server之前,先调用一个新的get-tcp-ip接口,对于As对于客户端而言,这个http接口只返回一个tcp-server的IP;这个http接口实现了原客户端的IP平衡策略;得到tcp-server的IP后,和之前一样向tcp-server发起TCP长连接;这样就解决了扩展性问题:如果原来的IP发生变化,只需要get-tcp-ip的配置接口需要修改;如果增加了新的IP,get-tcp-ip接口的配置也随之修改;如果负载均衡策略发生变化,无需升级客户端;然而,新的问题又出现了,如果所有IP都放在客户端,当一个IP挂了,客户端可以换一个IP连接保证可用性,而get-tcp-ip接口只维护静态的tcp-server集群IP.完全不知道这些IP对应的tcp-server是否可用。-服务器集群中的每台服务器是否可用,tcp-server主动上报是一个潜在的解决方案,如果某个tcp-server挂掉,则上报终止,对于停止上报状态的tcp-server,get-tcp-ipinterface,对应的tcp-server的外网IP不会返回给客户端。这个设计有问题吗?状态上报确实解决了tcp-server的高可用问题,但是这种设计造成了一个“反向依赖”的耦合小错误:让tcp-server依赖了一个与自身业务web无关的服务——服务器。方案五:tcp-server状态拉取更好的方案是:web-server通过“pull”获取各个tcp-server的状态,而不是tcp-server通过“push”上报自己的状态。这样每个tcp-server都是独立解耦的,只需要关注高级的tcp业务功能即可。高可用性、负载平衡和可扩展性等任务由get-tcp-ip的Web服务器专门执行。还有一点,在server端实现负载均衡还有一个好处,可以实现异构tcp-server的负载均衡和过载保护:静态实现:web-server下多个tcp-server的IP可以配置负载的权重,根据tcp-server机器配置分配负载(nginx也有类似的功能);动态实现:web-server可以根据被“拉”回来的tcp-server的状态动态分配负载,tcp-server的性能会急剧下降实现过载保护;总结(一)web-server是如何实现负载均衡的?使用nginx反向代理进行轮询、随机化和ip-hash。(2)tcp-server如何快速保证请求的一致性?独立的。(3)如何保证高可用?客户配置多个tcp-server域名。(4)如何防止DNS劫持和提速?IP直连,客户端配置多个tcp-serverIP。(5)如何保证可扩展性?服务端提供get-tcp-ip接口,对客户端屏幕屏蔽负载均衡策略,方便扩展。(6)如何保证高可用?tcp-server将状态“推”到get-tcp-ip接口,而orget-tcp-ip接口“拉”tcp-server状态。细节很重要,想法比细节更重要。【本文为专栏作者《58神剑》原创稿件,转载请联系原作者】点此阅读更多该作者好文
