Docker-Consul容器服务更新与发现

devtools/2024/9/25 23:24:14/

前言

Docker Compose 则进一步简化了多个容器应用的编排与管理。另一方面,Consul 作为一款先进的服务发现工具,为分布式和微服务架构提供了可靠的服务注册与发现机制。本文将探讨 Docker Compose 和 Consul 在容器化环境中的协同作用,以及它们如何共同帮助开发人员更高效地构建、部署和管理其应用程序。

Docker Compose相关介绍请参考:

Docker-Compose单机多容器应用编排与管理-CSDN博客

目录

一、概述

1. 服务注册与发现

consul-toc" style="margin-left:40px;">2. 什么是 consul

3. 服务架构

3.1 传统架构

consul%20%E6%9E%B6%E6%9E%84-toc" style="margin-left:80px;">3.2 consul 架构

4. 关键特性

二、Consul 部署

1. 容器服务更新与发现拓扑图

2. 部署信息

consul%20%E6%9C%8D%E5%8A%A1%E5%99%A8-toc" style="margin-left:40px;">3. consul 服务器

consul%20%E6%9C%8D%E5%8A%A1-toc" style="margin-left:80px;">3.1 建立 consul 服务

3.2 查看集群信息

3.3 通过 http api 获取集群信息

4. registrator 服务器

4.1 安装 Gliderlabs/Registrato

4.2 测试服务发现功能是否正常

consul%C2%A0-toc" style="margin-left:80px;">4.3 验证 http 和 nginx 服务是否注册到 consul 

consul-template%C2%A0-toc" style="margin-left:40px;">5. consul-template 

5.1 准备 template nginx 模板文件

5.2 安装配置 nginx 服务

5.3 配置并启动 template

5.4 访问 template-nginx

5.5 增加一个 nginx 容器节点

consul%20%E5%A4%9A%E8%8A%82%E7%82%B9-toc" style="margin-left:40px;">6. consul 多节点

docker%C2%A0-toc" style="margin-left:80px;">6.1 安装 docker 

consul%20%E7%9B%B8%E5%85%B3%E6%9C%8D%E5%8A%A1%E6%96%87%E4%BB%B6%EF%BC%8C%E5%90%AF%E5%8A%A8%20consul%20%E6%9C%8D%E5%8A%A1-toc" style="margin-left:80px;">6.2 拷贝 consul 相关服务文件,启动 consul 服务

6.3 查看集群信息


一、概述

1. 服务注册与发现

① 服务注册:在Docker中运行的应用程序可以通过Consul客户端向Consul服务注册自己的信息,包括服务名称、IP地址、端口号等。这样,Consul就会维护一个服务目录,记录着所有可用的服务实例及其位置信息。

② 服务发现:其他Docker容器或应用程序可以通过Consul客户端查询Consul服务注册中心,动态地发现和连接到需要的服务。Consul根据服务名称、标签、健康状态等条件来选择合适的服务实例,实现服务间的通信和协作。

consul">2. 什么是 consul

Consul 是一种开源的服务发现和配置管理工具,由 HashiCorp 开发。它提供了一系列功能,包括服务注册、服务发现、健康检查、KV存储等,旨在简化构建和管理分布式系统的过程。

① 服务注册与发现:Consul 允许服务实例向 Consul 注册其信息,包括服务名称、网络位置(IP地址和端口号)、健康状态等。其他服务或客户端可以通过 Consul 查询服务注册中心,动态地发现和连接到需要的服务,从而实现服务间的通信。

② 健康检查:Consul 可以定期对服务实例进行健康检查,以确保服务的可用性。如果一个服务实例不健康,Consul 会将其标记为不可用,同时通知其他服务实例进行相应的调整,保证系统的稳定性。

③ KV 存储:Consul 提供了一个分布式的键值存储系统,允许用户存储和检索配置信息、应用程序状态等。这个功能对于动态配置和共享状态在分布式系统中是非常有用的。

④ 多数据中心支持:Consul 支持多数据中心部署,可以轻松地在不同地理位置的数据中心中管理和发现服务,提高系统的可用性和容错性。

3. 服务架构

3.1 传统架构

在 upstream 块中,需要指定后端服务器的 IP 地址和端口号,即 ip:port;在proxy_pass指令中,需要指定转发请求的目标;

当需要添加新的后端服务器时,需要修改代理端配置文件,且需要重启服务才可以生效,有一定的局限性。

consul%20%E6%9E%B6%E6%9E%84" style="background-color:transparent;">3.2 consul 架构

后端服务 A-N 可以把当前自己的网络位置注册到服务发现模块,服务发现就以 K-V 的方式记录下来,K 一般是服务名,V 就是 ip:port。服务发现模块定时的进行健康检查,轮询查看这些后端服务能不能访问的了。前端在调用后端服务 A-N 的时候,会先询问服务发现模块后端服务的网络位置,然后再调用它们的服务。 

4. 关键特性

  • 服务注册与发现:consul通过DNS或者HTTP接口使服务注册和服务发现变的很容易,一些外部服务,例如saas提供的也可以一样注册;
  • 健康检查:健康检测使consul可以快速的告警在集群中的操作。和服务发现的集成,可以防止服务转发到故障的服务上面;
  • Key/Value存储:一个用来存储动态配置的系统。提供简单的HTTP接口,可以在任何地方操作。
  • 多数据中心:无需复杂的配置,即可支持任意数量的区域。

二、Consul 部署

1. 容器服务更新与发现拓扑图

Consul Template

  • Consul Template守护进程是Consul Template工具的一部分,用于监视Consul中的键值存储(KV)中的变化,并根据这些变化来更新本地的配置文件。它可以在后台运行,并定期检查Consul中的数据,以确保生成的配置文件与最新的配置信息保持同步;
  • 是一个配置文件模板,可以获取注册中心所有的服务发现,然后将服务发现的名称:端口号转发给 Nginx,并且更新 nginx.conf 文件。

Consul Server

  • 作为注册中心,Consul Server 负责维护服务目录,记录当前可用的服务实例及其位置信息;
  • 负责执行健康检查来确保服务的可用性,定期检查服务实例的健康状态,如果某个服务实例出现故障或不可用,Consul会将其标记为不健康,并从服务目录中移除;同时服务实例新增或者恢复,Consul会将其加入到服务目录中;
  • 提供了KV存储,用于存储配置信息、应用程序状态等。这个分布式键值存储可以用于共享配置、动态更新应用程序参数等场景;
  • 支持事件处理机制,可以发布和订阅各种事件,例如服务状态变更、健康检查结果等。

Consul Agent

  • 是一个轻量级的代理程序,用于运行在每个部署了服务的节点上。它负责与Consul集群通信,并执行各种任务,包括服务注册、健康检查、服务发现和处理来自其他节点的RPC请求等。 

Registrator

  • 是一个服务注册器,它是一个独立的进程,运行在容器编排环境中;它的主要作用是监视运行中的服务实例,并将它们注册到服务发现系统中,例如Consul或etcd。通过这种注册,其他服务可以发现并与这些服务进行通信,而无需事先知道它们的位置或IP地址。

2. 部署信息

服务节点ip安装运行服务docker版本
consul 服务器192.168.190.107运行consul服务、nginx服务、consul-template守护进程26.0.2
registrator 服务器192.168.190.108运行registrator容器、运行nginx容器20.10.17
consul 服务器192.168.190.106运行consul服务26.0.2

consul%20%E6%9C%8D%E5%8A%A1%E5%99%A8" style="background-color:transparent;">3. consul 服务器

consul%20%E6%9C%8D%E5%8A%A1" style="background-color:transparent;">3.1 建立 consul 服务

① 二进制包直接安装

[root@consul ~]# mkdir /opt/consul
[root@consul ~]# cd /opt/consul/
[root@consul consul]# ls
consul_0.9.2_linux_amd64.zip       # 准备二进制包
[root@consul consul]# unzip consul_0.9.2_linux_amd64.zip
[root@consul consul]# mv consul /usr/local/bin/

② 设置代理,后台启动 consul 服务端

[root@consul consul]#  consul agent \
> -server \
> -bootstrap \
> -ui \
> -data-dir=/var/lib/consul-data \
> -bind=192.168.190.107 \
> -client=0.0.0.0 \
> -node=consul-server01 &> /var/log/consul.log &
[1] 7694

③ 启动 consul 后默认会监听5个端口

[root@consul consul]# netstat -natp | grep consul
tcp        0      0 192.168.190.107:8300    0.0.0.0:*               LISTEN      37870/consul        
tcp        0      0 192.168.190.107:8301    0.0.0.0:*               LISTEN      37870/consul        
tcp        0      0 192.168.190.107:8302    0.0.0.0:*               LISTEN      37870/consul        
tcp6       0      0 :::8500                 :::*                    LISTEN      37870/consul        
tcp6       0      0 :::8600                 :::*                    LISTEN      37870/consul  
# 8300:replication、leader farwarding的端口
# 8301:lan cossip的端口
# 8302:wan gossip的端口
# 8500:web ui界面的端口
# 8600:使用dns协议查看节点信息的端口

3.2 查看集群信息

① 查看members状态

[root@consul consul]# consul members
Node             Address               Status  Type    Build  Protocol  DC
consul-server01  192.168.190.107:8301  alive   server  0.9.2  2         dc1

② 查看集群状态

[root@consul consul]# consul operator raft list-peers # 获取Consul集群中Raft协议的节点列表
Node             ID                    Address               State   Voter  RaftProtocol
consul-server01  192.168.190.107:8300  192.168.190.107:8300  leader  true   2
[root@consul consul]# consul info | grep leaderleader = trueleader_addr = 192.168.190.107:8300

3.3 通过 http api 获取集群信息

[root@consul consul]# curl 127.0.0.1:8500/v1/status/peers
["192.168.190.107:8300"]
# 查看集群server成员
[root@consul consul]# curl 127.0.0.1:8500/v1/status/leader
"192.168.190.107:8300"
# 集群 server-leader
[root@consul consul]# curl 127.0.0.1:8500/v1/catalog/services
{"consul":[]}
# 注册的所有服务
[root@consul consul]# curl 127.0.0.1:8500/v1/catalog/nginx
# 查看 nginx 服务信息
[root@consul consul]# curl 127.0.0.1:8500/v1/catalog/nodes
[{"ID":"f17caaee-ff27-b4e8-c592-afcdad3a2e47","Node":"consul-server01","Address":"192.168.190.107","Datacenter":"dc1","TaggedAddresses":{"lan":"192.168.190.107","wan":"192.168.190.107"},"Meta":{},"CreateIndex":5,"ModifyIndex":6}]
# 集群节点详细信息

4. registrator 服务器

4.1 安装 Gliderlabs/Registrato

Gliderlabs/Registrator 可检查容器运行状态自动注册,还可注销 docker 容器的服务到服务配置中心。目前支持 Consul、Etcd 和 SkyDNS2。运行一个 Registrator 容器,开启自动发现服务:

[root@registrator ~]# docker run -d \  # 运行Docker容器并将其设置为后台运行
> --name=registrator \                 # 指定名称为"registrator"
> --net=host \                         # 使用主机网络模式
> -v /var/run/docker.sock:/tmp/docker.sock \
# 将主机的Docker守护进程的Unix套接字映射到容器内的/tmp/docker.sock,这样Registrator容器就可以与 Docker守护进程通信
> --restart=always \               # 容器遇到错误或意外退出时自动重启
> gliderlabs/registrator:latest \  # 使用镜像gliderlabs/registrator来运行容器,:latest表示使用最新版本的镜像
> --ip=192.168.190.108 \           # 设置Registrator容器的IP地址为192.168.10.13
> consul://192.168.190.107:8500      # 192.168.190.107:8500是Consul的地址和端口

4.2 测试服务发现功能是否正常

[root@registrator ~]# docker run -itd -p:1080:80 --name nginx-01 -h nginx1 nginx
[root@registrator ~]# docker run -itd -p:1081:80 --name nginx-02 -h nginx2 nginx
[root@registrator ~]# docker run -itd -p:1082:80 --name apache-01 -h apache1 httpd
[root@registrator ~]# docker ps -a
CONTAINER ID   IMAGE                           COMMAND                  CREATED          STATUS          PORTS                                   NAMES
3004e92d23e4   httpd                           "httpd-foreground"       8 seconds ago    Up 7 seconds    0.0.0.0:1082->80/tcp, :::1082->80/tcp   apache-01
108612e81495   nginx                           "/docker-entrypoint.…"   2 minutes ago    Up 2 minutes    0.0.0.0:1081->80/tcp, :::1081->80/tcp   nginx-02
dfbfe87308ed   nginx                           "/docker-entrypoint.…"   2 minutes ago    Up 2 minutes    0.0.0.0:1080->80/tcp, :::1080->80/tcp   nginx-01
53166bf2c442   gliderlabs/registrator:latest   "/bin/registrator --…"   23 minutes ago   Up 23 minutes                                           registrator
# 一个发现服务,两个容器服务

consul%C2%A0">4.3 验证 http 和 nginx 服务是否注册到 consul 

[root@consul consul]# curl 127.0.0.1:8500/v1/catalog/services 
{"consul":[],"httpd":[],"nginx":[]}

consul-template%C2%A0">5. consul-template 

Consul-Template是基于Consul的自动替换配置文件的应用。Consul-Template是一个守护进程,用于实时查询Consul集群信息,并更新文件系统上任意数量的指定模板,生成配置文件。更新完成以后,可以选择运行 shell 命令执行更新操作,重新加载 Nginx。

Consul-Template可以查询Consul中的服务目录、Key、Key-values 等。这种强大的抽象功能和查询语言模板可以使 Consul-Template 特别适合动态的创建配置文件。例如:创建Apache/Nginx Proxy Balancers 、 Haproxy Backends等。

5.1 准备 template nginx 模板文件

consul服务器上操作:

[root@consul consul]# vim /opt/consul/nginx.ctmpl
upstream http_backend {{{range service "nginx"}}server {{.Address}}:{{.Port}};{{end}}
}
# 定义nginx upstream一个模板server {listen 8000;server_name localhost 192.168.190.107;access_log /var/log/nginx/kgc.com-access.log;                                                       index index.html index.php;location / {proxy_set_header HOST $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header Client-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_pass http://http_backend;}
}
# 定义一个server,监听8000端口,反向代理到upstream

5.2 安装配置 nginx 服务

consul 节点安装: 

[root@consul consul]# yum install -y epel-release.noarch
[root@consul consul]# yum install -y nginx
[root@consul consul]# vim /etc/nginx/nginx.conf
http {include             vhost/*.conf;  # 添加虚拟主机目录创建虚拟主机目录:
[root@consul consul]# cd /etc/nginx/
[root@consul nginx]# mkdir vhost
启动nginx服务:
[root@consul nginx]# systemctl start nginx.service

5.3 配置并启动 template

consul 节点操作: 

[root@consul opt]# ls
consul-template_0.19.3_linux_amd64.zip # 准备安装包
[root@consul opt]# unzip consul-template_0.19.3_linux_amd64.zip
[root@consul opt]# mv consul-template /usr/local/bin/在前台启动template服务,启动后不要按ctrl+c中止consul-template进程:
consul-template --consul-addr 192.168.190.107:8500 \
--template "/opt/consul/nginx.ctmpl:/etc/nginx/vhost/fqlnginx.conf:/usr/sbin/nginx -s reload" \
--log-level=info另外打开一个终端查看生成配置文件:
[root@consul opt]# cd /etc/nginx/vhost/
[root@consul vhost]# ls
fqlnginx.conf
[root@consul vhost]# cat fqlnginx.conf 
upstream http_backend {server 192.168.190.108:1080;server 192.168.190.108:1081;}server {listen 8000;server_name localhost 192.168.190.107;access_log /var/log/nginx/kgc.com-access.log;index index.html index.php;location / {proxy_set_header HOST $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header Client-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_pass http://http_backend;}
}

5.4 访问 template-nginx

在 registrator 节点操作: 

[root@registrator ~]# docker ps -a
CONTAINER ID   IMAGE                           COMMAND                  CREATED        STATUS        PORTS                                   NAMES
3004e92d23e4   httpd                           "httpd-foreground"       15 hours ago   Up 15 hours   0.0.0.0:1082->80/tcp, :::1082->80/tcp   apache-01
108612e81495   nginx                           "/docker-entrypoint.…"   15 hours ago   Up 15 hours   0.0.0.0:1081->80/tcp, :::1081->80/tcp   nginx-02
dfbfe87308ed   nginx                           "/docker-entrypoint.…"   15 hours ago   Up 15 hours   0.0.0.0:1080->80/tcp, :::1080->80/tcp   nginx-01
53166bf2c442   gliderlabs/registrator:latest   "/bin/registrator --…"   15 hours ago   Up 15 hours                                           registrator[root@registrator ~]# docker exec -it nginx-01 /bin/bash
root@nginx1:/# echo "this is web1 nginx_01" > /usr/share/nginx/html/index.html 
root@nginx1:/# exit
[root@registrator ~]# docker exec -it nginx-02 /bin/bash
root@nginx2:/# echo "this is web2 nginx_02" > /usr/share/nginx/html/index.html
root@nginx2:/# exit

访问 192.168.190.107:8000/ 查看轮询结果:

[root@registrator ~]# curl http://192.168.190.107:8000
this is web1 nginx_01
[root@registrator ~]# curl http://192.168.190.107:8000
this is web2 nginx_02
[root@registrator ~]# curl http://192.168.190.107:8000
this is web1 nginx_01
[root@registrator ~]# curl http://192.168.190.107:8000
this is web2 nginx_02

5.5 增加一个 nginx 容器节点

① 增加一个 nginx 容器节点,测试服务发现及配置更新功能

[root@registrator ~]# docker run -itd -p:1083:80 --name nginx-03 -h nginx3 nginx
# 观察template服务,会从模板更新/usr/local/nginx/conf/vhost/kgc.conf文件内容,并且重载nginx服务

② 查看 cousul 节点 template 更新的配置文件内容

[root@consul vhost]# pwd
/etc/nginx/vhost
[root@consul vhost]# ls
fqlnginx.conf
[root@consul vhost]# cat fqlnginx.conf 
upstream http_backend {server 192.168.190.108:1080;server 192.168.190.108:1081;server 192.168.190.108:1083;  # 新增了一个nginx服务}
……

③ 访问 192.168.190.107:8000/ 查看轮询结果

[root@registrator ~]# docker exec -it nginx-03 /bin/bash
root@nginx3:/# echo "this is web3 nginx_03" > /usr/share/nginx/html/index.html
root@nginx3:/# exit[root@registrator ~]# curl http://192.168.190.107:8000
this is web1 nginx_01
[root@registrator ~]# curl http://192.168.190.107:8000
this is web2 nginx_02
[root@registrator ~]# curl http://192.168.190.107:8000
this is web3 nginx_03
[root@registrator ~]# curl http://192.168.190.107:8000
this is web2 nginx_02
[root@registrator ~]# curl http://192.168.190.107:8000
this is web3 nginx_03
[root@registrator ~]# curl http://192.168.190.107:8000
this is web1 nginx_01

④ 停用 nginx-01 服务,查看 template 更新的配置文件内容,以及轮询结果

[root@registrator ~]# docker stop nginx-01
nginx-01
[root@registrator ~]# docker ps
CONTAINER ID   IMAGE                           COMMAND                  CREATED         STATUS         PORTS                                   NAMES
a9814459efac   nginx                           "/docker-entrypoint.…"   6 minutes ago   Up 6 minutes   0.0.0.0:1083->80/tcp, :::1083->80/tcp   nginx-03
108612e81495   nginx                           "/docker-entrypoint.…"   15 hours ago    Up 9 minutes   0.0.0.0:1081->80/tcp, :::1081->80/tcp   nginx-02
53166bf2c442   gliderlabs/registrator:latest   "/bin/registrator --…"   15 hours ago    Up 9 minutes                                           registrator[root@consul vhost]# cat fqlnginx.conf 
upstream http_backend {server 192.168.190.108:1081;server 192.168.190.108:1083;}
……[root@registrator ~]# curl http://192.168.190.107:8000
this is web2 nginx_02
[root@registrator ~]# curl http://192.168.190.107:8000
this is web3 nginx_03
[root@registrator ~]# curl http://192.168.190.107:8000
this is web2 nginx_02
[root@registrator ~]# curl http://192.168.190.107:8000
this is web3 nginx_03

consul%20%E5%A4%9A%E8%8A%82%E7%82%B9" style="background-color:transparent;">6. consul 多节点

添加一台 docker 环境的服务器 192.168.190.106/24 加入已有的群集中,实际是为了扩展 consul 集群的规模和容量,以提高系统的可用性和可靠性。

docker%C2%A0">6.1 安装 docker 

安装依赖包:
yum install -y yum-utils device-mapper-persistent-data lvm2 
设置阿里云镜像源:
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo 
安装最新版本:
yum install -y docker-ce docker-ce-cli containerd.io  systemctl start docker.service
systemctl enable docker.service 

consul%20%E7%9B%B8%E5%85%B3%E6%9C%8D%E5%8A%A1%E6%96%87%E4%BB%B6%EF%BC%8C%E5%90%AF%E5%8A%A8%20consul%20%E6%9C%8D%E5%8A%A1">6.2 拷贝 consul 相关服务文件,启动 consul 服务

192.168.190.107:
[root@consul vhost]# scp /usr/local/bin/consul 192.168.190.106:/usr/local/bin/
192.168.190.106:
[root@ha02 ~]# consul agent \
> -server \
> -ui \
> -data-dir=/var/lib/consul-data \
> -bind=192.168.190.106 \           # 指定Consul agent监听的IP地址,用于节点间通信
> -client=0.0.0.0 \
> -node=consul-server02 \           # 指定当前节点的名称为"consul-server02"
> -enable-script-checks=true  \
> -datacenter=dc1  \                # 指定Consul集群所属的数据中心名称为"dc1"
> -join 192.168.190.107 &> /var/log/consul.log &
# 加入已知的Consul节点,这里指定加入IP地址为192.168.190.107的节点
[1] 3171

6.3 查看集群信息

查看members状态:
[root@ha02 ~]# consul members
Node             Address               Status  Type    Build  Protocol  DC
consul-server01  192.168.190.107:8301  alive   server  0.9.2  2         dc1
consul-server02  192.168.190.106:8301  alive   server  0.9.2  2         dc1
查看集群状态:
[root@ha02 ~]# consul operator raft list-peers
Node             ID                    Address               State     Voter  RaftProtocol
consul-server01  192.168.190.107:8300  192.168.190.107:8300  leader    true   2
consul-server02  192.168.190.106:8300  192.168.190.106:8300  follower  true   2
# 192.168.190.106状态为follower

http://www.ppmy.cn/devtools/29829.html

相关文章

【docker】maven 打包docker的插件学习

docker-maven-plugin GitHub地址:https://github.com/spotify/docker-maven-plugin 您可以使用此插件创建一个 Docker 映像,其中包含从 Maven 项目构建的工件。例如,Java 服务的构建过程可以输出运行该服务的 Docker 映像。 该插件是 Spot…

外包干了3个月,技术退步明显。。。。。

先说一下自己的情况,本科生,19年通过校招进入广州某软件公司,干了接近4年的功能测试,今年年初,感觉自己不能够在这样下去了,长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试…

Neo4j v5 中 Cypher 的变化

How Cypher changed in Neo4j v5 Neo4j v5 中 Cypher 的变化 几周前,Neo4j 5 发布了。如果你像我一样,在 Neo4j 4 的后期版本中忽略了所有的弃用警告,你可能需要更新你的 Cypher 查询以适应最新版本的 Neo4j。幸运的是,新的 Cyp…

OpenCV 实现重新映射(53)

返回:OpenCV系列文章目录(持续更新中......) 上一篇:OpenCV 实现霍夫圆变换(52) 下一篇 :OpenCV实现仿射变换(54) 目标 在本教程中,您将学习如何: 一个。使用 OpenCV 函数 cv::remap 实现简…

Redis__事务

文章目录 😊 作者:Lion J 💖 主页: https://blog.csdn.net/weixin_69252724 🎉 主题:Redis__事务 ⏱️ 创作时间:2024年05月02日 ———————————————— 这里写目录标题 文章目…

【再探】设计模式— 工厂方法、单例及原型模式

创建型设计模式是处理对象创建的设计模式,主要特点是“将对象的创建与业务代码分离”。一共有五种:工厂方法模式、单例模式、原型模式、抽象工厂模式及建造者模式。 1 单例模式 需求: 在整个系统中只需要一个实例。管理共享资源&#xff0…

CMake:set与list的字符串操作(六)

1、变量操作 有时候项目中的源文件并不一定都在同一个目录中,但是这些源文件最终却需要一起进行编译来生成最终的可执行文件或者库文件。如果我们通过file命令对这个目录下的源文件进行搜索,最后还需要做一个字符串拼接的操作,关于字符串拼接…

OpenCV 笔记(31):图像锐化算法——拉普拉斯锐化和 USM 锐化

1. 图像锐化和增强 图像锐化是一种突出和加强图像中景物的边缘和轮廓的技术,使图像变得更加清晰。它通过增强图像的高频分量来减少图像中的模糊,增强图像细节边缘和轮廓,增强灰度反差,便于后期对目标的识别和处理。 图像增强是改…