狂神说Docker

Posted Filwaod

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了狂神说Docker相关的知识,希望对你有一定的参考价值。

文章目录


参考: https://blog.csdn.net/weixin_47024018/article/details/127916629

1.Docker概念与安装

1.1 概述

Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows操作系统的机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。

基础名词:

  1. 镜像(image):
    docker镜像就好比是一个模板,可以通过这个模板来创建容器服务,tomcat镜像 => run =>tomcat01容器(提供服务),通过这个镜像可以创建多个容器(最终服务运行或者项目运行就是在容器中的)。

  2. 容器(container):
    Docker利用容器技术可以独立运行一个或者一组应用,通过镜像来创建的,启动,停止、删除、基本命令
    目前就可以把这个容器理解为一个简易的linux系统

  3. 仓库(repository)
    仓库就是存放镜像的地方!仓库分为公有和私有仓库!
    Docker hub(默认是国外的) 阿里云…都有容器服务器(配置镜像加速!)

1.2 安装

# 卸载旧版本的docker
yum remove  docker \\
            docker-client \\
            docker-client-latest \\
            docker-common \\
            docker-latest \\
            docker-latest-logrotate \\
            docker-logrotate \\
            docker-engine

# 下载需要的安装包
yum install -y yum-utils

# 设置镜像的仓库
yum-config-manager \\
    --add-repo \\
    http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
    
# 更新yum软件包索引
yum makecache fast

# 安装Docker引擎
yum install docker-ce docker-ce-cli containerd.io 

# 启动Docker
systemctl start docker

# 测试helloWorld
docker run hello-world

# 查看一下下载的这个hello-word 镜像
dcoker images

1.3 卸载

# 卸载旧版本Docker
yum remove docker \\
                  docker-client \\
                  docker-client-latest \\
                  docker-common \\
                  docker-latest \\
                  docker-latest-logrotate \\
                  docker-logrotate \\
                  docker-engine

# 卸载引擎
yum remove docker-ce docker-ce-cli containerd.io

# 删除目录
rm -rf /var/lib/docker

1.4 Docker的执行镜像原理

1.5 Docker为什么比Vm快

1、Docker有着比虚拟机更少的抽象层。

2、Docker利用的是虚拟主机的内核,vm需要是Guest OS。

所以说,新建的容器的时候,docker不需要虚拟机一样重新加载一个操作系统内核,避免引导。虚拟机是加载Guest OS,分钟级别,而docker是利用虚拟机主机的操作系统,忽略了这个复杂的过程,秒级别。

1.6 Docker底层原理

Docker 是一个Client-Server结构的系统,Docker的守护进程运行在主机上,通过Socket从客户端访问!

DockerServer接收到Docker-Client的指令,就会执行这个命令!

2.Docker常用命令

2.1 帮助命令

docker version           # 显示docker信息
docker info              # 显示docker系统的信息, 宝库啊镜像和容器的数量
docker 命令 --help    	 # 万能命令

docker search mysql      # 搜索命令

[root@VM-4-8-centos ~]# docker search mysql
NAME                            DESCRIPTION                                      STARS     OFFICIAL   AUTOMATED
mysql                           MySQL is a widely used, open-source relation…   13974     [OK]       
mariadb                         MariaDB Server is a high performing open sou…   5327      [OK]       
percona                         Percona Server is a fork of the MySQL relati…   602       [OK]       
phpmyadmin                      phpMyAdmin - A web interface for MySQL and M…   768       [OK]       
circleci/mysql                  MySQL is a widely used, open-source relation…   29                   
bitnami/mysql                   Bitnami MySQL Docker Image                       80                   [OK]
bitnami/mysqld-exporter                                                          4                    
ubuntu/mysql                    MySQL open source fast, stable, multi-thread…   43                   
cimg/mysql                                                                       0                    
rapidfort/mysql                 RapidFort optimized, hardened image for MySQL    14                   
google/mysql                    MySQL server for Google Compute Engine           23                   [OK]
ibmcom/mysql-s390x              Docker image for mysql-s390x                     2                    
rapidfort/mysql8-ib             RapidFort optimized, hardened image for MySQ…   0                    
hashicorp/mysql-portworx-demo                                                    0                    
rapidfort/mysql-official        RapidFort optimized, hardened image for MySQ…   0                    
newrelic/mysql-plugin           New Relic Plugin for monitoring MySQL databa…   1                    [OK]
databack/mysql-backup           Back up mysql databases to... anywhere!          82                   
linuxserver/mysql               A Mysql container, brought to you by LinuxSe…   38                   
mirantis/mysql                                                                   0                    
docksal/mysql                   MySQL service images for Docksal - https://d…   0                    
vitess/mysqlctld                vitess/mysqlctld                                 1                    [OK]
linuxserver/mysql-workbench                                                      48                   
bitnamicharts/mysql                                                              0                    
eclipse/mysql                   Mysql 5.7, curl, rsync                           0                    [OK]
drud/mysql                                                                       0       

# 可选项,通过搜索赖过滤
--filter=STARS=3000    # 搜索出来的镜像就是STARS大于3000的              

2.2 镜像命令

docker imgaes 查看所有镜像

[root@VM-4-8-centos ~]# docker images
REPOSITORY           TAG       IMAGE ID       CREATED         SIZE
hello-world          latest    feb5d9fea6a5   18 months ago   13.3kB
canal/canal-server   v1.1.5    0c7f1d62a7d8   23 months ago   874MB
mysql                5.7.25    98455b9624a9   4 years ago     372MB

# 解释
REPOSITORY 镜像的仓库源
TAG		   镜像的标签
IMAGE ID   镜像的id
CREATED	   镜像的创建时间
SIZE       镜像的大小

# 可选项
-a, --all		# 列出所有镜像
-f, --filter    # 过滤
-q, --quiet     # 只显示镜像的id

docker pull 拉取镜像

 # 指定版本拉取镜像 docker pull 镜像名[:tag]  不加标签,默认拉取最新版
[root@VM-4-8-centos ~]# docker pull mysql:5.7
5.7: Pulling from library/mysql
2ec521688c56: Pull complete 
f911f9b90db6: Pull complete 
38eb4fe7ed26: Pull complete 
01f772a6b25f: Pull complete 
499456357ebf: Pull complete 
274f3ad0dcec: Pull complete 
3e6a5b12e1de: Pull complete 
de0c5c82dbbc: Pull complete 
c9bd281f4600: Pull complete 
3289c4277a83: Pull complete 
8b66f10a11fa: Pull complete 
Digest: sha256:1780318bdabc0edd36907bf91b47632eb912e8ea91258eca3590f8aca6f54836
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7

docker rmi 删除镜像

# docker 执行删除镜像,根据id 或者名称
docker rmi id

# rmi删除不了正在使用的镜像,加-f强制删除
docker rmi -f id

# docker 执行批量删除镜像 通过递归方式进行删除
docker rmi -f $(docker images -aq)

2.3 容器命令

先拉取一个镜像

docker pull centos

docker run [可选参数] image 新建容器并启动

docker run [可选参数] image

# 参数说明
--name="Name"   容器名称  tomcat01  tomcat02 ,用来区分容器
-d  			后端方式运行
-it  			使用交互方式运行,进入容器查看内容
-小p  			指定容器的端口  -p 8080:8080
	-p ip:主机端口:容器端口
	-p 主机端口:容器端口 (常用)
	-p 容器端口

-大p   			随机指定端口


# 测试,启动并且进入容器
[root@VM-4-8-centos ~]# docker run -p 9999 -it 5d0da3dc9764
[root@4a098b3bac03 /]# ls
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  
opt  proc  root  run  sbin  srv  sys  tmp  usr  var

# 使用exit退出容器命令
[root@4a098b3bac03 /]# exit
exit

docker ps 命令 列出所有容器

# 列出当前正在运行的容器
docker ps 命令 
-a	# 列出当前正在运行的容器+带出历史运行过的容器
-n=? # 显示最近创建的容器
-q  #  只显示容器的编号

[root@VM-4-8-centos ~]# docker ps -a
CONTAINER ID   IMAGE          COMMAND       CREATED         STATUS                    PORTS     NAMES
acdfa099761b   5d0da3dc9764   "/bin/bash"   4 seconds ago   Exited (0) 1 second ago             thirsty_colden

退出容器

exit   # 直接容器停止并退出
Ctrl + P + Q  # 容器不停止退出

删除容器

docker rm 容器id				   # 删除指定的容器,不能删除正在运行的容器,如果需要删除,则需要 rm -f 强制删除 
docker rm -f $(docker ps -aq)      # 删除所有的容器

docker ps -a -q | xargs docker rm  # 删除所有的容器

启动和停止容器的操作

docker start 容器id      # 启动容器
docker restart 容器id    # 重启容器
docker stop 容器id       # 停止容器
docker kill 容器id	   # 强制杀死容器

2.4 其他常用命令

 # 命令 docker run -d 镜像名!
[root@VM-4-8-centos ~]# docker run -d centos  
964f2309ef3cfcb07b534059502323db66b23953ac44da286b7ca0b247fda327

[root@VM-4-8-centos ~]# docker ps -a
CONTAINER ID   IMAGE     COMMAND       CREATED          STATUS                      PORTS     NAMES
964f2309ef3c   centos    "/bin/bash"   23 seconds ago   Exited (0) 22 seconds ago             wonderful_wilbur

# 问题docker ps. 发现 centos 停止了
 
# 常见的坑:docker 容器使用后台运行,就必须有要一个前台进行,docker发现没有应用,就会自动的停止
# 容器启动后,发现自己没有提供服务,就会立刻停止,就是没有程序了

docker logs 容器id 查看日志的命令

docker logs 容器id

#参数
-f	 # 跟踪日志输出
-n=? # 显示多少条日志,不写默认为all
-t   # 显示时间戳

docker top 容器id 查看容器中进程信息

#docker top 容器id 是查看docker内部的信息
[root@VM-4-8-centos ~]# docker top 52f808ba7f1a
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                22004               21983               0                   10:39               pts/0               00:00:00            /bin/bash

docker inspect 容器id 镜像的元数据

# 命令  docker inspect 容器id


# 测试
[root@VM-4-8-centos ~]# docker inspect 52f808ba7f1a
[
    
        "Id": "52f808ba7f1a2419694fc0cd31d2fd8810a4456e5c8b0917096f5c80af164dff",
        "Created": "2023-03-27T02:39:42.598864277Z",
        "Path": "/bin/bash",
        "Args": [],
        "State": 
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 22004,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2023-03-27T02:39:42.943573356Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        ,
        "Image": "sha256:5d0da3dc976460b72c77d94c8a1ad043720b0416bfc16c52c45d4847e53fadb6",
        "ResolvConfPath": "/var/lib/docker/containers/52f808ba7f1a2419694fc0cd31d2fd8810a4456e5c8b0917096f5c80af164dff/resolv.conf",
        "HostnamePath": "/var/lib/docker/containers/52f808ba7f1a2419694fc0cd31d2fd8810a4456e5c8b0917096f5c80af164dff/hostname",
        "HostsPath": "/var/lib/docker/containers/52f808ba7f1a2419694fc0cd31d2fd8810a4456e5c8b0917096f5c80af164dff/hosts",
        "LogPath": "/var/lib/docker/containers/52f808ba7f1a2419694fc0cd31d2fd8810a4456e5c8b0917096f5c80af164dff/52f808ba7f1a2419694fc0cd31d2fd8810a4456e5c8b0917096f5c80af164dff-json.log",
        "Name": "/suspicious_wright",
        "RestartCount": 0,
        "Driver": "overlay2",
        "Platform": "linux",
        "MountLabel": "",
        "ProcessLabel": "",
        "AppArmorProfile": "",
        "ExecIDs": null,
        "HostConfig": 
            "Binds": null,
            "ContainerIDFile": "",
            "LogConfig": 
                "Type": "json-file",
                "Config": 
            ,
            "NetworkMode": "default",
            "PortBindings": 
                "9999/tcp": [
                    
                        "HostIp": "",
                        "HostPort": ""
                    
                ]
            ,
            "RestartPolicy": 
                "Name": "no",
                "MaximumRetryCount": 0
            ,
            "AutoRemove": false,
            "VolumeDriver": "",
            "VolumesFrom": null,
            "ConsoleSize": [
                25,
                188
            ],
            "CapAdd": null,
            "CapDrop": null,
            "CgroupnsMode": "host",
            "Dns": [],
            "DnsOptions": [],
            "DnsSearch": [],
            "ExtraHosts": null,
            "GroupAdd": null,
            "IpcMode": "private",
            "Cgroup": "",
            "Links": null,
            "OomScoreAdj": 0,
            "PidMode": "",
            "Privileged": false,
            "PublishAllPorts": false,
            "ReadonlyRootfs": false,
            "SecurityOpt": null,
            "UTSMode": "",
            "UsernsMode": "",
            "ShmSize": 67108864,
            "Runtime": "runc",
            "Isolation": "",
            "CpuShares": 0,
            "Memory": 0,
            "NanoCpus": 0,
            "CgroupParent": "",
            "BlkioWeight": 0,
            "BlkioWeightDevice": [],
            "BlkioDeviceReadBps": [],
            "BlkioDeviceWriteBps": [],
            "BlkioDeviceReadIOps": [],
            "BlkioDeviceWriteIOps": [],
            "CpuPeriod": 0,
            "CpuQuota": 0,
            "CpuRealtimePeriod": 0,
            "CpuRealtimeRuntime": 0,
            "CpusetCpus": "",
            "CpusetMems": "",
            "Devices": [],
            "DeviceCgroupRules": null,
            "DeviceRequests": null,
            "MemoryReservation": 0,
            "MemorySwap": 0,
            "MemorySwappiness": null,
            "OomKillDisable": false,
            "PidsLimit": null,
            "Ulimits": null,
            "CpuCount": 0,
            "CpuPercent": 0,
            "IOMaximumIOps": 0,
            "IOMaximumBandwidth": 0,
            "MaskedPaths": [
                "/proc/asound",
                "/proc/acpi",
                "/proc/kcore",
                "/proc/keys",
                "/proc/latency_stats",
                "/proc/timer_list",
                "/proc/timer_stats",
                "/proc/sched_debug",
                "/proc/scsi",
                "/sys/firmware"
            ],
            "ReadonlyPaths": [
                "/proc/bus",
                "/proc/fs",
                "/proc/irq",
                "/proc/sys",
                "/proc/sysrq-trigger"
            ]
        ,
        "GraphDriver": 
            "Data": 
                "LowerDir": "/var/lib/docker/overlay2/a8ec94947d108db6d6865b996ba0e1f9f29862e5a20741062d43e0f40bd33d92-init/diff:/var/lib/docker/overlay2/e20884d4e1b741ba886a96cdb9aacd515a0dc873e13e9ab457ba80dbeebe7ff6/diff",
                "MergedDir": "/var/lib/docker/overlay2/a8ec94947d108db6d6865b996ba0e1f9f29862e5a20741062d43e0f40bd33d92/merged",
                "UpperDir": "/var/lib/docker/overlay2/a8ec94947d108db6d6865b996ba0e1f9f29862e5a20741062d43e0f40bd33d92/diff",
                "WorkDir": "/var/lib/docker/overlay2/a8ec94947d108db6d6865b996ba0e1f9f29862e5a20741062d43e0f40bd33d92/work"
            ,
            "Name": "overlay2"
        ,
        "Mounts": [],
        "Config": 
            "Hostname": "52f808ba7f1a",
            "Domainname": "",
            "User": "",
            "AttachStdin": true,
            "AttachStdout": true,
            "AttachStderr": true,
            "ExposedPorts": 
                "9999/tcp": 
            ,
            "Tty": true,
            "OpenStdin": true,
            "StdinOnce": true,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "/bin/bash"
            ],
            "Image": "5d0da3dc9764",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": 
                "org.label-schema.build-date": "20210915",
                "org.label-schema.license": "GPLv2",
                "org.label-schema.name": "CentOS Base Image",
                "org.label-schema.schema-version": "1.0",
                "org.label-schema.vendor": "CentOS"
            
        ,
        "NetworkSettings": 
            "Bridge": "",
            "SandboxID": "47c564b6df75a68cbfbc3f707f4a86896008e565583fdf3a1b858ce4340431b0",
            "HairpinMode": false,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "Ports": 
                "9999/tcp": [
                    
                        "HostIp": "0.0.0.0",
                        "HostPort": "32772"
                    ,
                    
                        "HostIp": "::",
                        "HostPort": "32772"
                    
                ]
            ,
            "SandboxKey": "/var/run/docker/netns/47c564b6df75",
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "EndpointID": "71b4819e81e4bf1d2475fee4fe982537dd6974f76f853deeafe704af0ceca649",
            "Gateway": "172.17.0.1",
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "IPAddress": "172.17.0.2",
            "IPPrefixLen": 16,
            "IPv6Gateway": "",
            "MacAddress": "02:42:ac:11:00:02",
            "Networks": 
                "bridge": 
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "0a61313f17fe621a78c4756bb9b0461723747bd050c2ff8e2465736d17b103ce",
                    "EndpointID": "71b4819e81e4bf1d2475fee4fe982537dd6974f76f853deeafe704af0ceca649",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:11:00:02",
                    "DriverOpts": null
                
            
        
    
]

进入当前正在运行的容器

# 我们通过从容器都是使用后台运行的,需要进入容器,修改一些配置

# 方式一
# docker exec -it 容器id bashShell
[root@VM-4-8-centos ~]# docker exec -it 52f808ba7f1a /bin/bash

[root@52f808ba7f1a /]# ls
bin  dev  etc  home  lib  lib64  lost+found  media  
mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

# 方式二
docker attach 容器id

# 测试
[root@VM-4-8-centos ~]# docker attach 6cb0fea026f8   
正在执行的代码.....


# docker exec     # 进入容器后开启一个新的终端,可以在里面操作(常用)
# docker attach   # 进入容器正在执行的终端,不会启动新的进程!

从容器内拷贝文件到主机上

# docker cp 容器id:容器内路径  目的的主机路径
[root@VM-4-8-centos ~]# docker ps
CONTAINER ID   IMAGE          COMMAND       CREATED       STATUS       PORTS                                         NAMES
52f808ba7f1a   5d0da3dc9764   "/bin/bash"   4 hours ago   Up 4 hours   0.0.0.0:32772->9999/tcp, :::32772->9999/tcp   suspicious_wright

# 进入到容器内部
[root@VM-4-8-centos ~]# docker attach 52f808ba7f1a
[root@52f808ba7f1a /]# cd /home
[root@52f808ba7f1a home]# ls

# 在容器内部创建一个 test.java文件
[root@52f808ba7f1a home]# touch test.java
[root@52f808ba7f1a home]# ls
test.java

# 退出容器
[root@52f808ba7f1a home]# exit
exit
[root@VM-4-8-centos ~]# cd /www
[root@VM-4-8-centos www]# ls
xxl-job

# 将容器内部的文件进行拷贝到当前文件夹下面
[root@VM-4-8-centos www]# docker cp 52f808ba7f1a:/home/test.java /www
Preparing to copy...
Successfully copied 1.536kB to /www
[root@VM-4-8-centos www]# ls
test.java  xxl-job

# 拷贝是一个手动过程,未来我们使用 -v 的技术,可以实现自动同步  /home  /home

3.小练习

3.1 Docker下安装nginx

# 1、搜索镜像 search 去docker官网下载
[root@VM-4-8-centos ~]# docker search nginx
 
# 2、下载nginx            
[root@VM-4-8-centos ~]# docker pull nginx

[root@VM-4-8-centos ~]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
nginx        latest    ac232364af84   4 days ago      142MB
centos       latest    5d0da3dc9764   18 months ago   231MB

# 3、启动nginx
# docker run -d --name nginx01 -p 3344:80 nginx
# -d 后台运行
#--name  给容器命名
# -p 宿主机端口
[root@VM-4-8-centos ~]# docker run -d --name nginx01 -p 3344:80 nginx
758560e9f1544d39c50ef4cad8f936523c5a523bab44a73b771c1b774761be4f

[root@VM-4-8-centos ~]# curl localhost:3344
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html  color-scheme: light dark; 
body  width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; 
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>

学相伴狂神说 RabbitMQ笔记(简单使用RabbitMQ)

目录

什么是rabbitMQ

使用docker安装RabbitMQ,如果没有使用过docker的可以看这篇文章https://blog.csdn.net/qq_44716544/article/details/119870837

授权账号和密码

设置用户分配操作权限

RabbitMQ支持的消息模型

1.入门案例

1. RabbitMQ入门案例 - Simple 简单模式

2. 什么是AMQP

01 什么是AMQP

02 AMQP生产者流转过程

03 AMQP消费者流转过程

3. RabbitMQ的核心组成部分

01 RabbitMQ的核心组成部分

02 RabbitMQ整体架构是什么样子的?

03 RabbitMQ的运行流程

4. RabbitMQ入门案例 - fanout 模式

01 RabbitMQ的模式之发布订阅模式

5. RabbitMQ入门案例 - Direct 模式

6. RabbitMQ入门案例 - Topic 模式

完整案例(创建交换机,创建队列,交换机与队列绑定)

7. RabbitMQ入门案例 - Work模式

01 Work模式轮询模式(Round-Robin)

01轮询模式

02 Work模式公平分发模式 

8. RabbitMQ使用场景

01 解耦、削峰、异步

02 高内聚,低耦合

四、Springboot案例

1. Fanout 模式

2. Direct 模式

3. Topic 模式

五、RabbitMQ高级

2. 死信队列

3. 内存磁盘的监控

01 RabbitMQ内存警告

02 RabbitMQ的内存控制

03 RabbitMQ的内存换页

04 RabbitMQ的磁盘预警

4. 集群(docker集群rabbitmq)

1.先创建三个rabbitmq容器

2.容器节点加入集群


什么是rabbitMQ

 RabbitMQ是一个由erlang开发的AMQP(Advanced Message Queue 高级消息队列协议 )的开源实现,能够实现异步消息处理
 RabbitMQ是一个消息代理:它接受和转发消息。
你可以把它想象成一个邮局:当你把你想要发布的邮件放在邮箱中时,你可以确定邮差先生最终将邮件发送给你的收件人。在这个比喻中,RabbitMQ是邮政信箱,邮局和邮递员。 
RabbitMQ和邮局的主要区别在于它不处理纸张,而是接受,存储和转发二进制数据块
        
优点:异步消息处理
           业务解耦(下订单操作:扣减库存、生成订单、发红包、发短信),将下单操作主流程:扣减库存、生成订单然后通过MQ消息队列完成通知,发红包、发短信
            错峰流控 (通知量 消息量 订单量大的情况实现MQ消息队列机制,淡季情况下访问量会少)
        
              灵活的路由(Flexible Routing) 
             在消息进入队列之前,通过 Exchange 来路由消息的。对于典型的路由功能,RabbitMQ 已经提供了一些内置的 Exchange 来实现。针对更复杂的路由功能,可以将多个 Exchange 绑定在一起,也通过插件机制实现自己的 Exchange 。
        RabbitMQ网站端口号:15672
        程序里面实现的端口为:5672


       

 

使用docker安装RabbitMQ,如果没有使用过docker的可以看这篇文章https://blog.csdn.net/qq_44716544/article/details/119870837

1.拉取RabbitMQ镜像

docker pull rabbitmq:management

2.运行RabbitMQ镜像

docker run -itd --name rabbit01 --hostname myrabbit -e RABBITMQ_DEFAULT_USER=chenjinxian -e RABBITMQ_DEFAULT_PASS=chenjinxian -p 15672:15672 -p  5672:5672 -p 25672:25672 rabbitmq:management

注意:RABBITMQ_DEFAULT_USER=chenjinxian -e RABBITMQ_DEFAULT_PASS=chenjinxian 

   这里设置的是(RABBITMQ_DEFAULT_USER)登录的账号和( RABBITMQ_DEFAULT_PASS)密码,根据自身来修改

 这里看到容器已经开启成功了,然后就可以使用了

 

3.通过浏览器打开

如果你使用的是本地虚拟机,那么你直接使用虚拟机显示的ipv4地址加端口号就可以访问了;

如果你使用的是云服务器,那么你需要在对应服务器(阿里云,腾讯云等)的安全组中开放15672端口,并且在防火墙中也开放15672端口

 

 显示如上图那么就可以开始使用了

然后通过命令进入rabbitmq容器

docker exec -it rabbit01 /bin/bash

授权账号和密码

rabbitmqctl add_user admin admin

设置用户分配操作权限

rabbitmqctl set_user_tags admin administrator

用户级别:

  1. administrator:可以登录控制台、查看所有信息、可以对 rabbitmq进行管理

  2. monitoring:监控者 登录控制台,查看所有信息

  3. policymaker:策略制定者 登录控制台,指定策略

  4. managment 普通管理员 登录控制台

为用户添加资源权限

rabbitmqctl set_permissions -p / admin ".*"".*"".*"

也可以在界面操作进行添加用户

 

RabbitMQ支持的消息模型

1.简单模式 Simple  

 

     2.工作模式 Work

       

 

     3.发布订阅模式

 4.路由模式

5.主题 Topic模式

 

      6.参数模式

7.出版商确认模式

 

1.入门案例

1. RabbitMQ入门案例 - Simple 简单模式

  1. jdk1.8

  2. 构建一个 maven工程

  3. 定义生产者

  4. 定义消费者

  5. 观察消息的在 rabbitmq-server服务中的进程

 

01 构建一个maven工程

02 导入依赖

 <dependencies>
        <!--导入rabbitmq的依赖-->
        <dependency>
            <groupId>com.rabbitmq</groupId>
            <artifactId>amqp-client</artifactId>
            <version>5.13.0</version>
        </dependency>

    </dependencies>

3.代码编写 

 在上图的模型中,有以下概念:

  1. 生产者,也就是要发送消息的程序

  2. 消费者:消息的接受者,会一直等待消息到来。

  3. 消息队列:图中红色部分。类似一个邮箱,可以缓存消息;生产者向其中投递消息,消费者从其中取出消息。

生产者

package com.chen.rabbitmq.simple;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.MessageProperties;

/**
 * @description: 简单模式Simple
 */
public class Producer 


    public static void main(String[] args) 

        // 所有的中间件技术都是基于tcp/ip协议基础之上构建新型的协议规范,只不过rabbitmq遵循的是amqp
        // ip port

        // 1: 创建连接工程
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("128.197.157.151");
        connectionFactory.setPort(5672);
        connectionFactory.setUsername("chenjinxian");//rabbitmq登录的账号
        connectionFactory.setPassword("chenjinxian");//rabbitmq登录的密码
        connectionFactory.setVirtualHost("/");

        //springboot ---rabbitmq

        Connection connection = null;
        Channel channel = null;
        try 
            // 2: 创建连接Connection Rabbitmq为什么是基于channel去处理而不是链接? 长连接----信道channel
            connection = connectionFactory.newConnection("生成者");
            // 3: 通过连接获取通道Channel
            channel = connection.createChannel();
            // 4: 通过通创建交换机,声明队列,绑定关系,路由key,发送消息,和接收消息
            String queueName = "queue1";

            /*
             * @params1 队列的名称
             * @params2 是否要持久化durable=false 所谓持久化消息是否存盘,如果false 非持久化 true是持久化? 非持久化会存盘吗? 会存盘,但是会随从重启服务会丢失。
             * @params3 排他性,是否是独占独立
             * @params4 是否自动删除,随着最后一个消费者消息完毕消息以后是否把队列自动删除
             * @params5 携带附属参数
             */
            channel.queueDeclare(queueName, true, false, false, null);
            // 5: 准备消息内容
            String message = "Hello chenjinxian!!!";
            // 6: 发送消息给队列queue
            // @params1: 交换机  @params2 队列、路由key @params 消息的状态控制  @params4 消息主题
            // 面试题:可以存在没有交换机的队列吗?不可能,虽然没有指定交换机但是一定会存在一个默认的交换机。
            channel.basicPublish("", queueName, null, message.getBytes());

            System.out.println("消息发送成功!!!");
         catch (Exception ex) 
            ex.printStackTrace();
         finally 
            // 7: 关闭通道
            if (channel != null && channel.isOpen()) 
                try 
                    channel.close();
                 catch (Exception ex) 
                    ex.printStackTrace();
                
            
            // 8: 关闭连接

            if (connection != null && connection.isOpen()) 
                try 
                    connection.close();
                 catch (Exception ex) 
                    ex.printStackTrace();
                
            
        


    

 

 

消费者

package com.chen.rabbitmq.simple;

import com.rabbitmq.client.*;
import java.io.IOException;

public class Consumer 


    public static void main(String[] args) 

        // 所有的中间件技术都是基于tcp/ip协议基础之上构建新型的协议规范,只不过rabbitmq遵循的是amqp
        // ip port

        // 1: 创建连接工程
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("128.197.157.151");//服务器IP
        connectionFactory.setPort(5672);
        connectionFactory.setUsername("chenjinxian");
        connectionFactory.setPassword("chenjinxian");
        connectionFactory.setVirtualHost("/");

        Connection connection = null;
        Channel channel = null;
        try 
            // 2: 创建连接Connection
            connection = connectionFactory.newConnection("消费者");
            // 3: 通过连接获取通道Channel
            channel = connection.createChannel();
            // 4: 通过通创建交换机,声明队列,绑定关系,路由key,发送消息,和接收消息


            // true = ack 正常的逻辑是没问题 死循环 rabbit 重发策略
            // false = nack 消息这在消费消息的时候可能会异常和故障
            final  Channel channel2 = channel;
            channel2.basicConsume("queue1", false, new DeliverCallback() 
                public void handle(String consumerTag, Delivery message) throws IOException 
                    try 
                        System.out.println("收到消息是" + new String(message.getBody(), "UTF-8"));
                        channel2.basicAck(message.getEnvelope().getDeliveryTag(),false);
                    catch (Exception ex)
                        ex.printStackTrace();
                        // 三次确认 -- reject + sixin
                    

                
            , new CancelCallback() 
                public void handle(String consumerTag) throws IOException 
                    System.out.println("接受失败了...");
                
            );

            System.out.println("开始接受消息");
            System.in.read();

         catch (Exception ex) 
            ex.printStackTrace();
         finally 
            // 7: 关闭通道
            if (channel != null && channel.isOpen()) 
                try 
                    channel.close();
                 catch (Exception ex) 
                    ex.printStackTrace();
                
            
            // 8: 关闭连接

            if (connection != null && connection.isOpen()) 
                try 
                    connection.close();
                 catch (Exception ex) 
                    ex.printStackTrace();
                
            
        


    

 

2. 什么是AMQP

01 什么是AMQP

AMQP全称:Advanced Message Queuing Protocol(高级消息队列协议)。是应用层协议的一个开发标准,为面向消息的中间件设计

02 AMQP生产者流转过程

 

03 AMQP消费者流转过程

 

3. RabbitMQ的核心组成部分

01 RabbitMQ的核心组成部分

 

核心概念: 核心概念:
Server :又称Broker ,接受客户端的连接,实现AMQP实体服务。安装rabbitmq-serverConnection:连接,应用程序与Broker的网络连接TCP/IP/三次握手和四次挥手 服务器:又称Broker,接受客户端的连接,实现AMQP实体服务。安装Rabbitmq-serverConnection:连接,应用程序与Broker的网络连接tcp/ip/三次握手和四次挥手
Channel:网络信道,几乎所有的操作都在Channel中进行,Channel是进 息读写的通道,客户端可以建立对恪Channel,每个Channel代表一个会话任务。 频道:网络信道,几乎所有的操作都在频道中进行频道,是进息读写的通道,客户端可以建立对恪频道频道,每个频道代表一个会话任务频道。
Message :消息:服务与应用程序之间传送的数据,由Properties和body组成,Properties可是对消息进行修饰,如消息的优先级,延迟等高级特性,Body则就是消息体的内容。 消息:消息:服务与应用程序之间传送的数据,由Properties和Body组成,Properties可是对消息进行修饰,如消息的优先级,延迟等高级特性,Body则就是消息体的内容。
Virtual Host虚拟地址,用于进行逻辑隔离,最上层的消息路由,一个虚拟主机理由可以有若干个Exhange和Queueu,同一个虚拟主机里面不能有相同名字的Exchange 虚拟主机虚拟地址,用于进行逻辑隔离,最上层的消息路由,一个虚拟主机理由可以有若干个Exhange和Queueu,同一个虚拟主机里面不能有相同名字的Exchange
Exchange :交换机,接受消息,根据路由键发送消息到绑定的队列。(==不具备消息存储的能力==)Bindings : Exchange和Queue之间的虚拟连接,binding中可以保护多个routing key. 交换:交换机,接受消息,根据路由键发送消息到绑定的队列.(=不具备消息存储的能力==)绑定:Exchange和Queue之间的虚拟连接,Binding中可以保护多个路由密钥。
Routing key :是一个路由规则,虚拟机可以用它来确定如何路由一个特疋消恳.bttos:/bloq.csdn.net/qg _4485823(Queue:队列:也成为Message Queue,消息队列,保存消息并将它们转发给消费苦。"gwa" 路由密钥:是一个路由规则,虚拟机可以用它来确定如何路由一个特征消息(队列:队列:也成为消息队列,消息队列,保存消息并将它们转发给消费者.

 

02 RabbitMQ整体架构是什么样子的?

03 RabbitMQ的运行流程

 

 

4. RabbitMQ入门案例 - fanout 模式

01 RabbitMQ的模式之发布订阅模式

 

发布订阅模式的具体实现

  1. 类型:fanout

  2. 特点:Fanout - 发布与订阅模式,是一种广播机制,它是没有路由 key的模式

(注意这里已经在可视化界面让队列绑定了交换机)

 

生产者

package com.chen.rabbitmq.fanout;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

/**
 发布订阅模式的具体实现
 类型:fanout
 特点:Fanout - 发布与订阅模式,是一种广播机制,它是没有路由 key的模式
 */
public class Producer 
    public static void main(String[] args) 
        // 1: 创建连接工厂
        ConnectionFactory connectionFactory = new ConnectionFactory();
        // 2: 设置连接属性
        connectionFactory.setHost("128.156.157.161");
        connectionFactory.setPort(5672);
        connectionFactory.setVirtualHost("/");
        connectionFactory.setUsername("chenjinxian");
        connectionFactory.setPassword("chenjinxian");
        Connection connection = null;
        Channel channel = null;
        try 
            // 3: 从连接工厂中获取连接
            connection = connectionFactory.newConnection("生产者");
            // 4: 从连接中获取通道channel
            channel = connection.createChannel();

            // 5: 准备发送消息的内容
            String message = "hello xuexi!!!";

            // 6:准备交换机
            String exchangeName = "fanout_change";

            // 8: 指定交换机的类型
            String type = "fanout";
            // 7: 发送消息给中间件rabbitmq-server
            // @params1: 交换机exchange
            // @params2: 队列名称/routingkey
            // @params3: 属性配置
            // @params4: 发送消息的内容
            //  #.course.* queue3
            // *.order.# queue2 ta
            // com.order.course.xxx collecion
            channel.basicPublish(exchangeName,"", null, message.getBytes());


            System.out.println("消息发送成功!");
         catch (Exception ex) 
            ex.printStackTrace();
            System.out.println("发送消息出现异常...");
         finally 

            // 7: 释放连接关闭通道
            if (channel != null && channel.isOpen()) 
                try 
                    channel.close();
                 catch (Exception ex) 
                    ex.printStackTrace();
                
            
            if (connection != null) 
                try 
                    connection.close();
                 catch (Exception ex) 
                    ex.printStackTrace();
                
            
        
    

消费者

package com.chen.rabbitmq.fanout;

import com.rabbitmq.client.*;

import java.io.IOException;

/**
 发布订阅模式的具体实现
 类型:fanout
 特点:Fanout - 发布与订阅模式,是一种广播机制,它是没有路由 key的模式
 */
public class Consumer 

    private static Runnable runnable = new Runnable() 
        public void run() 
            // 1: 创建连接工厂
            ConnectionFactory connectionFactory = new ConnectionFactory();
            // 2: 设置连接属性
            connectionFactory.setHost("128.156.157.151");
            connectionFactory.setPort(5672);
            connectionFactory.setVirtualHost("/");
            connectionFactory.setUsername("chenjinxian");
            connectionFactory.setPassword("chenjinxian");
            //获取队列的名称
            final String queueName = Thread.currentThread().getName();
            Connection connection = null;
            Channel channel = null;
            try 
                // 3: 从连接工厂中获取连接
                connection = connectionFactory.newConnection("生产者");
                // 4: 从连接中获取通道channel
                channel = connection.createChannel();
                // 5: 申明队列queue存储消息
                /*
                 *  如果队列不存在,则会创建
                 *  Rabbitmq不允许创建两个相同的队列名称,否则会报错。
                 *
                 *  @params1: queue 队列的名称
                 *  @params2: durable 队列是否持久化
                 *  @params3: exclusive 是否排他,即是否私有的,如果为true,会对当前队列加锁,其他的通道不能访问,并且连接自动关闭
                 *  @params4: autoDelete 是否自动删除,当最后一个消费者断开连接之后是否自动删除消息。
                 *  @params5: arguments 可以设置队列附加参数,设置队列的有效期,消息的最大长度,队列的消息生命周期等等。
                 * */
                // 这里如果queue已经被创建过一次了,可以不需要定义
                //channel.queueDeclare("queue1", false, false, false, null);
                // 6: 定义接受消息的回调
                Channel finalChannel = channel;
                finalChannel.basicConsume(queueName, true, new DeliverCallback() 
                    @Override
                    public void handle(String s, Delivery delivery) throws IOException 
                        System.out.println(queueName + ":收到消息是:" + new String(delivery.getBody(), "UTF-8"));
                    
                , new CancelCallback() 
                    @Override
                    public void handle(String s) throws IOException 
                    
                );
                System.out.println(queueName + ":开始接受消息");
                System.in.read();
             catch (Exception ex) 
                ex.printStackTrace();
                System.out.println("发送消息出现异常...");
             finally 
                // 7: 释放连接关闭通道
                if (channel != null && channel.isOpen()) 
                    try 
                        channel.close();
                     catch (Exception ex) 
                        ex.printStackTrace();
                    
                
                if (connection != null && connection.isOpen()) 
                    try 
                        connection.close();
                     catch (Exception ex) 
                        ex.printStackTrace();
                    
                
            
        
    ;



    public static void main(String[] args) 
        // 启动三个线程去执行
        new Thread(runnable, "queue1").start();
        new Thread(runnable, "queue2").start();
        new Thread(runnable, "queue3").start();
        new Thread(runnable, "queue4").start();
        //new Thread(runnable, "queue5").start();
    

 

 

5. RabbitMQ入门案例 - Direct 模式

 (注意这里已经在可视化界面让队列绑定了交换机)

生产者

package com.chen.rabbitmq.routing;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

/**
 Direct 模式
 */
public class Producer 
    public static void main(String[] args) 
        // 1: 创建连接工厂
        ConnectionFactory connectionFactory = new ConnectionFactory();
        // 2: 设置连接属性
        connectionFactory.setHost("128.176.157.151");
        connectionFactory.setPort(5672);
        connectionFactory.setVirtualHost("/");
        connectionFactory.setUsername("chenjinxian");
        connectionFactory.setPassword("chenjinxian");
        Connection connection = null;
        Channel channel = null;
        try 
            // 3: 从连接工厂中获取连接
            connection = connectionFactory.newConnection("生产者");
            // 4: 从连接中获取通道channel
            channel = connection.createChannel();

            // 5: 准备发送消息的内容
            String message = "hello direct_exchange!!!";

            // 6:准备交换机
            String exchangeName = "direct_exchange";
            // 7: 定义路由key
            String routeKey = "email";
            // 8: 指定交换机的类型
            String type = "direct";
            // 7: 发送消息给中间件rabbitmq-server
            // @params1: 交换机exchange
            // @params2: 队列名称/routingkey
            // @params3: 属性配置
            // @params4: 发送消息的内容
            //  #.course.* queue3
            // *.order.# queue2 ta
            // com.order.course.xxx collecion
            channel.basicPublish(exchangeName, routeKey, null, message.getBytes());
            System.out.println("消息发送成功!");
         catch (Exception ex) 
            ex.printStackTrace();
            System.out.println("发送消息出现异常...");
         finally 
            // 7: 释放连接关闭通道
            if (channel != null && channel.isOpen()) 
                try 
                    channel.close();
                 catch (Exception ex) 
                    ex.printStackTrace();
                
            
            if (connection != null) 
                try 
                    connection.close();
                 catch (Exception ex) 
                    ex.printStackTrace();
                
            
        
    

消费者

package com.chen.rabbitmq.routing;

import com.rabbitmq.client.*;

import java.io.IOException;

/**
 Direct 模式
 */
public class Consumer 

    private static Runnable runnable = new Runnable() 
        public void run() 
            // 1: 创建连接工厂
            ConnectionFactory connectionFactory = new ConnectionFactory();
            // 2: 设置连接属性
            connectionFactory.setHost("123.156.147.151");
            connectionFactory.setPort(5672);
            connectionFactory.setVirtualHost("/");
            connectionFactory.setUsername("chenjinxian");
            connectionFactory.setPassword("chenjinxian");
            //获取队列的名称
            final String queueName = Thread.currentThread().getName();
            Connection connection = null;
            Channel channel = null;
            try 
                // 3: 从连接工厂中获取连接
                connection = connectionFactory.newConnection("生产者");
                // 4: 从连接中获取通道channel
                channel = connection.createChannel();
                // 5: 申明队列queue存储消息
                /*
                 *  如果队列不存在,则会创建
                 *  Rabbitmq不允许创建两个相同的队列名称,否则会报错。
                 *
                 *  @params1: queue 队列的名称
                 *  @params2: durable 队列是否持久化
                 *  @params3: exclusive 是否排他,即是否私有的,如果为true,会对当前队列加锁,其他的通道不能访问,并且连接自动关闭
                 *  @params4: autoDelete 是否自动删除,当最后一个消费者断开连接之后是否自动删除消息。
                 *  @params5: arguments 可以设置队列附加参数,设置队列的有效期,消息的最大长度,队列的消息生命周期等等。
                 * */
                // 这里如果queue已经被创建过一次了,可以不需要定义
                //channel.queueDeclare("queue1", false, false, false, null);
                // 6: 定义接受消息的回调
                Channel finalChannel = channel;
                finalChannel.basicConsume(queueName, true, new DeliverCallback() 
                    @Override
                    public void handle(String s, Delivery delivery) throws IOException 
                        System.out.println(queueName + ":收到消息是:" + new String(delivery.getBody(), "UTF-8"));
                    
                , new CancelCallback() 
                    @Override
                    public void handle(String s) throws IOException 
                    
                );
                System.out.println(queueName + ":开始接受消息");
                System.in.read();
             catch (Exception ex) 
                ex.printStackTrace();
                System.out.println("发送消息出现异常...");
             finally 
                // 7: 释放连接关闭通道
                if (channel != null && channel.isOpen()) 
                    try 
                        channel.close();
                     catch (Exception ex) 
                        ex.printStackTrace();
                    
                
                if (connection != null && connection.isOpen()) 
                    try 
                        connection.close();
                     catch (Exception ex) 
                        ex.printStackTrace();
                    
                
            
        
    ;



    public static void main(String[] args) 
        // 启动三个线程去执行
        new Thread(runnable, "queue1").start();
        new Thread(runnable, "queue2").start();
        new Thread(runnable, "queue3").start();
        new Thread(runnable, "queue4").start();
      //  new Thread(runnable, "queue5").start();
    

6. RabbitMQ入门案例 - Topic 模式

  (注意这里已经在可视化界面让队列绑定了交换机)

 生产者

package com.chen.rabbitmq.topics;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

/**
 Topic模式
 */
public class Producer 
    public static void main(String[] args) 
        // 1: 创建连接工厂
        ConnectionFactory connectionFactory = new ConnectionFactory();
        // 2: 设置连接属性
        connectionFactory.setHost("125.156.157.151");
        connectionFactory.setPort(5672);
        connectionFactory.setVirtualHost("/");
        connectionFactory.setUsername("chenjinxian");
        connectionFactory.setPassword("chenjinxian");
        Connection connection = null;
        Channel channel = null;
        try 
            // 3: 从连接工厂中获取连接
            connection = connectionFactory.newConnection("生产者");
            // 4: 从连接中获取通道channel
            channel = connection.createChannel();

            // 5: 准备发送消息的内容
            String message = "hello topic_exchange!!!";

            // 6:准备交换机
            String exchangeName = "topic_exchange";
            // 7: 定义路由key
            String routeKey = "com.order.user";
            // 8: 指定交换机的类型
            String type = "topic";
            // 7: 发送消息给中间件rabbitmq-server
            // @params1: 交换机exchange
            // @params2: 队列名称/routingkey
            // @params3: 属性配置
            // @params4: 发送消息的内容
            //  #.course.* queue3
            // *.order.# queue2 ta
            // com.order.course.xxx collecion
            channel.basicPublish(exchangeName, routeKey, null, message.getBytes());
            System.out.println("消息发送成功!");
         catch (Exception ex) 
            ex.printStackTrace();
            System.out.println("发送消息出现异常...");
         finally 
            // 7: 释放连接关闭通道
            if (channel != null && channel.isOpen()) 
                try 
                    channel.close();
                 catch (Exception ex) 
                    ex.printStackTrace();
                
            
            if (connection != null) 
                try 
                    connection.close();
                 catch (Exception ex) 
                    ex.printStackTrace();
                
            
        
    

 消费者不变

完整案例(创建交换机,创建队列,交换机与队列绑定)

package com.chen.rabbitmq.all;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

/**
完整案例
 */
public class Producer 
    public static void main(String[] args) 
        // 1: 创建连接工厂
        ConnectionFactory connectionFactory = new ConnectionFactory();
        // 2: 设置连接属性
        connectionFactory.setHost("151.156.157.151");
        connectionFactory.setPort(5672);
        connectionFactory.setVirtualHost("/");
        connectionFactory.setUsername("chenjinxian");
        connectionFactory.setPassword("chenjinxian");
        Connection connection = null;
        Channel channel = null;
        try 
            // 3: 从连接工厂中获取连接
            connection = connectionFactory.newConnection("生产者");
            // 4: 从连接中获取通道channel
            channel = connection.createChannel();
            // 6: 准备发送消息的内容
            String message = " 你好,小白";
            // 交换机
            String  exchangeName = "direct_message_exchange";
            // 交换机的类型 direct/topic/fanout/headers
            String exchangeType = "direct";

            // 如果你用界面把queueu 和 exchange的关系先绑定话,你代码就不需要在编写这些声明代码可以让代码变得更加简洁,但是不容读懂
            // 如果用代码的方式去声明,我们要学习一下
            // 7: 声明交换机 所谓的持久化就是指,交换机会不会随着服务器重启造成丢失,如果是true代表不丢失,false重启就会丢失
            channel.exchangeDeclare(exchangeName,exchangeType,true);

            // 8: 声明队列
            channel.queueDeclare("queue5",true,false,false,null);
            channel.queueDeclare("queue6",true,false,false,null);
            channel.queueDeclare("queue7",true,false,false,null);

            // 9:绑定队列和交换机的关系
            channel.queueBind("queue5",exchangeName,"order");
            channel.queueBind("queue6",exchangeName,"order");
            channel.queueBind("queue7",exchangeName,"course");

            channel.basicPublish(exchangeName, "course", null, message.getBytes());
            System.out.println("消息发送成功!");
         catch (Exception ex) 
            ex.printStackTrace();
            System.out.println("发送消息出现异常...");
         finally 
            // 7: 释放连接关闭通道
            if (channel != null && channel.isOpen()) 
                try 
                    channel.close();
                 catch (Exception ex) 
                    ex.printStackTrace();
                
            
            if (connection != null) 
                try 
                    connection.close();
                 catch (Exception ex) 
                    ex.printStackTrace();
                
            
        
    

 执行完后生成队列和交换机

 

 

7. RabbitMQ入门案例 - Work模式

01 Work模式轮询模式(Round-Robin)

 

当有多个消费者时,我们的消息会被哪个消费者消费呢,我们又该如何均衡消费者消费信息的多少呢?

主要有两种模式:

  1. 轮询模式的分发:一个消费者一条,按均分配

  2. 公平分发:根据消费者的消费能力进行公平分发,处理快的处理的多,处理慢的处理的少;按劳分配

01轮询模式

生产者

package com.chen.rabbitmq.work.lunxun;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
/**
 轮询模式
 */
public class Producer 
    public static void main(String[] args) 
        // 1: 创建连接工厂
        ConnectionFactory connectionFactory = new ConnectionFactory();
        // 2: 设置连接属性
        connectionFactory.setHost("123.156.147.151");
        connectionFactory.setPort(5672);
        connectionFactory.setVirtualHost("/");
        connectionFactory.setUsername("chenjinxian");
        connectionFactory.setPassword("chenjinxian");
        Connection connection = null;
        Channel channel = null;
        try 
            // 3: 从连接工厂中获取连接
            connection = connectionFactory.newConnection("生产者");
            // 4: 从连接中获取通道channel
            channel = connection.createChannel();
            // 6: 准备发送消息的内容
            //===============================end topic模式==================================
            for (int i = 1; i <= 20; i++) 
                //消息的内容
                String msg = "学相伴:" + i;
                // 7: 发送消息给中间件rabbitmq-server
                // @params1: 交换机exchange
                // @params2: 队列名称/routingkey
                // @params3: 属性配置
                // @params4: 发送消息的内容
                channel.basicPublish("", "queue1", null, msg.getBytes());
            
            System.out.println("消息发送成功!");
         catch (Exception ex) 
            ex.printStackTrace();
            System.out.println("发送消息出现异常...");
         finally 
            // 7: 释放连接关闭通道
            if (channel != null && channel.isOpen()) 
                try 
                    channel.close();
                 catch (Exception ex) 
                    ex.printStackTrace();
                
            
            if (connection != null) 
                try 
                    connection.close();
                 catch (Exception ex) 
                    ex.printStackTrace();
                
            
        
    

消费者

package com.chen.rabbitmq.work.lunxun;
import com.rabbitmq.client.*;
import java.io.IOException;
/**
 轮询模式
 */
public class Work1 
    public static void main(String[] args) 
        // 1: 创建连接工厂
        ConnectionFactory connectionFactory = new ConnectionFactory();
        // 2: 设置连接属性
        connectionFactory.setHost("123.156.147.155");
        connectionFactory.setPort(5672);
        connectionFactory.setVirtualHost("/");
        connectionFactory.setUsername("chenjinxian");
        connectionFactory.setPassword("chenjinxian");
        Connection connection = null;
        Channel channel = null;
        try 
            // 3: 从连接工厂中获取连接
            connection = connectionFactory.newConnection("消费者-Work1");
            // 4: 从连接中获取通道channel
            channel = connection.createChannel();
            // 5: 申明队列queue存储消息
            /*
             *  如果队列不存在,则会创建
             *  Rabbitmq不允许创建两个相同的队列名称,否则会报错。
             *
             *  @params1: queue 队列的名称
             *  @params2: durable 队列是否持久化
             *  @params3: exclusive 是否排他,即是否私有的,如果为true,会对当前队列加锁,其他的通道不能访问,并且连接自动关闭
             *  @params4: autoDelete 是否自动删除,当最后一个消费者断开连接之后是否自动删除消息。
             *  @params5: arguments 可以设置队列附加参数,设置队列的有效期,消息的最大长度,队列的消息生命周期等等。
             * */
            // 这里如果queue已经被创建过一次了,可以不需要定义
//            channel.queueDeclare("queue1", false, false, false, null);
            // 同一时刻,服务器只会推送一条消息给消费者
            // 6: 定义接受消息的回调
            Channel finalChannel = channel;
            //finalChannel.basicQos(1);

            finalChannel.basicConsume("queue1", true, new DeliverCallback() 
                @Override
                public void handle(String s, Delivery delivery) throws IOException 
                    try
                        System.out.println("Work1-收到消息是:" + new String(delivery.getBody(), "UTF-8"));
                        Thread.sleep(200);
                    catch(Exception ex)
                        ex.printStackTrace();
                    
                
            , new CancelCallback() 
                @Override
                public void handle(String s) throws IOException 
                
            );
            System.out.println("Work1-开始接受消息");
            System.in.read();
         catch (Exception ex) 
            ex.printStackTrace();
            System.out.println("发送消息出现异常...");
         finally 
            // 7: 释放连接关闭通道
            if (channel != null && channel.isOpen()) 
                try 
                    channel.close();
                 catch (Exception ex) 
                    ex.printStackTrace();
                
            
            if (connection != null && connection.isOpen()) 
                try 
                    connection.close();
                 catch (Exception ex) 
                    ex.printStackTrace();
                
            
        
    
package com.chen.rabbitmq.work.lunxun;
import com.rabbitmq.client.*;
import java.io.IOException;
/**
 轮询模式
 */
public class Work2 
    public static void main(String[] args) 
        // 1: 创建连接工厂
        ConnectionFactory connectionFactory = new ConnectionFactory();
        // 2: 设置连接属性
        connectionFactory.setHost("123.195.157.151");
        connectionFactory.setPort(5672);
        connectionFactory.setVirtualHost("/");
        connectionFactory.setUsername("chenjinxian");
        connectionFactory.setPassword("chenjinxian");
        Connection connection = null;
        Channel channel = null;
        try 
            // 3: 从连接工厂中获取连接
            connection = connectionFactory.newConnection("消费者-Work2");
            // 4: 从连接中获取通道channel
            channel = connection.createChannel();
            // 5: 申明队列queue存储消息
            /*
             *  如果队列不存在,则会创建
             *  Rabbitmq不允许创建两个相同的队列名称,否则会报错。
             *
             *  @params1: queue 队列的名称
             *  @params2: durable 队列是否持久化
             *  @params3: exclusive 是否排他,即是否私有的,如果为true,会对当前队列加锁,其他的通

以上是关于狂神说Docker的主要内容,如果未能解决你的问题,请参考以下文章

狂神说JavaGit最新教程通俗易懂

狂神说Java

狂神说Java

狂神说ngnix笔记(附md文件下载链接)

Docker(感谢狂神)

狂神说Java个人笔记-JavaWeb

(c)2006-2024 SYSTEM All Rights Reserved IT常识