架构实践
文章目录
保证session一致性
session:服务器为每个用户创建一个会话,存储用户的相关信息,以便多次请求能够定位到同一个上下文。
常见方法:
- session文件同步法:多台 web-server 相互同步数据
- 客户端同步法:一个用户只存储自己的数据
- 反向代理hash一致性:四层hash还是七层hash都可以做,保证一个用户的请求落在一台web-server上
- 后台统一存储:web-server重启和扩容,session也不会丢失,推荐redis存储
web层、service层无状态是大规模分布式系统设计原则之一,session属于状态,不宜放在web层,所以推荐后台统一存储。
降低第三方服务挂了的影响
首先,可以将第三方接口,收口到一个服务内。好处:
- 解除调用方与第三方接口的耦合;
- 当第三方的接口变动时,只有服务需要修改,而不是所有调用方均修改;
- 方便服务降级
跨公网调用第三方,可能存在的问题:
- 公网抖动,第三方服务不稳定,影响自身服务;
- 一个接口超时,占住工作线程,影响其他接口;
降低影响的优化方案:
- 增大工作线程,降低对其他接口的影响;
- 降低接口超时时间;
- 服务垂直拆分;
结合业务的解决方案:
- 业务能接受旧数据:读取本地数据,异步代理定期更新数据;
- 通过OpendID实时获取微信用户基本信息,先拿本地数据,再异步获取数据,更新本地数据
- 实名认证
- 有多个第三方服务提供商:多个第三方互备;
- 短信网关,可以购买多个短信网关,调用失败后调用另一个
- 邮件服务、电子合同
- 向第三方同步数据:本地写成功就算成功,异步向第三方同步数据;
- 外卖平台下单,平台再通知商家
改配置不用重启
- 发信号触发配置重载;
- 检测配置文件变化(文件md5值或last_modify_time),自动重新载入;
- 注册中心或配置中心,Apollo分布式配置中心;
TCP接入层的负载均衡+高可用架构
互联网架构中,web-server接入一般使用nginx来做反向代理,实施负载均衡。整个架构分三层:
- 上游调用层,一般是browser或者APP;
- 中间反向代理层,nginx;
- 下游真实接入集群,web-server,常见web-server的有tomcat,apache;
那整个访问过程是怎么样的?
- browser向目标网址发起请求;
- DNS将目标网址解析为外网IP(1.2.3.4);
- browser通过外网IP(1.2.3.4)访问nginx;
- nginx实施负载均衡策略,常见策略有轮询,随机,IP-hash等;
- nginx将请求转发给内网IP(192.168.0.1)的web-server;
由于http短连接,以及web应用无状态的特性,理论上任何一个http请求落在任意一台web-server都应该得到正常处理。 画外音:如果必须落在一台,说明架构可能不合理,难以水平扩展。
问题来了,tcp是有状态的连接,客户端和服务端一旦建立连接,一个client发起的请求必须落在同一台tcp-server上,此时如何做负载均衡,如何保证水平扩展呢?
方案一:单机法tcp-server
无法保证高可用。
方案二:集群法tcp-server
可以通过搭建tcp-server集群来保证高可用,客户端来实现负载均衡:
“IP直通车”有什么新问题? 将IP写死在客户端,在客户端实施负载均衡,扩展性很差:
- 如果原有IP发生变化,客户端得不到实时通知;
- 如果新增IP,即tcp-sever扩容,客户端也得不到实时通知;
- 如果负载均衡策略变化,需要升级客户端;
方案三:服务端实施负载均衡 只有将复杂的策略下沉到服务端,才能根本上解决扩展性的问题。
DNS,居然还能这么用?
一个http请求,典型的执行流程是怎么样的呢?
可以看到,典型流程为:
- 客户端请求dns-server,发起域名解析;
- dns-server返回域名对应的外网ip(1.2.3.4);
- 客户端通过外网ip(1.2.3.4),访问反向代理;
- 反向代理通过内网ip(192.168.x.x),将请求分发给web-server;
- web-server对请求进行处理;
除了域名解析,在架构设计时,还能利用DNS做一些什么事情呢?
-
用户就近访问 “智能DNS”
-
反向代理水平扩展
典型的互联网架构中,可以通过增加web-server来扩充web层的性能,但反向代理nginx仍是整个系统的唯一入口,如果系统吞吐超过nginx的性能极限,难以扩容,此时就需要dns-server来配合水平扩展。
具体做法是:在dns-server对于同一个域名可以配置多个nginx的外网ip,每次DNS解析请求,轮询返回不同的ip,这样就能实现nginx的水平扩展,这个方法叫“DNS轮询”。
- 利用DNS实施负载均衡
架构设计中,除了域名解析,DNS还有其他用武之地:
- 智能DNS,根据用户ip来就近访问服务器;
- DNS轮询,水平扩展反向代理层;
- 利用DNS实施负载均衡;
无锁缓存,每秒10万并发,怎么实现?
业务场景:
- 超高吞吐量,每秒要处理海量请求;
- 写多读少,大部分请求是对数据进行修改,少部分请求对数据进行读取;
解决方案:
- Map <key,val> 加锁(库级别锁);
- 减小锁粒度,key 取余后 加锁,或每个key单独加锁,但资源开销大(行级别锁);
- 无锁缓存,对数据签名(比如crc32)放到数据末尾,高并发下多线程写数据可能每个数据只写成功一半,读取时校验签名,不匹配丢弃再从数据库拉取;
P站,架构实践
Vanilla JS 框架
文章作者 小叨
上次更新 2022-02-11