狂神说Docker
Posted Filwaod
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了狂神说Docker相关的知识,希望对你有一定的参考价值。
文章目录
参考: https://blog.csdn.net/weixin_47024018/article/details/127916629
1.Docker概念与安装
1.1 概述
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows操作系统的机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。
基础名词:
-
镜像(image):
docker镜像就好比是一个模板,可以通过这个模板来创建容器服务,tomcat镜像 => run =>tomcat01容器(提供服务),通过这个镜像可以创建多个容器(最终服务运行或者项目运行就是在容器中的)。 -
容器(container):
Docker利用容器技术可以独立运行一个或者一组应用,通过镜像来创建的,启动,停止、删除、基本命令
目前就可以把这个容器理解为一个简易的linux系统 -
仓库(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)
目录
使用docker安装RabbitMQ,如果没有使用过docker的可以看这篇文章https://blog.csdn.net/qq_44716544/article/details/119870837
什么是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
用户级别:
-
administrator:可以登录控制台、查看所有信息、可以对 rabbitmq进行管理
-
monitoring:监控者 登录控制台,查看所有信息
-
policymaker:策略制定者 登录控制台,指定策略
-
managment 普通管理员 登录控制台
为用户添加资源权限
rabbitmqctl set_permissions -p / admin ".*"".*"".*"
也可以在界面操作进行添加用户
RabbitMQ支持的消息模型
1.简单模式 Simple
2.工作模式 Work
3.发布订阅模式
4.路由模式
5.主题 Topic模式
6.参数模式
7.出版商确认模式
1.入门案例
1. RabbitMQ入门案例 - Simple 简单模式
-
jdk1.8
-
构建一个 maven工程
-
定义生产者
-
定义消费者
-
观察消息的在 rabbitmq-server服务中的进程
01 构建一个maven工程
02 导入依赖
<dependencies>
<!--导入rabbitmq的依赖-->
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>5.13.0</version>
</dependency>
</dependencies>
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的模式之发布订阅模式
发布订阅模式的具体实现
-
类型:fanout
-
特点: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)
当有多个消费者时,我们的消息会被哪个消费者消费呢,我们又该如何均衡消费者消费信息的多少呢?
主要有两种模式:
-
轮询模式的分发:一个消费者一条,按均分配
-
公平分发:根据消费者的消费能力进行公平分发,处理快的处理的多,处理慢的处理的少;按劳分配
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的主要内容,如果未能解决你的问题,请参考以下文章