作者:Harmonica链接:https://www.cnblogs.com/Coura...为什么要进行资源隔离公共资源,如磁盘、网络、CPU等,都会存在竞争问题。在构建分布式架构时,可以将原本连接在一起的组件、模块和资源分开,以实现最大的利用效率或性能。资源隔离后,当某一部分组件出现故障时,可以隔离故障,便于定位,防止传播,避免滚雪球和雪崩效应。常见的隔离方式有:线程隔离、进程隔离、集群隔离、机房隔离、读写隔离、动静态隔离、爬虫隔离等线程隔离。核心业务线程与非核心业务线程分离。不同的业务需要不同的线程数。可以设置不同的线程池来给出框架中的一些应用实例,比如Netty中的主从多线程、Tomcat请求隔离、Dubbo线程模型等。Netty主从模型的主线程负责认证和连接。成功后,从线程负责连接的读写操作。代码大致如下:EventLoopGroupbossGroup=newNioEventLoopGroup(1);EventLoopGroupworkerGroup=newNioEventLoopGroup();ServerBootstrapb=newServerBootstrap();b.group(bossGroup,workerGroup);主线程为单线程,从线程为线程池,默认为cpu*2个数。你可以在我们的业务处理程序中做一个简单的测试:+msg);}服务器读取数据时打印看一下当前线程:threadname=nioEventLoopGroup-3-1serverreceivemsg="..."可以发现这里使用的线程其实和处理io线程;Dubbo线程隔离模型Dubbo的底层通信框架其实使用的是Netty,但是Dubbo并没有直接使用Netty的io线程来处理业务,可以简单的在producer端输出当前的线程名:threadname=DubboServerHandler-192.168.1.115:20880-thread-2,...可以发现使用业务逻辑的不是nioEventLoopGroup线程。这是因为Dubbo有自己的线程模型。可以看看官网提供的模型图:从图中可以看出,Dubbo服务器收到请求后,通过调度器(Dispatcher)分发到不同的线程池中。另外简单总结一下Dispatcher:Dispatcher调度器可以配置消息处理线程:所有的消息都派发到线程池,包括请求、响应、连接事件、断开事件、心跳等,Direct所有的消息都不派发到线程池,而且都是直接在IO线程上执行的。message只将请求响应消息派发到线程池,其他连接断开事件、心跳等消息直接在IO线程上执行。execution只派发请求消息到线程池,不包括response、response等连接断开事件、心跳等消息,直接在IO线程上执行。connection在IO线程上,将连接断开事件放入队列中,有序的一条条执行,其他消息派发到线程池。通过查看源码我们可以知道,Dubbo默认使用的线程池为FixedThreadPool,线程数默认为200;Tomcat请求线程隔离Tomcat是Servelet的具体实现,Tomcat请求支持四种请求处理方式:BIO、AIO、NIO、APRBIO模式:阻塞I/O操作,也就是说Tomcat使用传统的Java。I/O操作(即Java.io包及其子包)。Tomcat7以下版本默认以bio模式运行。由于每个请求都需要创建一个线程来处理,线程开销大,无法应对高并发场景,性能是几种模式中最低的。NIO模式:同步非阻塞I/O操作,是一种基于缓冲区的API,可以提供非阻塞I/O操作,具有比传统I/O操作更好的并发性能。Tomcat7版本之后,Tomcat将连接干预和业务处理拆分成两个线程池进行处理,即可以使用一个独立的线程池来维护servlet的创建。connector能够干预的请求数必须大于业务复杂的servlet处理的请求数。中间Tomcat加入队列等待servlet线程池空闲。这两步都是由Tomcat内核完成的。第一阶段无法区分具体的服务或资源,只能介入连接。servlet初始化完成后,我们根据自己的业务线划分独立的连接池。这样,如果一个独立的业务或资源发生崩溃,不会影响其他业务线程,从而达到资源隔离和服务降级的效果。使用servlet3后,系统线程隔离变得更加灵活。可以分为核心业务队列和非核心业务队列:线程隔离的小总结。一旦某个资源出现问题,虽然处于隔离状态,但如果不重启jvm,很难让该资源再次可用。如果线程池内部线程出现OOM、FullGC、CPU耗尽等问题,线程隔离是不可控的。只能保证分配线程资源上的隔离,不能保证整体的稳定性。陌生的是,在Linux操作系统中,通过文件管理系统将各个进程的虚拟内存映射到实际的物理内存。这样做的好处是避免了不同进程之间的相互影响。在分布式系统中,线程隔离并不能完全隔离故障,避免雪崩。比如一个线程组内存不足导致OOM,其他线程组也会受到影响。所以,进程隔离的思想就是通过不同的虚拟机,将CPU、内存等资源也隔离开来。具体操作是将业务逻辑拆分到多个子系统(拆分原理参考:Redis集群拆分原理之AKF),实现物理隔离,当某个子系统出现问题时,不会影响到其他子系统子系统。集群隔离如果系统中某个业务模块存在抢购、闪购、高存储I/O强度、高网络I/O、高计算I/O等需求,当并发度高。该函数耗尽了整个模块占用的所有资源,导致响应编码甚至节点不可用。如上图拆分后,如果某天购物人数突然增加,可能会影响电商交易功能模块。损坏后,电子商务模块的其他浏览查询将无法使用。所以需要建立集群进行隔离。也就是说,继续拆分模块,把功能变成微服务。解决方案独立拆分模块微服务可以使用hystrix隔离微服务中的分布式服务故障。他可以被线程和信号量隔离。线程池隔离和信号量隔离的比较这里和上面的线程隔离一样,不赘述,简单描述一下hystrix的两种隔离方式的区别:隔离方式是否支持超时,是否支持熔断隔离原理,是否是异步调用资源消耗线程池隔离支持,可以直接返回支持。当线程池达到maxSize时,请求会触发fallback接口熔断。每个服务都可以独立使用线程池,可以是异步的也可以是同步的。大量的调用方法和大量线程的上下文切换很容易造成机器负载高。不支持信号量隔离。如果是阻塞,只能通过调用协议支持(如:socket超时返回),当信号量达到maxConcurrentRequests时。再次请求会触发fallback通过信号量的计数器同步调用。它不支持异步小。它只是一个计数器信号量隔离。也就是说,有很多线程过来,需要获取信号量。只有获得信号量后,才能继续执行。否则,它将首先进入队列。等待或者直接fallbackcallback最重要的是信号量的调用是同步的,即每次调用都要阻塞调用者的线程,直到返回结果。这就导致无法超时访问(只能靠调用协议超时,不能主动释放)。官方网站上对信号量隔离的描述表明,通常只有当调用量如此之大(每个实例每秒数百次)以至于单独线程的开销太高时,您才应该为HystrixCommands使用信号量隔离;这通常只适用于非网络呼叫。理解以下两点:细粒度隔离太高,需要隔离数百个实例。这个时候用线程池隔离成本太高了。通常,这是非网络呼叫的情况。机房隔离的主要目的有两个。一是将不同地域的用户数据隔离到不同地域。比如湖北的数据放在湖北的服务器上。浙江的放在浙江服务器等,可以解决数据容量大、计算密集、I/O(网络)强度高等问题,相当于把流量分到各个区域。另一方面,机房的隔离也是为了保证安全。所有数据都放在一个地方。如果发生自然灾害或爆炸,所有数据都将丢失。因此,在多个机房多活或异地冷备份建立服务(计算服务、数据存储)的整体副本,是微服务数据异构的放大版。如果机房层面出现问题,可以通过智能dns、httpdns、负载均衡等技术快速切换,尽可能让区域用户不受影响。数据读写隔离采用主从模式集群mysql、redis等数据存储服务,读写分离。然后,当写入的数据不可用时,也可以通过重试机制,通过其他节点临时读取数据。多节点划分子网时,除了可以异地多活外,还可以作为数据中心使用。所有数据在本地机房CRUD异步同步到数据中心,再由数据中心分发到其他机房,所以数据不能暂时存放在本地机房。使用时,可以尝试连接到远程机房或数据中心。静态隔离的主要思想是在边缘服务器中分布一些静态资源,因为很多资源在日常访问中不会发生变化,所以不需要每次都从主服务器上获取,这些数据可以保存下来在边缘服务器上减轻主服务器的压力。有一个非常详细的解释参考:全局负载均衡和CDN内容分发爬虫隔离建立适当的规则将爬虫请求转移到另一个集群。目前我们开发的都是API接口,而且大部分都是开放的API接口。也就是说,只要有人拿到这个接口,任何人都可以通过这个API接口获取数据。如果网络爬虫请求速度快,获取的数据很多,不仅会对服务器造成影响,而且爬虫用不了多久就用不上了。我们使用API??接口来开发同一个网站。开放平台需要限制API接口的调用频率,以节省服务器资源,避免频繁的恶意调用。在大型互联网项目中,Web服务和网络爬虫的访问流量可以达到5:1,甚至更高,一些系统有时会因为爬虫流量过大而资源耗尽,服务不可用。解决策略大致有两个方面:一是限制流量,限制访问频率;另一种是将爬虫请求转发到固定的地方。爬虫限流登录/会话限制下载限流访问频率ip限制,黑白名单如果要区分访问是否是爬虫,可以简单的使用nginx分析ua处理UA介绍UserAgentUA简称,是用户代理。通常我们使用浏览器来访问一个网站,而在网站的日志中,我们的浏览器就是一种UA。禁止特定的UA访问。比如某网站A最近抄袭了公司主站B的内容,除了域名,内容和图片都是我们主站的内容。这种情况下,有两种可能:一种是:它利用爬虫抓取了公司主站B的内容,展示在自己的服务器上;另一种是:通过代理访问公司主站B,域名A是盗版的,骗取流量。无论如何,禁止继续这种行为。解决方法有两种:1)禁止IP2)禁止UA从nginx日志观察,访问者的代理IP经常变化,但是访问UA是固定的,所以可以禁止UA。Nginx不仅可以处理ua分离流量,还可以通过更强大的openresty完成更复杂的逻辑,实现一个流量网关和软防火墙。近期热点文章推荐:1.1,000+Java面试题及答案(2021最新版)2.别在满屏的if/else中,试试策略模式,真的很好吃!!3.操!Java中xx≠null的新语法是什么?4、SpringBoot2.5发布,深色模式太炸了!5.《Java开发手册(嵩山版)》最新发布,赶快下载吧!感觉不错,别忘了点赞+转发!
