系统间通信的需求 -> 消息队列; 最早的中间件之一; 官方文档都很不错;

rabbitmq

我们这边用的是私有化部署的rabbitmq
文档指路:https://www.rabbitmq.com/getstarted.html

比较传统的消息中间件:

  • 处理和响应消息的方式是destructive的,一旦消息被成功处理,就会从broker上删除

rabbitmq服务器上查看

1
2
3
whereis rabbitmq
rabbitmq-plugins list
rabbitmqctl list_users

web 管理端

  • admin-Users 配置对应的user - Can access virtual hosts

nacos 对rabbitmq的配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
rabbitmq:
host: ${rabbitmq.host}
port: ${rabbitmq.port}
username: ${rabbitmq.username}
password: ${rabbitmq.password}
virtual-host: homework
listener:
direct:
acknowledge-mode: auto
retry:
enabled: true
max-attempts: 5
initial-interval: 2000
simple:
retry:
enabled: true
max-attempts: 4
initial-interval: 2000
prefetch: 1
acknowledge-mode: auto

自己的消息中心也集成到了内部管理端

集成RabbitMQ统一发送接收方案

  • java团队
    • 利用rabbitmq提供相关离线操作,及高并发削峰
    • skywalking - skywalking/agent/config/apm-trace-ignore-plugin.config + trace.ignore_path=RabbitMQ/**

Kafka

Java团队也用这个

  • Partition(分区)

    rocketmq

    之前被推过一个内部的微服务开发框架,用的是rocketMQ
    文档指路:http://rocketmq.apache.org/docs/quick-start/
  • 每个Topic包含多个队列,通过多个队列来实现多实例并行生产和消费
  • Subscriber-Consumer Group

基于异步消息提升性能

wiki指路

https://zh.wikipedia.org/wiki/%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97

名词解释-设计/演进

主题

队列模型

  • Queue(FIFO-Linear List,具体实现-链表or数组)

  • Producer-Consumer

    发布-订阅模型(publish-subscribe pattern)

  • Publisher发布者(消息的发送方)-Subscriber订阅者(消息的接收方)

  • Topic(服务端存放消息的容器)

  • 发布者将消息发送到主题中,订阅者在接收消息之前需要先“订阅主题”

  • 订阅既是一个动作,也是主题在消费时的一个逻辑副本

  • 每份订阅中,订阅者都可以接收到主题的所有消息

  • RabbitMQ用的是队列模型,但是可以实现发布订阅功能(解决了多个消费者的问题-Exchange模块)

  • RocketMQ和Kafka用是发布-订阅模型(业务模型比较像,但是具体实现不一样)

使用锁保护共享数据,协调异步线程

Pulsar

  • 最早yahoo开发

  • 存储计算分离设计(设计思路)

    pulsar - node - 坑一个

  • https://pulsar.apache.org/docs/en/client-libraries-cpp/#install-rpm

  • https://pulsar.apache.org/docs/en/client-libraries-node/

  • 安装pulsar-client之前需要安装C++的client library

    Errors

    但是呢,我们现在安装$ npm install pulsar-client的时候,报错

    1
    install response status 404 Not Found on https://pulsar.apache.org/docs/en/client-libraries-cpp/libpulsar-v1.6.2-node-v72-linux-x64.tar.gz

    node-pre-gyp下载二进制文件的路径,优先来源于对应模块的镜像地址,该镜像地址通过配置’npm_config_’ + 模块名 + ‘_binary_host_mirror’来实现自定义;在没有定义镜像地址的情况下,读取模块package.json中的binary属性信息。

这个时候如果有libpulsar-v1.6.2-node-v72-linux-x64.tar.gz这个文件,就可以配置个host,打到自己服务器,提供这个资源,如果没有,就看看之前安装过的,图快的话node_modules弄过来;

1
2
3
4
5
6
7
8
9
10
# node_modules如果物理机上有,压缩下,拿过来就行
tar -czvf node_modules.tar.gz node_modules
tar -xvf node_modules.tar.gz
中间的周转是用cos进行存储的,wget拿
# 如果在image里面,可以
docker images # 拿到id
docker run -it --entrypoint sh "id"
yum install lrzsz
sz node_modules.tar.gz
# 也同样用cos进行存储的,wget拿

这个报错是因为找不到libpulsar.so.2.8.1文件,所以按这个https://pulsar.apache.org/docs/en/client-libraries-cpp/#install-rpm安装下对应版本的即可;
find -name libpulsar.so.2.8.1
看看能不能找到,找到了位置不对的话,ln -s /path/to/lib**.so /usr/lib ,sudo ldconfig
Note If you get the error that libpulsar.so: cannot open shared object file: No such file or directory when starting Pulsar client, you may need to run ldconfig first.
find

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Error: libpulsar.so.2.8.1: cannot open shared object file: No such file or directory
26|htmlToSvg | at Object.Module._extensions..node (internal/modules/cjs/loader.js:1208:18)
26|htmlToSvg | at Module.load (internal/modules/cjs/loader.js:1002:32)
26|htmlToSvg | at Function.Module._load (internal/modules/cjs/loader.js:901:14)
26|htmlToSvg | at Module.require (internal/modules/cjs/loader.js:1044:19)
26|htmlToSvg | at Module.Hook._require.Module.require (/usr/local/lib/node_modules/pm2/node_modules/require-in-the-middle/index.js:80:39)
26|htmlToSvg | at require (internal/modules/cjs/helpers.js:77:18)
26|htmlToSvg | at bindings (/neworiental/nodejs/seal_svg_server-1/node_modules/bindings/bindings.js:112:48)
26|htmlToSvg | at Object.<anonymous> (/neworiental/nodejs/seal_svg_server-1/node_modules/pulsar-client/index.js:20:42)
26|htmlToSvg | at Module._compile (internal/modules/cjs/loader.js:1158:30)
26|htmlToSvg | at Module._compile (/neworiental/nodejs/seal_svg_server-1/node_modules/pirates/lib/index.js:99:24)
PM2 | App name:htmlToSvg id:26 disconnected
PM2 | App [htmlToSvg:26] exited with code [0] via signal [SIGINT]
PM2 | App [htmlToSvg:26] starting in -cluster mode-
PM2 | App [htmlToSvg:26] online

上面的是想办法弄编好的,如果实在没有,就走node-gyp去编了,根据报错一步步解决即可

根本解决ERROR,把centos的环境处理好

1
2
3
4
5
6
7
8
9
10
11
12
13
14
1.就node-pre-gyp不行的话,因为找不到已经预编译好的符合要求的版本嘛,就走本地编译
2.node-gyp本地编译的时候,mac注意配置下PULSAR_CPP_DIR 即可
- export PULSAR_CPP_DIR="/usr/local/Cellar/libpulsar/2.9.1_1"
- brew安装的,也是注意下环境变量的配置,保证位置找对了
export CPLUS_INCLUDE_PATH="$(brew --prefix)/include"\nexport LIBRARY_PATH="$(brew --prefix)/lib"
export CPLUS_INCLUDE_PATH="$CPLUS_INCLUDE_PATH:$(brew --prefix)/include"
export LIBRARY_PATH="$LIBRARY_PATH:$(brew --prefix)/lib"
3.node-gyp本地编译的时候,linux服务器注意准备好文档中写的requirement,然后就可以编译了,看报什么错,就解决什么错就行 (https://pulsar.apache.org/docs/zh-CN/next/client-libraries-cpp/#%E5%AE%89%E8%A3%85-rpm - 这个里面提示了nodejs需要预先安装什么)
注意点1:yum -y install gcc automake autoconf libtool make
yum -y install gcc-c++
注意点2:
client-devel
client
这两个都要安装,rpm -ivh apache-pulsar-client*.rpm 一个一个的,运行两遍就行;确保都安装了;
  • 如果确定了要的预编译包,也可以自己编译好了,然后打gz的包,发布到我们自己的文档对象存储上,然后在pulsar-client的安装脚本里面,把地址改下就行

    consumer

    There are two main ways of using the consumer:

  • Blocking style: synchronously calling receive(msg).

  • Non-blocking (event based) style: using a message listener.

  • 但是这部分node的封装有点问题,listener模式下,如果把receiverQueueSize设置为0,会报错,提示应该更明确的,让非阻塞模式下就不要使用这个了;

  • receiverQueueSize 设置 consumer 接收队列的大小,即在应用程序调用 receive 之前允许堆积的消息数。 A value higher than the default of 1000 could increase consumer throughput, though at the expense of more memory utilization.