亿级流量系统多级缓存架构5
资源隔离服务降级
什么叫资源隔离?
服务隔离是指在一个大型系统中,可以把原连接在一起的组件,模块,服务,资源拆分开。
那么在系统出现故障的时候,可以隔离故障,阻止传播,不会出现滚雪球和雪崩的效应。
隔离的方式主要有
- 线程隔离
- 进程隔离
- 集群隔离
- 机房隔离
- 读写隔离
- 动静隔离
- 爬虫隔离
- 等…
线程隔离
主要是在多线程环境下,对线程池进行治理,把核心业务和非核心业务分割开。
但是在多线程池下,不同线程池中的线程
在使用Netty的时候
netty本身是负载网络io的框架,想要做到网络服务和业务隔离, 首先它不应该和项目中的业务逻辑在同一线程池中
如果同一线程池中
Tomcat中的资源隔离
servlet3请求隔离
servlet 2.0
需要Tomcat7以上版本
Tomcat把连接介入和业务处理拆分成两个线程池来处理,即
Connector 介入连接,配置socket处理方式
可选
- Http11Protocol
- Http11NioProtocol
- Http11Nio2Protocol
- Http11AprProtocol
Connector**
在异 介入连接,可以采用BI/O,nio,ajp,apr.
性能提现的是qps,即介入连接数
Executor Servlet
可以使用独立的线程池来维护servlet的创建。
那么
connector能介入的请求肯定比业务复杂的servlet处理的个数要多,在中间,Tomcat还加入了队列,来等待servlet线程池空闲。
这两步是Tomcat内核完成的,在一阶段无法区分具体业务或资源,所以只能在连接介入,servlet初始化完成后我们根据自己的业务线去划分独立的连接池。
那么在独立的业务或资源中如果出现崩溃,不会影响其他的业务线程,从而达到资源隔离和服务降级的效果。
在使用了servlet3之后,系统线程隔离变得更灵活了。可以划分核心业务队列和非核心业务队列,
但是
- 资源一旦出现问题,虽然是隔离状态,想要让资源重新可用,很难做到不重启jvm。
- 线程池内部线程如果出现OOM、FullGC、cpu耗尽等问题也是无法控制的
结论
线程隔离,只能保证在分配线程这个资源上进行隔离,并不能保证整体稳定性
进程隔离
在项目最初期,一般都是allinone的技术架构,然后做负载均衡,session共享。
通过线程隔离无法完全避免雪崩。
java cpu、内存这些资源可以通过不同的虚拟机进程来做隔离。
- 集群式
- 分布式
集群隔离
如果系统中某个业务模块包含像
- 抢购、秒杀
- 存储I/O密集度高
- 网络I/o高
- 计算I/O高
这类需求的时候,很容易在并发量高的时候因为这种功能把整个模块占有的资源全部耗尽,导致响应编码甚至节点不可用。
解决方案
- 独立拆分模块
- 微服务化
可以使用hystrix在微服务中隔离分布式服务故障。他可以通过线程和信号量进行隔离。
机房隔离异地多活
解决数据容量大,计算,i/o(网络)密集度高的问题
把服务建立整体副本(计算服务、数据存储),在多机房内做异地多活或冷备份、是微服务数据异构的放大版
当在机房层面出现问题的时候,可以通过智能dns、httpdns、负载均衡等技术快速切换
数据(读写)分离
通过主从模式,将mysql、redis等数据存储服务集群化,读写分离,那么在写入数据不可用的时候,也可以通过重试机制临时通过其他节点读取到数据。
多节点在做子网划分的时候,除了异地多活,还可以做数据中心,所有数据在本地机房crud 异步同步到数据中心,数据中心再去分发数据给其他机房
那么数据临时在本地机房不可用的时候,就可以尝试连接异地机房或数据中心。
动静隔离
把静态资源从原有服务中隔离出来,参考cdn技术
***爬虫隔离
目前我们开发的都是API接口,并且多数都是开放的API接口。也就是说,只要有人拿到这个接口,任何人都可以通过这个API接口获取数据,那么像网络爬虫的,请求速度又快,获取的数据又多,不用多久,爬虫方完全可以用我们API的接口来开发一个同样的网站,这样的话,后果就有点严重了,所以我们需要限流,限制访问的频率
开放平台的API接口调用需要限制其频率,以节约服务器资源和避免恶意的频繁调用
在大型互联网项目中,对于web服务和网络爬虫的访问流量能达到5:1,甚至更高,有的系统有时候就会因为爬虫流量过高而导致资源耗尽,服务不可用。
限流维度
- 登录/会话限制
- 下载限流
- 访问频率
- ip限制,黑白名单
想要分辨出来一个访问是不是爬虫,可以简单的使用nginx来分析ua处理
nginx不仅可以处理ua来分离流量,还可以通过更强大的openresty来完成更复杂的逻辑,实现一个流量网关,软防火墙。
资源隔离
磁盘
数据库