前言
随着微服务的流行,单体应用被拆分成一个个独立的微进程,可能一个简单的请求,需要多个微服务共同处理,这样其实是增加了出错的概率,所以如何保证在单个微服务出现问题的时候,对整个系统的负面影响降到最低,这就需要用到我们今天要介绍的线程隔离。
线程模型
在介绍线程隔离之前,我们先了解一下主流容器,框架的线程模型,因为微服务是一个个独立的进程,之间的调用其实就是走网络io,网络io的处理容器如tomcat,通信框架如netty,微服务框架如dubbo,都很好的帮我们处理了底层的网络io流,让我们可以更加的关注于业务处理;
Netty
Netty是基于java nio的高性能通信框架,使用了主从多线程模型,借鉴Netty系列之 Netty线程模型的一张图片如下所示:
主线程负责认证,连接,成功之后交由从线程负责连接的读写操作,大致如下代码:
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup);
主线程是一个单线程,从线程是一个默认为cpu*2个数的线程池,可以在我们的业务handler中做一个简单测试:
public void channelRead(ChannelHandlerContext ctx, Object msg) {
System.out.println("thread name=" + Thread.currentThread().getName() + " server receive msg=" + msg);
}
服务端在读取数据的时候打印一下当前的线程:
threadname=nioEventLoopGroup-3-1server receive msg="..."
可以发现这里使用的线程其实和处理io线程是同一个;
Dubbo
Dubbo的底层通信框架其实使用的就是Netty,但是Dubbo并没有直接使用Netty的io线程来处理业务,可以简单在生产者端输出当前线程名称:
threadname=DubboServerHandler-192.168.1.115:20880-thread-2,...
可以发现业务逻辑使用并不是nioEventLoopGroup线程,这是因为Dubbo有自己的线程模型,