Skip to main content

异步通信1:JMS

异步通信1:JMS

同步的问题:

  • 紧耦合
  • 没有冗余,调用失败即失败,繁忙/断网等时候会出现问题(no request buffer)
  • 没有送达保障,不可靠,原因同上

结果:编程简单但是系统脆弱

异步通信模型:所有需要通信的终端都发消息给中间的消息服务器(Kafka等)处理

通信messaging: 松耦合

Controller 接受到请求,给mq发代表这个请求的消息(纯文本等形式描述),做Producer

Service 轮询mq的订阅topic, 不断拿出消息进行处理消费

client怎么知道处理完成?

  • Ajax 轮询刷新
  • WebSocket server推送
  • mq的一个新topic,client订阅这个topic, server处理完发一个消息给topic

request buffer: 削峰填谷

问题:

  • 返回值如何保存
  • 异常如何处理

一种解决方法: 把解决结果也组成一个消息发送到一个topic里面

JMS:java message service, 规定语言层级的API

  • 异步
  • 可靠(能保证有且仅有的语义)

header properties body

Body:

Text, Map, Bytes, Object, Stream 和基类Message

上层实现:

  • 例如可以让Tomcat起一个JMS,不需要引入外部依赖

  • 也可以换成kafka之类

消息模型:

  • queue/p2p (peer to peer), 没有了服务器(或者说只剩下消息系统作为服务器), mq, senders, receivers
    • 单个消息只能被单个consumer消费
    • consumer消费所有的消息
  • pub/sub, send/recv中间层topic, send publish给topic, recv 订阅topic
    • 单个消息可以有多个consumer
    • 只有subscribe了某个topic之后才开始消费,支持过滤等

超卖?service处理,controller给client的消息只是“订单正在处理......”

作业的websocket实现: 一种方法websocket + sockjs

  • Spring后端 WebSocketMessageBrokerConfigurer(Stomp协议, 在TCP上简单包了一层) + SimpMessagingTemplate(底层是concurrenthashmap) + @MessageMapping, @SendTo

  • 前端: 使用了sockjs库和后端的withSockJS();相匹配, sockJS为浏览器提供了回退的选项, 先尝试http, 能连通再升级为websocket, 当不支持websocket的时候自动降级为http

  • 筛选客户端方式设计

client可以选择订阅广播的public topic或者给发送/接受一对一的user私人频道, 而请求一对一的私人频道就由Id来路由 通过@MessageMapping 和 convertAndSend 来控制发送对象, 通过WebSocketMessageBrokerConfigurer来自动维护topic群组的概念, 应用程序只需要向某个topic发送或者接受消息即可

    simpMessagingTemplate.convertAndSend("/topic/heartbeats", new WebSocketDTO.Message("heartbeat", 0L, -1L, now(), WebSocketDTO.Status.MESSAGE));

hw3问答题:

Q: 为什么ConcurrentMap是线程安全的 A: 因为它底层使用数组 + 链表/红黑树的形式. 在数组的单个节点上有一把可重入锁, 需要获取锁才能对链表/红黑树之中的元素进行操作, 因而是线程安全的

Q: 为什么要选择并发安全的集合类型 A: 因为常见的集合结构例如HashMap, ArrayList是并发不安全的, 在并发请求后端websocket服务时, 会导致请求的session不能正常得到维护, 发生错误或资源泄漏等

Q: 如果数据库系统在事务执行过程中不断地将事务操作的结果执行落盘操作,会带来什么潜在问题?可以如何处理? 脏读, 不可重复读等事务隔离性问题, 回滚等事务原子性问题; 可以用MVCC和锁(取决于事务隔离级别)来控制并发事务相互的可见性, 从而控制执行中事务对其他事务的落盘数据的可见性; 可以在落盘之前先写undo log来让落盘数据允许回滚.

Q: 如果数据库系统在事务执行提交后再将事务操作的结果执行落盘操作,会带来什么潜在问题?可以如何处理? 提交后落盘前断电等带来的一致性问题, 并发事务先"看到"提交再看到实际数据的一致性问题等, 大事务数据的效率问题等. 一致性问题可以通过MVCC和加锁来解决, 断电等缓存一致性问题可以通过在落盘之前先写redo log来进行处理, 这样即使出错也可以重做; 效率问题也可以通过允许部分数据异步落盘, 通过写redo log的方式保证一致性的方法解决