精华内容
下载资源
问答
  • 事件驱动和消息驱动

    千次阅读 2020-04-17 10:26:15
    事件驱动和消息驱动 消息驱动和事件驱动很类似,都是先有一个事件,然后产生一个相应的消息,再把消息放入消息队列,由需要的项目获取。他们的区别是消息是谁产生的 消息驱动:鼠标管自己点击不需要和系统有过多的...

    事件驱动和消息驱动

    消息驱动和事件驱动很类似,都是先有一个事件,然后产生一个相应的消息,再把消息放入消息队列,由需要的项目获取。他们的区别是消息是谁产生的

    消息驱动:鼠标管自己点击不需要和系统有过多的交互,消息由系统(第三方)循环检测,来捕获并放入消息队列。消息对于点击事件来说是被动产生的,高内聚。

    事件驱动:鼠标点击产生点击事件后要向系统发送消息 “我点击了” 的消息,消息是主动产生的。再发送到消息队列中。事件往往会将事件源包装起来。


    事件驱动往往和轮询机制相关,它们通常被统称为 event loop。重点在于并不会给每一个事件分配一个轮询来探知其变化,而是设置一个中央轮询中心,用这个轮询中心去轮询每个注册的对象。轮询中心一旦检测到了注册其中的对象有事件发生,那么就通知对此事件感兴趣的对象。而对此事件感兴趣的对象此时会调用的方法被称为回调函数。


    有时也把事件驱动按照实现方式的不同进行区分(个人并不认为很准确,但是很多人都这么说):

    • 轮询方式
      线程不断轮询访问相关事件发生源有没有发生事件,有发生事件就调用事件处理逻辑。
    • 事件驱动方式
      事件发生时主线程把事件放入事件队列,在另外线程不断循环消费事件列表中的事件,调用事件对应的处理逻辑处理事件。事件驱动方式也被称为消息通知方式,其实是设计模式中观察者模式的思路。

    事件驱动模型可以用下图表示(来源于《Software Architecture Patterns》):
    在这里插入图片描述
    主要包括 4 个基本组件:

    • 事件队列(event queue):接收事件的入口,存储待处理事件
    • 分发器(event mediator):将不同的事件分发到不同的业务逻辑单元
    • 事件通道(event channel):分发器与处理器之间的联系渠道
    • 事件处理器(event processor):实现业务逻辑,处理完成后会发出事件,触发下一步操作

    比如说在 Java 的 Socket NIO 模型中,SocketChannel 总是将自身注册为对可读、可写事件感兴趣,ServerSocketChannel 却往往将自己注册为对有一个新的 TCP 连接请求感兴趣。不同的类型的对象可以以不同的兴趣注册到同一个分发器中,分发器既需要能够辨别发生了的不同事件,又需要能够将不同的事件分派给不同的事件通道。因为分发器具备这种为有着不同兴趣的不同对象服务的能力,所以分发器仅仅需要占一个线程。

    另一个问题是事件处理器如何知道事件发生了?事件处理器就像人一样,人通过每天时不时地看看报纸、看看手机 APP,”时不时地看“这个动作时由人主动发出的,这是最关键的。处理器需要一个其独享的线程,在这个线程中进行检查是否发生了新的事件,这个线程在没有被通知时是阻塞的,一旦 Event Channel 传来了新的事件,事件处理器就不再阻塞。

    所以,有一个单线程不阻塞地进行轮询事件队列,一旦发现事件发生了,就通过事件分发器,将包装好的事件通过事件通道传给事件处理器。而每个事件处理器也单独占据一个线程,如果此时没有事件传递过来,其就会阻塞,直到事件传递过来。

    事件队列和事件处理器除了在各自的线程模型是否阻塞上有所区别以外,在实现者上也有所区别。通常事件队列包括分发器、事件通道都是由类库替我们完成的,而事件处理器的逻辑则需要更偏向业务的程序员完成。

    展开全文
  • 微服务架构之消息驱动
  • 基于消息驱动框架的软件开发成为大数据应用系统的重要模式之一。基于面向实体、消息驱动的开发架构,设计并实现了该架构中的消息管理模块。定义了消息基本格式,制定了消息管理规范,并且具体实现了其功能,通过一个...
  • 消息驱动与事件驱动比较

    万次阅读 2017-07-24 14:35:52
    简单记录自己对于 消息驱动 和 事件驱动的理解。关于这二者的具体区别,于实现上来说,二者都是 注册绑定,然后交付执行。消息驱动模型在注册的时候仅仅注册一个回调函数作为处理函数。 而事件驱动模型则需要注册...

    简单记录自己对于 消息驱动 和 事件驱动的理解。

    关于这二者的具体区别,于实现上来说,二者都是 注册绑定,然后交付执行。

    消息驱动模型在注册的时候仅仅注册一个回调函数作为处理函数。
    而事件驱动模型则需要注册多个函数作为处理函数。

    消息驱动模型由于处理函数只有一个的缘故,
    故需要在回调函数中使用switch等手段,
    对消息进行派发并具体处理。
    而事件驱动模型则需要在各个回调函数中处理各自的事物。

    所以从框架角度说,
    消息驱动模型的复用性高于事件驱动模型,
    或者说事件驱动模型一般用于处理某个特定的问题。

    而造成这种情形的原因是,
    消息驱动模型不需要知道具体的消息含义,
    而事件驱动模型则需要知道具体的事件含义,
    否则无法通过回调函数处理。

    细节说明:
    事件驱动机制跟消息驱动机制相比


    9102年,重新审视 事件驱动 与 消息驱动。

    事件
    驱动
    消息

    需要理解的是这三个词的含义。

    首先聊一下何为驱动,
    驱动具象化理解就像开车一样,点一脚油就动一下。

    抽象的代码表示驱动一词

    
    func driver() {
      while(condition) {
        watch(worker);
      }
    }
    

    何为事件,字面意思,
    意思是比较重大、对一定的人群会产生一定影响的事情。

    简单用代码描述如下

    // 用户定义
    register(read_fn, flag);
    
    // 用户定义
    func read_fn(bytes []) {
      dosomething();
    }
    
    // 框架提供
    func register(do, flag) {
      fn[flag] = do;
    }
    
    // 框架提供
    func watch(worker) {
      // 例子,此处也可能是 epoll poll select 等
      // 或者是经过包装的高级模型
      which= WaitForMultipleObjecct();
      fn[ctx[which].flag](ctx[which].bytes);
    }
    

    何为消息,同字面意思

    // 用户定义
    func worker(msg) {
       switch(msg) {
       case 0: break;
       case 1: break;
       default: break;
       //....
       }
    }
    
    // 框架提供
    func watch(worker) {
      // 阻塞队列常用于实现消息队列和事件队列
      msg = GetHeadFromBlockQueue();
      worker(msg);
    }
    
    

    上述就是常见框架的缩影,具体到日常框架中,再对比一下使用方式,如下。

    例如 libuv 或libevent的使用示例

    struct event* ev_listen = event_new(xxx);
    
    event_add(ev_listen, NULL);
    bufferevent_setcb(bev, socket_read_cb, NULL, event_cb, arg);
    
    // 事件循环
    event_base_dispatch(base);
    

    再例如

    // 省略注册窗口类时对于消息分发函数注册等代码。
    // ....
    
    // 消息泵
    BOOL ret;
    while((ret=GetMessage(&msg,hWnd,0,0))!=0) {
      if(ret==-1) {
        //handle the error and possibly exit
        return -1;
      }
      else {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
      }
    }
    

    实现上二者差异并不算大,例如消息驱动中,可以向消息队列中压入消息唤醒,而事件驱动中也可以从外部写fd 唤醒。

    事件的作用范围为系统提供的事件种类。
    消息的作用范围为系统提供的消息种类。

    可以实现自定义消息,却无法自定义事件。
    当然消息本身可以看做是一种特殊的事件。

    二者应用领域有一定交集,各有所长。

    事件驱动模型主要应用于 网络框架,有着固定的几大基础事件。
    [被]连接,[被]断开,收,发。

    消息驱动模型常见于 窗口框架。需要应付种类繁多的消息。
    WM_xxxxx

    展开全文
  • 十一、消息驱动Stream

    万次阅读 2020-04-19 15:57:11
    SpringCloud消息驱动框架Stream的使用

    一、Stream 介绍

    Stream 简介

    Spring Cloud Stream是一个构建消息驱动微服务的框架。屏蔽底层消息中间件的差异,降低切换成本,统一消息的编程模型。

    应用程序通过inputs或者outputs来与Streambinder对象交互。通过我们配置来binding(绑定),而Streambinder对象负责与消息中间件交互。所以,我们只需搞清楚如何与Stream交互就可以方便使用消息驱动的方法。

    通过使用Spring Integration来连接消息代理中间件以实现事件消息驱动,Stream为一些供应商的消息中间件产品提供了个性化的自动化配置,引用了发布-订阅、消费组、分组三个概念。目前仅支持RabbitMqKafka

    Stream中的消息通信方式遵循了发布-订阅模式,根据Topic主题进行广播。

    为什么使用 Stream ?

    如果用到了RabbitMQKafka,由于这两个消息中间件的架构上的不同,像RabbitMQexchange, kafka有TopicPartitions分区,这些中间件的差异性导致我们实际项目开发给我们造成了一定的困扰,我们如果用了两个消息队列的其中一种,后面的业务需求,我想往另外一种消息队列进行迁移,这时候无疑就是一个灾难性的,一大堆东西都要重新推倒重新做,因为它跟我们的系统耦合了,这时候Stream给我们提供了一种解耦合的方式。

    统一底层差异组件 Binder

    在没有绑定器这个概念下的情况下,SpringBoot应用要直接与消息中间件进行信息交互的时候,由于各消息中间件构建的初衷不同,它们的实现细节上会有较大的差异,通过定义绑定器作为中间层,完美的实现了应用程序与消息中间件细节之间的隔离。Stream对消息中间件的进一步封装,可以做到代码层面对中间件的无感知,甚至于动态的切换中间件(RabbitMQ切换Kafka),使得微服务开发的高度解耦,服务可以关注更多自己的业务流程。通过定义绑定器Binder作为中间层,实现了应用程序与消息中间件细节之间的隔离。
    SpringCloudStream处理架构

    组成说明
    inputs消费者
    outputs生产者
    Middleware中间件,目前只支持RabbitMQ和Kafka
    BinderBinder是应用与消息中间件之间的封装,目前实行了Kafka和RabbitMQ的Binder,通过Binder可以很方便的连接中间件,可以动态的改变消息类型(对应于Kalka的topic,RabbitMQ的exchange),这些都可以通过配置文件来实现

    二、Stream 的使用

    2.1 Stream 标准流程

    Stream标准流程

    • Binder:方便的连接消息中间件,屏蔽差异
    • Channel:通道,是队列Queue的一种抽象,在消息通讯系统中就是实现存储和转发的媒介,通过Channel对队列进行配置
    • Source/Sink:发送端的流/接收端的流

    常用注解:

    注解说明
    @Input注解标识输入通道,通过该输入通道接收到的消息进入应用程序
    @Output注解标识输出通道,发布的消息将通过该通道离开应用程序
    @StreamL istener监听队列,用于消费者的队列的消息接收
    @EnableBinding指信道channel和exchange绑定在一起

    2.2 消息驱动之生产者

    ① 新建项目cloud-stream-rabbitmq-provider8801,添加stream依赖

    <!--stream rabbit -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
    </dependency>
    

    ② 配置文件中添加stream的配置

    spring:
      cloud:
        stream:
          binders: #在此处配置要绑定的rabbitmq的服务信息
           defaultRabbit: #表示定义的名称,用于binding整合
             type: rabbit #消息组件类型
             environment: #设置rabbitmq的相关环境配置
               spring:
                 rabbitmq:
                   host: 192.168.182.200
                   port: 5672
                   username: guest
                   password: guest
          bindings: #服务的整合处理
            output: #这个名字是一个通道的名称
              destination: studyExchange #表示要使用的Exchange名称定义
              content-type: application/json #设置消息类型,本次为json,本文要设置为“text/plain”
              binder: defaultRabbit #设置要绑定的消息服务的具体设置
    

    ③ 新建发送消息接口和实现类

    public interface IMessageProvider {
        public String send();
    }
    
    import com.hucheng.service.IMessageProvider;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.cloud.stream.annotation.EnableBinding;
    import org.springframework.cloud.stream.messaging.Source;
    import org.springframework.messaging.MessageChannel;
    import org.springframework.messaging.support.MessageBuilder;
    
    import java.util.UUID;
    
    @EnableBinding(Source.class) //定义消息的推送管道
    public class MessageProvider implements IMessageProvider {
    
        @Autowired
        private MessageChannel output; // 消息发送管道
    
        @Override
        public void send() {
            String uuid = UUID.randomUUID().toString();
            output.send(MessageBuilder.withPayload(uuid).build());
            System.out.println("*****UUID: "  +uuid+"*****");
        }
    }
    

    ④业务类代码

    @RestController
    public class SendMessageController {
        @Autowired
        private IMessageProvider provider;
    
        @GetMapping("/sendMessage")
        public void sendMessage() {
             provider.send();
        }
    }
    

    2.3 消息驱动之消费者

    ①新建项目cloud-stream-rabbitmq-consumer8802,添加stream依赖

    <!--stream rabbit -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
    </dependency>
    

    ②配置文件中添加stream的配置

    spring:
      cloud:
        stream:
          binders: #在此处配置要绑定的rabbitmq的服务信息
            defaultRabbit: #表示定义的名称,用于binding整合
              type: rabbit #消息组件类型
              environment: #设置rabbitmq的相关环境配置
                spring:
                  rabbitmq:
                    host: 192.168.182.200
                    port: 5672
                    username: guest
                    password: guest
          bindings: #服务的整合处理
            input: #这个名字是一个通道的名称
              destination: studyExchange #表示要使用的Exchange名称定义,同Provider名
              content-type: application/json #设置消息类型,本次为json,本文要设置为“text/plain”
              binder: defaultRabbit #设置要绑定的消息服务的具体设置
    

    ③业务类代码

    public interface IMessageProvider {
        public String send();
    }
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.cloud.stream.annotation.EnableBinding;
    import org.springframework.cloud.stream.annotation.StreamListener;
    import org.springframework.cloud.stream.messaging.Sink;
    import org.springframework.messaging.Message;
    import org.springframework.stereotype.Controller;
    
    /**
     * @author HuChan
     */
    @Controller
    @EnableBinding(Sink.class)
    public class ReceiveListenerController {
    
        @Value("server.port")
        private String port;
    
        @StreamListener(Sink.INPUT)//消费者
        public void input(Message<String> message){
            System.out.println("消费者1号, -----> 接受到的消息: " + message.getPayload() + " port: " + port);
        }
    }
    

    ④测试:

    向生产者发送请求:http://localhost:8801/sendMessage,消费者打印如下:
    在这里插入图片描述
    证明生产者向消费者发送消息成功!

    2.4 消息重复消费问题

    问题描述:

    此如在如下场景中,订单系统我们做集群部署,都会从RabbitMQ中获取订单信息,那如果一个订单同时被两个服务获取到,那么就会造成数据错误,我们得避免这种情况。这时我们就可以使用Stream中的消息分组来解决那如果一个订单同时被两个服务获取到,那么就会造成数据错误,我们得避免这种情况。这时我们就可以使用Stream中的消息分组来解决。
    在这里插入图片描述
    解决方案分组和持久化属性group

    原理:微服务应用放置于同一个group中,就能够保证消息只会被其中一个应用消费一次,不同的组是可以消费的,同一组内会发生竞争关系,只有其中一个可以消费。

    测试:
    在这里插入图片描述
    新建项目cloud-stream-rabbitmq-consumer8803,属性消费者一样,改成相同的group属性,向生产者发送请求:http://localhost:8801/sendMessage,消费者仅有一个控制台有打印。

    2.5 消息持久化

    当配置了group属性后,消息可以持久化,即使服务中途断开后重启仍然可以获得,而未指定分组的服务就会丢失断开期间发送到MQ的消息。

    消息持久化在消息队列中非常的重要

    展开全文
  • 官方定义SpringCloudStream是一个构建消息驱动微服务的框架。SpringCloudStreamApplication应用程序通过inputs或者outputs来与SpringCloudStream中binder交互,通过我们配置来binding,而SpringCloudStream的binder...
  • 消息驱动bean学习

    2010-01-03 19:59:36
    消息驱动bean学习消息驱动bean学习消息驱动bean学习消息驱动bean学习
  • 基于Linux的消息驱动Socket模型.pdf
  • EJB消息驱动bean Demo

    2016-06-10 10:33:27
    网上看的一个视频教程里的一个Demo,EJB消息驱动bean Demo。
  • 偏僻的 消息驱动的远程通信框架。
  • ejb 消息驱动Bean例子

    2010-05-18 10:52:07
    ejb 消息驱动Bean例子.有Queue,Topic
  • 消息驱动bean EJB 3.0

    2009-07-04 22:34:03
    消息驱动bean EJB3.0。sender
  • msg.h/msg.c/modules.c/modules.h 这是个文件实现了消息驱动系统模型。 整个package 是一个VC 项目,可以测试上面的模型。
  • 消息驱动和事件驱动的一点点区别

    千次阅读 2019-02-03 10:44:18
    **消息驱动,**A发送一个消息到消息队列,B收到该消息。A很明确这个消息是发给B的。通常是点对点模式。 **事件驱动,**A发出一个事件,B或者C收到这个事件,或者没人收到这个事件,A只会产生一个事件,不会关心谁会...

    消息驱动
    A发送一个消息到消息队列,B收到该消息。A很明确这个消息是发给B的。通常是点对点模式。

    事件驱动
    A发出一个事件,B或者C收到这个事件,或者没人收到这个事件,A只会产生一个事件,不会关心谁会处理这个事件 。通常是发布订阅模式。

    展开全文
  • 模仿MFC消息驱动机制

    千次阅读 2014-04-03 23:01:30
    欢迎向我索要模仿MFC消息驱动的实例源码,希望能与更多的人讨论。 邮箱:wjh_2010@163.com 在微软推出的MFC架构中,其消息驱动机制是其精髓,使用简单,效率高,而且思路清晰。如果能够模拟MFC的消息驱动机制,并...
  • 基于消息驱动的二级任务调度模型
  • Win32编程 消息驱动

    2012-01-09 14:32:55
    1、消息驱动 在介绍Windows消息驱动概念之前,我们首先来回顾面向过程的程序结构:main()程序有明显的开始、中间过程和结束点,程序是围绕这个过程编写好相关的子过程,再把这些子过程串联在一起。程序编好以后,该...
  • 事件驱动VS消息驱动

    千次阅读 2017-03-10 22:20:15
    消息:当鼠标被按下,产生了鼠标按下事件,windows侦测到这一事件的发生,随即发出鼠标被按下的消息消息队列中,这消息附带了一系列相关的事件信息,比如鼠标哪个键被按了,在哪个窗口被按的,按下点的坐标是多少...
  • 消息(队列) 事件响应(服务处理程序) 调度算法 进程/线程 非阻塞I/O 程序的执行可以看成对CPU,内存,IO资源一次占用 现代操作系统支持多任务,可以分时复用上述资源. 1. 为什么采用...
  • 消息驱动Bean(MDB) 是设计用来专门处理基于消息请求的组件。一个MDB类必须实现MessageListener 接口。当容器检测到bean守候的队列一条消息时,就调用onMessage()方法,将消息作为参数传入。MDB在OnMessage()中决定...
  • 消息驱动的Bean和无状态的会话Bean有什么区别?.pdf
  • 本说明详细介绍了消息驱动bean的配置方法,经过了实际的试验的!!!!!!!!!!!
  • EJB之消息驱动Bean的总结。ejb 消息驱动Bean j2ee jms java
  • 消息驱动之背景概述(十九)

    千次阅读 2018-06-04 17:00:51
    Spring Cloud里面提供的消息驱动就来源于这里,并且使用这些消息驱动模块来完成微服务之间的通讯。消息中间件当我们的消息生产者产生了消息之后,就把消息推送到RabbitMQ或Kafka这样的消息中间件上,消息消费者实现...
  • linux下多线程udp网络编程实现消息驱动多状态机流转,在之前“linux下多线程udp网络编程实现消息驱动多状态机流转3”的基础上增加了对状态机流转过程中,消息接受的定时控制,settimer。
  • Spring Cloud Stream(消息驱动

    万次阅读 2017-06-26 17:59:59
    Spring Cloud Stream 是一个用来为微服务应用构建消息驱动能力的框架。它可以基于Spring Boot 来创建独立的,可用于生产的Spring 应用程序。他通过使用Spring Integration来连接消息代理中间件以实现消息事件驱动。...
  • linux下多线程udp网络编程实现消息驱动状态机流转,同时可实现BUSY检测。
  • linux下多线程udp网络编程实现消息驱动状态机流转,增加第三方呼叫BUSY状态
  • JMS的中文教程(Java的消息驱动)很好的一本书,我的珍藏~
  • linux下多线程udp网络编程实现消息驱动多状态机流转,收发一体

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 274,902
精华内容 109,960
关键字:

消息驱动