走过路过不要错过

点击蓝字关注我们

    RabbitMQ是目前非常热门的一款消息中间件,不管是互联网大厂还是中小企业都在大量使用。不管你是作为一名合格的开发同学还是运维同学,都有必要对RabbitMQ有所了解。但是本文并不是一篇rabbitmq入门文章,阅读需要有一定基础。

a4525975ba24b29b77250a78634bbd71.png

一、RabbitMQ简介

5096ea08dee3e8c6ed13f35bb2c890c5.png

以熟悉的电商场景为例,如果商品服务和订单服务是两个不同的微服务,在下单的过程中订单服务需要调用商品服务进行扣库存操作。按照传统的方式,下单过程要等到调用完毕之后才能返回下单成功,如果网络产生波动等原因使得商品服务扣库存延迟或者失败,会带来较差的用户体验,如果在高并发的场景下,这样的处理显然是不合适的,那怎么进行优化呢?这就需要消息队列登场了。

消息队列提供一个异步通信机制,消息的发送者不必一直等待到消息被成功处理才返回,而是立即返回。消息中间件负责处理网络通信,如果网络连接不可用,消息被暂存于队列当中,当网络畅通的时候在将消息转发给相应的应用程序或者服务,当然前提是这些服务订阅了该队列。如果在商品服务和订单服务之间使用消息中间件,既可以提高并发量,又降低服务之间的耦合度。

RabbitMQ就是这样一款我们苦苦追寻的消息队列。RabbitMQ是一个开源的消息代理的队列服务器,用来通过普通协议在完全不同的应用之间共享数据。

RabbitMQ除了像兔子一样跑的很快以外,还有这些特点:

开源、性能优秀,稳定性保障提供可靠性消息投递模式、返回模式与Spring AMQP完美整合,API丰富集群模式丰富,表达式配置,HA模式,镜像队列模型保证数据不丢失的前提做到高可靠性、可用性

MQ典型应用场景:

异步处理:把消息放入消息中间件中,等到需要的时候再去处理。流量削峰:例如秒杀活动,在短时间内访问量急剧增加,使用消息队列,当消息队列满了就拒绝响应,跳转到错误页面,这样就可以使得系统不会因为超负载而崩溃。日志处理;应用解耦:假设某个服务A需要给许多个服务(B、C、D)发送消息,当某个服务(例如B)不需要发送消息了,服务A需要改代码再次部署;当新加入一个服务(服务E)需要服务A的消息的时候,也需要改代码重新部署;另外服务A也要考虑其他服务挂掉,没有收到消息怎么办?要不要重新发送呢?是不是很麻烦,使用MQ发布订阅模式,服务A只生产消息发送到MQ,B、C、D从MQ中读取消息,需要A的消息就订阅,不需要了就取消订阅,服务A不再操心其他的事情,使用这种方式可以降低服务或者系统之间的耦合。
a4525975ba24b29b77250a78634bbd71.png

二、rabbitmq集群部署

5096ea08dee3e8c6ed13f35bb2c890c5.png

1、版本说明:

因为考虑到较早版本rabbitmq在k8s上的集群部署是使用autocluster插件去调用kubernetes apiserver来获取rabbitmq服务的endpoints,进而获取node节点信息,并自动加入集群,但是现在autocluster已不再更新了,并且只支持3.6.x版本,故而我们放弃了这种方式。

对于3.7.x或更新的版本,现在市场主流是使用 peer discovery subsystem来构建rabbitmq-cluster,官方github地址为:https://github.com/rabbitmq/rabbitmq-peer-discovery-k8s,本文版本我们选择rabbitmq3.8进行部署。

 2、部署方式:

在Kubernetes上搭建RabbitMQ有4种部署方法,本文选用hostname模式

IP模式Pod与server的DNSStatefulset 与 Headless Servicehostname模式

3、其他说明

后端存储使用ceph,大家也可根据需要对接使用nfsk8s: v1.18.3docker: 19.03.12centos: 7.7

4、rabbitmq集群部署-statefulset和持久化存储

---#创建命名空间test2apiVersion: v1kind: Namespacemetadata:  name: test2---#RBAC 权限账号等apiVersion: v1kind: ServiceAccountmetadata:  name: rabbitmq  namespace: test2---kind: RoleapiVersion: rbac.authorization.k8s.io/v1beta1metadata:  name: endpoint-reader  namespace: test2rules:- apiGroups: [""]  resources: ["endpoints"]  verbs: ["get"]---kind: RoleBindingapiVersion: rbac.authorization.k8s.io/v1beta1metadata:  name: endpoint-reader  namespace: test2subjects:- kind: ServiceAccount  name: rabbitmqroleRef:  apiGroup: rbac.authorization.k8s.io  kind: Role  name: endpoint-reader--- #service创建kind: ServiceapiVersion: v1metadata:  name: rabbitmq-headless  namespace: test2spec:  clusterIP: None  publishNotReadyAddresses: true  ports:   - name: amqp     port: 5672   - name: http     port: 15672  selector:    app: rabbitmq---kind: ServiceapiVersion: v1metadata:  namespace: test2  name: rabbitmq-servicespec:  ports:  - name: http    protocol: TCP    port: 15672    targetPort: 15672  - name: amqp    protocol: TCP    port: 5672    targetPort: 5672  selector:    app: rabbitmq  type: NodePort--- #Configmap创建 rabbitmq配置文件apiVersion: v1kind: ConfigMapmetadata:  name: rabbitmq-config  namespace: test2data:  enabled_plugins: |      [rabbitmq_management,rabbitmq_peer_discovery_k8s].#启用插件rabbitmq_management和rabbitmq_peer_discovery_k8s  rabbitmq.conf: |      cluster_formation.peer_discovery_backend  = rabbit_peer_discovery_k8s      cluster_formation.k8s.host = kubernetes.default.svc.cluster.local      cluster_formation.k8s.address_type = hostname      cluster_formation.node_cleanup.interval = 30      cluster_formation.node_cleanup.only_log_warning = true      cluster_partition_handling = autoheal      queue_master_locator=min-masters      loopback_users.guest = false      default_user=admin      default_pass=admin      default_vhost=loan      # 必须设置service_name,否则Pod无法正常启动,这里设置后可以不设置statefulset下env中的K8S_SERVICE_NAME变量      # cluster_formation.k8s.service_name = rabbitmq-headless      # 必须设置hostname_suffix,否则节点不能成为集群      #  rabbitmq-headless.test2.svc.cluster.local中test2为namespace名称,按需修改      cluster_formation.k8s.hostname_suffix = .rabbitmq-headless.test2.svc.cluster.local      cluster_formation.randomized_startup_delay_range.min = 0      cluster_formation.randomized_startup_delay_range.max = 2      vm_memory_high_watermark.absolute = 1GB      disk_free_limit.absolute = 2GB--- #statefulset创建(podAntiAffinity反亲和性)apiVersion: apps/v1kind: StatefulSetmetadata:  name: rabbitmq  namespace: test2spec:  serviceName: rabbitmq-headless  selector:    matchLabels:      app: rabbitmq  #在apps/v1中,需与 .spec.template.metadata.label 相同,用于hostname传播访问pod  replicas: 3  #副本数3,  template:    metadata:      labels:        app: rabbitmq      annotations:        scheduler.alpha.kubernetes.io/affinity: >            {              "podAntiAffinity": {                "requiredDuringSchedulingIgnoredDuringExecution": [{                  "labelSelector": {                    "matchExpressions": [{                      "key": "app",                      "operator": "In",                      "values": ["rabbitmq"]                    }]                  },                  "topologyKey": "kubernetes.io/hostname"                }]              }            }    spec:      serviceAccountName: rabbitmq      terminationGracePeriodSeconds: 10      containers:      - name: rabbitmq        image: rabbitmq:3.8        resources:          limits:            cpu: 2            memory: 2Gi          requests:            cpu: 1            memory: 1Gi        volumeMounts:          - name: config-volume            mountPath: /etc/rabbitmq          - name: rabbitmq-data            mountPath: /var/lib/rabbitmq/mnesia        ports:          - name: http            protocol: TCP            containerPort: 15672          - name: amqp            protocol: TCP            containerPort: 5672        livenessProbe:          exec:            command: ["rabbitmqctl", "status"]          initialDelaySeconds: 60          periodSeconds: 60          timeoutSeconds: 5        readinessProbe:          exec:            command: ["rabbitmqctl", "status"]          initialDelaySeconds: 20          periodSeconds: 60          timeoutSeconds: 5        imagePullPolicy: Always        env:          - name: HOSTNAME            valueFrom:              fieldRef:                fieldPath: metadata.name          - name: MY_POD_NAMESPACE            valueFrom:              fieldRef:                fieldPath: metadata.namespace          - name: RABBITMQ_USE_LONGNAME            value: "true"          - name: K8S_SERVICE_NAME            value: "rabbitmq-headless"          - name: RABBITMQ_NODENAME            value: rabbit@$(HOSTNAME).$(K8S_SERVICE_NAME).$(MY_POD_NAMESPACE).svc.cluster.local          - name: RABBITMQ_ERLANG_COOKIE            value: "sccookie"      volumes:        - name: config-volume          configMap:            name: rabbitmq-config            items:            - key: rabbitmq.conf              path: rabbitmq.conf            - key: enabled_plugins              path: enabled_plugins  volumeClaimTemplates:  - metadata:      name: rabbitmq-data    spec:      storageClassName: "xsky-rbd"      accessModes: [ "ReadWriteOnce" ]      resources:        requests:          storage: 5Gi
[root@worker01 rmq]# kubectl apply -f rabbitmq-cluster.yamlnamespace/test1 unchangedserviceaccount/rabbitmq unchangedrole.rbac.authorization.k8s.io/endpoint-reader unchangedrolebinding.rbac.authorization.k8s.io/endpoint-reader unchangedservice/rabbitmq-headless unchangedservice/rabbitmq-service unchangedconfigmap/rabbitmq-config unchangedstatefulset.apps/rabbitmq configured

设置的web登录默认账号密码和vhost如下

default_user=admindefault_pass=admindefault_vhost=test

e300a3cf65956ed917775a284915fb87.png

0f29c544a6386c460586430940771ba5.png

通过暴露的nodeport端口访问验证:http://node-ip:nodeport,如下

6ba08f730cbfc94333da04ea3799b373.png

当然我们也可以创建ingress入口

apiVersion: extensions/v1beta1kind: Ingressmetadata:name: rabbitmqnamespace: test1spec:rules:- host: rabbitmq.domain.testhttp:paths:- backend:serviceName: rabbitmq-serviceservicePort: 15672

2d3b771440644b9755d9e755e25acfc0.png

9264b093140aba040f3ca35f0004f42b.png

七月

[先秦] 诗经

七月流火,九月授衣。

一之日觱发,二之日栗烈。

无衣无褐,何以卒岁?

三之日于耜,四之日举趾。

同我妇子,馌彼南亩,田畯至喜。

七月流火,九月授衣。

春日载阳,有鸣仓庚。

女执懿筐,遵彼微行,爰求柔桑。

春日迟迟,采蘩祁祁。

女心伤悲,殆及公子同归。

七月流火,八月萑苇。

蚕月条桑,取彼斧斨。

以伐远扬,猗彼女桑。

七月鸣鵙,八月载绩。

载玄载黄,我朱孔阳,为公子裳。

四月秀葽,五月鸣蜩。

八月其获,十月陨萚。

一之日于貉,取彼狐狸,为公子裘。

二之日其同,载缵武功,言私其豵,献豣于公。

五月斯螽动股,六月莎鸡振羽。

七月在野,八月在宇,九月在户,十月蟋蟀入我床下。

穹窒熏鼠,塞向墐户。

嗟我妇子,曰为改岁,入此室处。

六月食郁及薁,七月亨葵及菽。

八月剥枣,十月获稻。

为此春酒,以介眉寿。

七月食瓜,八月断壶,九月叔苴,采荼薪樗,食我农夫。

九月筑场圃,十月纳禾稼。

黍稷重穋,禾麻菽麦。

嗟我农夫,我稼既同,上入执宫功。

昼尔于茅,宵尔索绹。

亟其乘屋,其始播百谷。

二之日凿冰冲冲,三之日纳于凌阴。

四之日其蚤,献羔祭韭。

九月肃霜,十月涤场。

朋酒斯飨,曰杀羔羊,跻彼公堂,称彼兕觥,万寿无疆!

33de71b0cfa8613ab643935641c5cace.gif 659b3c38244e5d351363585626e1afd1.gif d676edd50f1b02fc5def6d414cfc8970.gif 

END

1ad3b253b1d77c6ee1affe51d7ac17fc.png

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐