Actor模型
在Actor模型中主角是actor,类似一种worker。
Actor彼此之间直接发送消息,不需要经过什么中介,消息是异步发送和处理的.
组成
-
state
指 actor 本身的属性信息
state只能被actor自己操作,不能被其他actor共享和操作,有效的避免加锁和数据竞争. -
behavior
actor 处理逻辑,通过行为来操作自身state -
Mailbox
存储消息的fifo队列,actor与actor发送消息,消息只能发送到邮箱,等待拥有邮箱的actor 去处理
这个过程是异步的。简单来说,有时间才处理,等我把前面任务先完成
akka
示例:
//累加器
static class CounterActor extends UntypedActor {
private int counter = 0;
@Override
public void onReceive(Object message){
//如果接收到的消息是数字类型,执行累加操作,
//否则打印counter的值
if (message instanceof Number) {
counter += ((Number) message).intValue();
} else {
System.out.println(counter);
}
}
}
public static void main(String[] args) throws InterruptedException {
//创建Actor系统
ActorSystem system = ActorSystem.create("HelloSystem");
//4个线程生产消息
ExecutorService es = Executors.newFixedThreadPool(4);
//创建CounterActor
ActorRef counterActor = system.actorOf(Props.create(CounterActor.class));
//生产4*100000个消息
for (int i=0; i<4; i++) {
es.execute(()->{
for (int j=0; j<100000; j++) {
counterActor.tell(1, ActorRef.noSender());
}
});
}
//关闭线程池
es.shutdown();
//等待CounterActor处理完所有消息
Thread.sleep(1000);
//打印结果
counterActor.tell("", ActorRef.noSender());
//关闭Actor系统
system.shutdown();
}
reactor模型
- Reactor模型的核心是:Reactor+Handles。
- Reactor在一个单独的线程中运行,负责监听和分发事件,将接收到的io事件交给不同的Handle来处理响应。Handles是处理程序执行I/O事件的实际操作
- Reactor通过调度适当的Handles来处理io事件。
- 事件到达的底层实现是epoll 实现
- 同时接收多个服务请求,并且依次同步的处理它们的事件驱动程序
处理顺序
- 等待事件 (Reactor job)
- 分发 "Ready-to-Read" 事件给用户处理函数( Reactor job)
- 读取数据 (user handler job)
- 处理数据( user handler job)
目前常用的Netty、Redis、Memcached、Nignx都是基于Reactor模式实现的。
java 示例
java 8 提供了两个非常有用发布者, Flux 和 Mono, 用来产生异步序列。
- Flux 代表的是 0 to N 个响应式序列
- Mono代表的是0或者1个响应式序列。只会触发Subscriber的onComplete和onError方法,没有onNext
public abstract class Flux<T> implements Publisher<T>
public abstract class Mono<T> implements Publisher<T>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
</dependency>
proactor 模型
- 事件到达的底层实现是epoll 实现
- 异步接收和同时处理多个服务请求的事件驱动程序
处理顺序
- 等待事件 (Proactor job)
- 读取数据 (now Proactor job)
- 分发 "Read-Completed" 给用户处理函数 (Proactor job)
- 处理数据 (user handler job)
目前成熟的框架很少, 有c++ ace proactor
高并发低延迟的核心的
如何设计一个高吞吐量,低延时的系统?
通常认为没有充分利用多线程压榨多个CPU的能力是造成性能问题的原因,实际上缓存问题才是性能杀手
并发的实现
- 第一个方法是用锁来保证. 使用锁会导致内核态的切换,但总可以确保任何时刻总有一个进程会被执行(相比之下Lock-Free如果代码逻辑出现问题,有可能所有线程都处在自旋等待状态,无法前进),锁也增加了编程的难度
- 另一个方法是借助于CAS进行无锁编程。而借助于CAS的Lock-Free则始终是运行在用户态的(节省了效率,避免了无谓的上下文切换),相比于锁,它的编程难度更加大.