【DevOps】搭建你的第一个 Docker 应用栈
搭建你的第一个 Docker 应用栈
- 1.Docker 集群部署
- 2.第一个 Hello World
- 2.1 获取应用栈各节点所需镜像
- 2.2 应用栈容器节点互联
- 2.3 应用栈容器节点启动
- 2.4 应用栈容器节点的配置
- 2.4.1 Redis Master 主数据库容器节点的配置
- 2.4.2 Redis Slave 从数据库容器节点的配置
- 2.4.3 Redis 数据库容器节点的测试
- 2.4.4 APP 容器节点(Django)的配置
- 2.4.5 HAProxy 容器节点的配置
- 2.4.6 应用栈访问测试
- 3.开发、测试和发布一体化
1.Docker 集群部署
Docker 是一个新兴的轻量级虚拟化技术,其易用、跨平台、可移植的特性使其在集群系统的搭建方面有着得天独厚的优势。Docker 能够标准化封装应用程序所需的整个运行时环境,因此基于 Docker,我们可以实现分布式应用集群的快速、准确、自动化部署。
考虑到读者可能是初次接触 Docker 的新手,我们将降低难度,在一台机器上利用 Docker 自带的命令行工具,搭建一个 Docker 应用栈,利用多个容器来组成一个特定的应用。读者可参考应用栈部署的过程,一步一步搭建你的第一个 Docker 应用栈。对于有一定 Docker 使用经验的读者,也可尝试在多台机器上搭建一个真正的 Docker 集群,相信这个过程将对理解 Docker 相关工作原理大有裨益。
2.第一个 Hello World
在 Docker 中,镜像是容器的基础,可以通过镜像来运行容器。本节将举例说明如何有效地利用 Docker Hub 中已有的镜像资源来搭建一个 Docker 应用栈。
在开始搭建过程前,需要对所要搭建的应用栈进行简单的设计和描述:我们将搭建一个包含 6 6 6 个节点的 Docker 应用栈,其中包括一个代理节点、两个 Web 的应用节点、一个主数据库节点及两个从数据库节点。应用栈具体结构如下图所示。
上图中,HAProxy 是负载均衡代理节点;Redis 是非关系型的数据库,它由一个主数据库节点和两个从数据库节点组成;App 是应用,这里是使用 Python 语言、基于 Django 架构设计一个访问数据库的基础 Web 应用。
2.1 获取应用栈各节点所需镜像
在搭建过程中,可以从 Docker Hub 获取现有可用的镜像,在这些镜像的基础上启动容器,按照需求进行修改来实现既定的功能。读者能在此过程中体会到 Docker 的高可移植特性所带来的便利,既提高了应用开发的效率,又降低了开发的难度。
依据上文所描述的应用栈结构,需要从 Docker Hub 获取 HAProxy、Redis 及 Django 的镜像。具体的操作示例如下:
$ sudo docker pull ubuntu
$ sudo docker pull django
$ sudo docker pull haproxy
$ sudo docker pull redis
$ sudo docker images
2.2 应用栈容器节点互联
在搭建第一个 Hello World 应用栈时,将在同一主机下进行 Docker 应用栈搭建。如果是一个真正的分布式架构集群,还需要处理容器的跨主机通信问题,在这里我们将不做介绍。鉴于在同一主机下搭建容器应用栈的环境,只需要完成容器互联来实现容器间的通信即可,这里采用 docker run
命令的 --link
选项建立容器间的互联关系。
这里介绍一下 --link
选项的用法,通过 --link
选项能够进行容器间安全的交互通信,使用格式为 name:alias
,其中 name
为连接容器的名称,alias
为连接的别名,可在一个 docker run
中重复使用该参数。使用示例如下:
$ sudo docker run --link redis:redis --name console ubuntu bash
上例将在 ubuntu
镜像上启动一个容器,并命名为 console
,同时将新启动的 console
容器连接到名为 redis
的容器上。在使用 --link
选项时,连接通过容器名来确定容器,这里建议启动容器时自定义容器名。
通过 --link
选项来建立容器间的连接,不但可以避免容器的 IP 和端口暴露到外网所导致的安全问题,还可以防止容器在重启后 IP 地址变化导致的访问失效,它的原理类似于 DNS 服务器的域名和地址映射。当容器的 IP 地址发生变化时,Docker 将自动维护映射关系中的 IP 地址,文件示例如下:
# 容器启动命令
$ sudo docker run -it --name redis-slave1 --link redis-master:master redis /bin/bash
# 容器内查看 /etc/hosts 文件
# cat /etc/hosts
172.17.0.6 08df6a2cb468
127.0.0.1 localhost
...
172.17.0.5 master
该容器的 /etc/host
文件中记录了名称为 master
的连接信息,其对应 IP 地址为 172.17.0.5
,即 redis-master
容器的 IP 地址。
通过上面的原理可以将 --link
设置理解为一条 IP 地址的单向记录信息,因此在搭建容器应用栈时,需要注意各个容器节点的启动顺序,以及对应的 --link
参数设置。应用栈各节点的连接信息如下:
- 启动
redis-master
容器节点; - 两个
redis-slave
容器节点启动时要连接到redis-master
上; - 两个 APP 容器节点启动时要连接到
redis-master
上; - HAProxy 容器节点启动时要连接到两个 APP 节点上。
综上所述,容器的启动顺序应为:
redis-master
→ redis-slave
→ APP → HAProxy
此外,为了能够从外网访问应用栈,并通过 HAProxy 节点来访问应用栈中的 APP,在启动 HAProxy 容器节点时,需要利用 -p
参数暴露端口给主机,即可通过主机 IP 加暴露的端口从外网访问搭建的应用栈。
2.3 应用栈容器节点启动
之前已经对应用栈的结构进行了分析,获取了所需的镜像资源,同时描述了应用栈中各个容器之间的互连关系,下面开始利用所获得的镜像资源来启动各个容器。应用栈各容器节点的启动命令如下:
# 启动 Redis 容器
$ sudo docker run -it --name redis-master redis /bin/bash
$ sudo docker run -it --name redis-slave1 --link redis-master:master redis /bin/bash
$ sudo docker run -it --name redis-slave2 --link redis-master:master redis /bin/bash
# 启动 Django 容器,即应用
$ sudo docker run -it --name APP1 --link redis-master:db -v ~/Projects/Django/App1:/usr/src/app django /bin/bash
$ sudo docker run -it --name APP2 --link redis-master:db -v ~/Projects/Django/App2:/usr/src/app django /bin/bash
# 启动 HAProxy 容器
$ sudo docker run -it --name HAProxy --link APP1:APP1 --link APP2:APP2 -p 6301:6301 -v ~/Projects/HAProxy:/tmp haproxy /bin/bash
以上容器启动时,为了方便后续与容器进行交互操作,统一设定启动命令为
/bin/bash
,请在启动每个新的容器时都分配一个终端执行。
启动的容器信息可以通过 docker ps
命令查看,示例如下:
$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bcoa13093fd1 haproxy:latest "/bin/bash" 5 days ago Up 21 seconds 0.0.0.0:6301->6301/tcp HAProxy
f92e170d7c3f django:latest "/bin/bash" 5 days ago Up 27 seconds APP2
a1705c6e06a8 django:latest "/bin/bash" 5 days ago Up 34 seconds APP1
7age537b661b redis:latest "/entrypoint.sh /bin" 5 days ago Up 46 seconds 6379/tcp redis-slave2
08df6a2cb468 redis:latest "/entrypoint.sh /bin" 5 days ago Up 57 minutes 6379/tcp redis-slave1
bc8e79b3e66c redis:latest "/entrypoint.sh /bin" 5 days ago Up 58 minutes 6379/tcp redis-master
至此,所有搭建应用栈所需容器的启动工作已经完成。
2.4 应用栈容器节点的配置
在应用栈的各容器节点都启动后,需要对它们进行配置和修改,以便实现特定的功能和通信协作,下面按照容器的启动顺序依次进行解释。
2.4.1 Redis Master 主数据库容器节点的配置
Redis Master 主数据库容器节点启动后,我们需要在容器中添加 Redis 的启动配置文件,以启动 Redis 数据库。
需要说明的是,对于需要在容器中创建文件的情况,由于容器的轻量化设计,其中缺乏相应的文本编辑命令工具,这时可以利用 volume
来实现文件的创建。在容器启动时,利用 -v
参数挂载 volume
,在主机和容器间共享数据,这样就可以直接在主机上创建和编辑相关文件,省去了在容器中安装各类编辑工具的麻烦。
在利用 Redis 镜像启动容器时,镜像中已经集成了 volume
的挂载命令,所以我们需要通过 docker inspect
命令来查看所挂载 volume
的情况。打开一个新的终端,执行如下命令:
$ sudo docker inspect --format "{{ .Volumes }}" bc8e
map[/data:/var/lib/docker/vfs/dir/f01cd2d7cecba683e74def4ae9c3c6bf5952a8cfafddbe19136d916154afee34]
可以发现,该 volume
在主机中的目录为 /var/lib/docker/vfs/dir/fo1cd2d7cecba683e74def4ae9c3c6bf5952a8cfafddbe19136d916154afee34
,在容器中的目录为 /data
。此时,可以进入主机的 volume
目录,利用启动配置文件模板来创建我们的主数据库的启动配置文件,执行命令如下:
# cd /var/lib/docker/vfs/dir/f01cd2d7cecba683e74def4ae9c3c6bf5952a8cfafddbe19136d916154afee34
# cp <your-own-redis-dir>/redis.conf redis.conf
# vim redis.conf
其中,<your-own-redis-dir>
可以是本机上任意与 redis
镜像内 redis
版本兼容的 redis
目录,下同。对于 Redis 的主数据库,需要修改模板文件中的如下几个参数:
daemonize yes
pidfile /var/run/redis.pid
在主机创建好启动配置文件后,切换到容器中的 volume
目录,并复制启动配置文件到 Redis 的执行工作目录,然后启动 Redis 服务器,执行过程如下:
# cd /data
# cp redis.conf /usr/local/bin
# cd /usr/local/bin
# redis-server redis.conf
以上就是配置 Redis Master 容器节点的全部过程,在完成配置另外两个 Redis Slave 节点后,再对应用栈的数据库部分进行整体测试。
2.4.2 Redis Slave 从数据库容器节点的配置
与 Redis Master 容器节点类似,在启动 Redis Slave 容器节点后,需要首先查看 volume
信息。
$ sudo docker inspect --format "{{ .Volumes }}" 08df
map[/data:/var/lib/docker/vfs/dir/f74cebbbod5ceea04e6f47a4750053d9f3a013938abc959d019609c4085cbf4e]
# cd /var/lib/docker/vfs/dir/f74cebbbod5ceea04e6f47a4750053d9f3a013938abc959d019609c4085cbf4e
# cp <your-own-redis-dir>/redis.conf redis.conf
# vim redis.conf
对于 Redis 的从数据库,需要修改如下几个参数:
daemonize yes
pidfile /var/run/redis.pid
slaveof master 6379
需要注意的是,slaveof
参数的使用格式为 slaveof <masterip> <masterport>
,可以看到对于 masterip
使用了 --link
参数设置的连接名来代替实际 IP 地址。通过连接名互连通信时,容器会自动读取它的 host
信息,将连接名转换为实际 IP 地址。
在主机创建好启动配置文件后,切换到容器中的 volume
目录,并复制启动配置文件到 Redis 的执行工作目录,然后启动 Redis 服务器,执行过程如下:
# cd /data
# cp redis.conf /usr/local/bin
# cd /usr/local/bin
# redis-server redis.conf
同理,可以完成对另一个 Redis Slave 容器节点的配置。至此,便完成了所有 Redis 数据库容器节点的配置。
2.4.3 Redis 数据库容器节点的测试
完成 Redis Master 和 Redis Slave 容器节点的配置以及服务器的启动后,可以通过启动 Redis 的客户端程序来测试数据库。
首先,在 Redis Master 容器内,启动 Redis 的客户端程序,并存储一个数据,执行过程如下:
# redis-cli
127.0.0.1:6379> set master bc8e
OK
127.0.0.1:6379> get master
"bc8e"
随后,在两个 Redis Slave 容器内,分别启动 Redis 的客户端程序,查询先前在 Master 数据库中存储的数据,执行过程如下:
# redis-cli
127.0.0.1:6379> get master
"bc8e"
由此可以看到,Master 数据库中的数据已经自动同步到了 Slave 数据库中。至此,应用栈的数据库部分已搭建完成,并通过测试。
2.4.4 APP 容器节点(Django)的配置
Django 容器启动后,需要利用 Django 框架,开发一个简单的 Web 程序。为了访问数据库,需要在容器中安装 Python 语言的 Redis 支持包,执行如下命令:
# pip install redis
安装完成后,进行简单的测试来验证支持包是否安装成功,执行过程如下:
# python
>>> import redis
>>> print(redis._file__)
/usr/local/lib/python3.4/site-packages/redis/__init__.py
如果没有报错,说明已经可以使用 Python 语言来调用 Redis 数据库。接下来,就开始创建 Web 程序。以 APP1 为例,在容器启动时,挂载了 -v ~/Projects/Django/App1:/usr/src/app
的 volume
,方便进入主机的 volume
目录来对新建 APP 进行编辑。
在容器的 volume
目录 /usr/src/app/
下,开始创建 APP,执行过程如下:
# 在容器内
# cd /usr/src/app/
# mkdir dockerweb
# cd dockerweb/
# django-admin.py startproject redisweb
# ls
redisweb
# cd redisweb/
# ls
manage.py redisweb
# python manage.py startapp helloworld
# ls
helloworld manage.py redisweb
在容器内创建 APP 后,切换到主机的 volume
目录 ~/Projects/Django/App1
,进行相应的编辑来配置 APP,执行过程如下:
# 在主机内
$ cd ~/Projects/Django/App1
$ ls
dockerweb
可以看到,在容器内创建的 APP 文件在主机的 volume
目录下同样可见。之后,我们来修改 helloworld
应用的视图文件 views.py
。
$ cd dockerweb/redisweb/helloworld/
$ ls
admin.py __init__.py migrations models.py tests.py views.py
# 利用 root 权限修改 views.py
$ sudo su
# vim views.py
为了简化设计,只要求完成 Redis 数据库信息输出,以及从 Redis 数据库存储和读取数据的结果输出。views.py
文件如下:
from django.shortcuts import render
from django.http import HttpResponse# 创建你自己的 view
import redisdef hello(request):str = redis.__file__str += "<br>"r = redis.Redis(host='db', port=6379, db=0)info = r.info()str += ("Set Hi <br>")r.set('Hi','Helloworld-APP1')str += ("Get Hi: %s <br>" % r.get('Hi'))str += ("Redis Info: <br>")str += ("Key: Info Value")for key in info:str += ("%s: %s <br>" % (key, info[key]))return HttpResponse(str)
需要注意的是,连接 Redis 数据库时,使用了 --link
参数创建 db
连接来代替具体的 IP 地址;同理,对于 APP2,使用相应的 db
连接即可。完成 views.py
文件修改后,接下来修改 redisweb
项目的配置文件 setting.py
,添加新建的 helloworld
应用,执行过程如下:
# cd ../redisweb/
# ls
_init__.py __pycache__ settings.py urls.py wsgi.py
# vim setting.py
在 setting.py
文件中的 INSTALLED_APPS
选项下添加 helloworld
,执行过程如下:
# Application definition
INSTALLED_APPS = ('django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','helloworld',
)
最后,修改 redisweb
项目的 URI 模式文件 urls.py
,它将设置访问应用的 URL 模式,并为 URL 模式调用视图函数之间的映射表。执行如下命令:
# vim urls.py
在 urls.py
文件中,引人 helloworld
应用的 hello
视图,并为 hello
视图添加一个 urlpatterns
变量。urls.py
文件内容如下:
from django.conf.urls import patterns, include, url
from django.contrib import admin
from helloworld.views import hellourlpatterns = patterns('',url(r'admin/', include(admin.site.urls)),url(r'helloworld$',hello),
)
在主机下修改完成这几个文件后,需要再次进入容器,在目录 /usr/src/app/dockerweb/redisweb
下完成项目的生成。执行过程如下:
# python manage.py makemigrations
No changes detected
# python manage.py migrate
Operations to perform:Apply all migrations: sessions, contenttypes, admin, auth
Running migrations:Applying contenttypes.0001_initial... OKApplying auth.0001_initial... OKApplying admin.0001_initial... OKApplying sessions.0001_initial... OK
# python manage.py syncdb
Operations to perform:Apply all migrations: admin, auth, sessions, contenttypes
Running migrations:No migrations to apply.You have installed Django's auth system, and don't have any superusers defined.
Would you like to create one now? (yes/no): yes
Username (leave blank to use 'root'): admin
Email address: sel@sel.com
Password:
Password (again):
Superuser created successfully.
至此,所有 APP1 容器的配置已经完成,另一个 APP2 容器配置也是同样的过程,只需要稍作修改即可。配置完成 APP1 和 APP2 容器后,就完成了应用栈的 APP 部分的全部配置。
在启动 APP 的 Web 服务器时,可以指定服务器的端口和 IP 地址。为了通过 HAProxy 容器节点接受外网所有的公共 IP 地址访问,实现均衡负载,需要指定服务器的 IP 地址和端口。对于 APP1 使用 8001
端口,而 APP2 则使用 8002
端口,同时,都使用 0.0.0.0
地址。以 APP1 为例,启动服务器的过程如下:
# python manage.py runserver 0.0.0.0:8001
Performing system checks...
System check identified no issues (0 silenced).
January 20, 2015 - 13:13:37
Django version 1.7.2, using settings 'redisweb.settings'
Starting development server at http://0.0.0.0:8001/
Quit the server with CONTROL-C.
2.4.5 HAProxy 容器节点的配置
在完成数据库和 APP 部分的应用栈部署后,最后部署一个 HAProxy 负载均衡代理的容器节点,所有对应用栈的访问将通过它来实现负载均衡。
首先,利用容器启动时挂载的 volume
将 HAProxy 的启动配置文件复制进容器中,在主机的 volume
目录 ~/Projects/HAProxy
下,执行过程如下:
$ cd ~/Projects/HAProxy
$ vim haproxy.cfg
其中,haproxy.cfg
配置文件的内容如下:
globallog 127.0.0.1 local0 # 日志输出配置,所有日志都记录在本机,通过 local0 输出maxconn 4096 # 最大连接数chroot /usr/local/sbin # 改变当前工作目录daemon # 以后台形式运行 HAProXynbproc 4 # 启动 4 个 HAProxy 实例pidfile /usr/local/sbin/haproxy.pid # pid 文件位置defaultslog 127.0.0.1 local3 # 日志文件的输出定向mode http # {tcp|http|health} 设定启动实例的协议类型option dontlognull # 保证 HAProXy 不记录上级负载均衡发送过来的用于检测状态没有数据的心跳包option redispatch # 当 serverId 对应的服务器挂掉后,强制定向到其他健康的服务器retries 2 # 重试两次连接失败就认为服务器不可用,主要通过后面的 check 检查maxconn 2000 # 最大连接数balance roundrobin # balance 有两个可用选项:roundrobin 和 source,其中,roundrobin 表示# 轮询,而 source 表示 HAProxy 不采用轮询的策略,而是把来自某个 IP 的请求转# 发给一个固定 IP 的后端timeout connect 5000ms # 连接超时时间timeout client 50000ms # 客户端连接超时时间timeout server 50000ms # 服务器端连接超时时间listen redis_proxy 0.0.0.0:6301stats enablestats uri /haproxy-statsserver APP1 APP1:8001 check inter 2000 rise 2 fall 5 #你的均衡节点server APP2 APP2:8002 check inter 2000 rise 2 fall 5
随后,进入到容器的 volume
目录 /tmp
下,将 HAProxy 的启动配置文件复制到 HAProxy 的工作目录中。执行过程如下:
# cd /tmp
# cp haproxy.cfg /usr/local/sbin/
# cd /usr/local/sbin/
# ls
haproxy haproxy-systemd-wrapper haproxy.cfg
接下来利用该配置文件来启动 HAProxy 代理,执行如下命令:
# haproxy -f haproxy.cfg
需要注意的是,如果修改了配置文件的内容,需要先结束所有的 HAProxy 进程,并重新启动代理。可以使用 killall
命令来结束进程,如果镜像中没有安装该命令,则需要先安装 psmisc
包,执行如下命令:
# apt-get install psmisc
# killall haproxy
至此,完成了 HAProxy 容器节点的全部部署,同时也完成了整个 Docker 应用栈的部署。
2.4.6 应用栈访问测试
整个应用栈部署完成后,就可以进行访问测试。参考应用栈搭建时的结构图可知,整个应用栈群的访问是通过 HAProxy 代理节点来进行的。在 HAProxy 容器节点启动时,通过 -p 6301:6301
参数,映射了容器访问的端口到主机上,因此可以在其他主机上,通过本地主机的 IP 地址和端口来访问搭建好的应用栈。
在应用栈启动后,先在本地主机上进行测试。在浏览器中访问 http:/172.17.0.9:6301/helloworld
可以查看 APP1 或 APP2 的页面内容,如下图所示,具体访问到的 APP 容器节点会由 HAProxy 代理进行均衡分配。同时,可以访问 http://172.17.0.9:6301/haproxy-stats
来查看 HAProxy 的后台管理页面。其中,172.17.0.9
为 HAProxy 容器的 IP 地址。
本地测试通过后,尝试在其他主机上通过应用栈入口主机的 IP 地址和暴露的 6301
端口来访问该应用栈的 APP,即访问http:/10.10.105.87:6301/helloworld
,如下图所示。其中,10.10.105.87
为宿主机的IP地址。
3.开发、测试和发布一体化
从 Docker 集群的搭建过程不难看出,通过 Docker 提供的虚拟化方式,可以快速建立起一套可复用的开发环境,以镜像的形式将开发环境分发给所有开发成员,达到了简化开发环境搭建过程的目的。Docker 的优点在于可以简化 CI
(持续集成)和 CD
(持续交付)的构建流程,让开发者集中精力在应用开发上,同时运维和测试也可以并行进行,并保持整个开发、测试、发布和运维的一体化。
Docker 以镜像和在镜像基础上构建的容器为基础,以容器为开发、测试和发布的单元,将与应用相关的所有组件和环境进行封装,避免了应用在不同平台间迁移时所带来的依赖性问题,确保了应用在生产环境的各阶段达到高度一致的实际效果。
在开发阶段,镜像的使用使得构建开发环境变得简单和统一。随着 Docker 的发展,镜像资源也日益丰富,开发人员可以轻易地找到适合的镜像加以利用。同时,利用 Dockerfile 也可以将一切可代码化的东西进行自动化运行。Docker 最佳实践是将应用分割成大量彼此松散耦合的 Docker 容器,应用的不同组件在不同的容器中同步开发,互不影响,为实现持续集成和持续交付提供了先天的便利。
在测试阶段,可以直接使用开发所构建的镜像进行测试,直接免除了测试环境构建的烦恼,也消除了因为环境不一致所带来的漏洞问题。
在部署和运维阶段,与以往代码级别的部署不同,利用 Docker 可以进行容器级别的部署,把应用及其依赖环境打包成跨平台、轻量级、可移植的容器来进行部署。
Docker 已经逐渐发展成为一个构建、发布、运行分布式应用的开放平台,以轻量级容器为核心建立起了一套完整的生态系统,它重新定义了应用开发、测试、交付和部署的过程。在当前云计算飞速发展的背景下,Docker 将引领着云时代进入一个崭新的发展阶段。
相关文章:

【DevOps】搭建你的第一个 Docker 应用栈
搭建你的第一个 Docker 应用栈 1.Docker 集群部署2.第一个 Hello World2.1 获取应用栈各节点所需镜像2.2 应用栈容器节点互联2.3 应用栈容器节点启动2.4 应用栈容器节点的配置2.4.1 Redis Master 主数据库容器节点的配置2.4.2 Redis Slave 从数据库容器节点的配置2.4.3 Redis 数…...

软件测试职业生涯需要编写的全套文档模板,收藏这一篇就够了 ~
作为一名测试工程师,在整个的职业生涯中,会涉及到各种不同类型的文档编写,大体包括如下: 对应文档模板及文档编写视频如下: 一、测试岗位必备的文档 在一个常规的软件测试流程中,会涉及到测试计划、测试方…...
【Kubernetes】Pod——k8s中最重要的对象之一
Pod是什么?如何使用Pod?资源共享和通信Pod 中的存储Pod 联网:跨 Pod 通信 静态 Pod感谢 💖 Pod是什么? Pod是k8s中创建和管理的、最小的可部署的计算单元。它包含一个或多个容器。就像豌豆荚里面包含了多个豌豆一样。…...
vue-cli-service: command not found问题解决
解决方案:重新安装一下: npm install -g vue/cli...
每日一练 | 华为认证真题练习Day117
1、缺省情况下,广播网络上OSPF协议Deadtime是? A. 20s B. 40s C. 10s D. 30s 2、当两台OSPF路由器形成TWO-WAY邻居关系时,LSDB已完成同步,但是SPF算法尚未运行。 A. 对 B. 错 3、以下哪种协议不属于文件传输协? …...

【JVM】垃圾回收(GC)详解
垃圾回收(GC)详解 一. 死亡对象的判断算法1. 引用计数算法2. 可达性分析算法 二. 垃圾回收算法1. 标记-清除算法2. 复制算法3. 标记-整理算法4. 分代算法 三. STW1. 为什么要 STW2. 什么情况下 STW 四. 垃圾收集器1. CMS收集器(老年代收集器&…...

阿里云服务器公网带宽多少钱1M?
阿里云服务器公网带宽计费模式按固定带宽”计费多少钱1M?地域不同带宽价格不同,北京、杭州、深圳等大陆地域价格是23元/Mbps每月,中国香港1M带宽价格是30元一个月,美国硅谷是30元一个月,日本东京1M带宽是25元一个月&am…...
应用DeepSORT实现目标跟踪
在ByteTrack被提出之前,可以说DeepSORT是最好的目标跟踪算法之一。本文,我们就来应用这个算法实现目标跟踪。 DeepSORT的官方网址是https://github.com/nwojke/deep_sort。但在这里,我们不使用官方的代码,而使用第三方代码&#…...
Beyond Compare 4 30天评估到期 解决方法
Beyond Compare 4 用习惯了,突然提示评估到期了,糟心😄 该方法将通过修改注册表,使BeyondCompare 版本4可以恢复到未评估状态,使其可以持续使用30天评估😄。 修改注册表 第一步:打开注册表。 在…...

化妆品用乙基己基甘油全球市场总体规模2023-2029
乙基己基甘油又名辛氧基甘油,分子式 C11H24O3,分子量 204.306,沸点 325℃,密度 0.962,无色液体,涂抹性能适中的润肤剂、保湿剂及润湿剂。它能够在提高配方滋润效果的同时又具有柔滑的肤感。加入在某些膏霜体…...

springboot家政服务管理平台springboot29
大家好✌!我是CZ淡陌。一名专注以理论为基础实战为主的技术博主,将再这里为大家分享优质的实战项目,本人在Java毕业设计领域有多年的经验,陆续会更新更多优质的Java实战项目,希望你能有所收获,少走一些弯路…...

【网络安全】如何保护IP地址?
使用防火墙是保护IP地址的一个重要手段。防火墙可以监控和过滤网络流量,并阻止未经授权的访问。一家网络安全公司的研究显示,超过80%的企业已经部署了防火墙来保护他们的网络和IP地址。 除了防火墙,定期更新操作系统和应用程序也是保护IP地址…...

2023年失业了,想学一门技术可以学什么?
有一个朋友,大厂毕业了,原本月薪估计有5w吧,年终奖也不错,所以早早的就买了房生了娃,一直是人生赢家的姿态。 但是今年突然就被毕业了,比起房货还有个几百万没还来说,他最想不通的是自己的价值…...

MySQL-MVCC(Multi-Version Concurrency Control)
MySQL-MVCC(Multi-Version Concurrency Control) MVCC(多版本并发控制):为了解决数据库并发读写和数据一致性的问题,是一种思想,可以有多种实现方式。 核心思想:写入时创建行的新版…...

ArcGIS中的镶嵌数据集与接缝线
此处介绍一种简单方法,根据生成的轮廓线来做镶嵌数据集的拼接。 一、注意修改相邻影像的上下重叠。注意修改ZOrder和每幅影像的范围。 二、修改新的镶嵌线并且导出影像文件。 三、还有其他方法和注意事项。...

网络安全工程师自主学习计划表(具体到阶段目标,保姆级安排,就怕你学不会!)
前言 接下来我将给大家分享一份网络安全工程师自学计划指南,全文将从学习路线、学习规划、学习方法三个方向来讲述零基础小白如何通过自学进阶网络安全工程师,全文篇幅有点长,同学们可以先点个收藏,以免日后错过了。 目录 前言…...

Linux 根据 PID 查看进程名称
ps aux | grep PID...

Python二级 每周练习题21
练习一: 提示用户输入两个正整数,编程求出介于这两个数之间的所有质数并打印输出。 显示格式为“*数是质数。” 答案: x(int(input(请输入第一个正整数:)),int(input(请输入第二个正整数:))) #变量x存放input输入的两个整数的元组 Num1min(x) #判断输入数字…...

【算法训练-数组 三】【数组矩阵】螺旋矩阵、旋转图像、搜索二维矩阵
废话不多说,喊一句号子鼓励自己:程序员永不失业,程序员走向架构!本篇Blog的主题是螺旋矩阵,使用【二维数组】这个基本的数据结构来实现 螺旋矩阵【EASY】 二维数组的结构特性入手 题干 解题思路 根据题目示例 mat…...

LED灯实验--汇编
asm-led.S .text .global _start _start: /* 1. led灯的初始化 *//* 1.1 使能GPIOE、DPIOF外设控制器的时钟 */ldr r0, 0x50000A28ldr r1, [r0]orr r1, r1, #(0x3 << 4)str r1, [r0]/* 1.2 设置PE10、PE8、PF10引脚为输出模式 */ldr r0, 0x50006000ldr r1, [r0]bic r1,…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...
conda相比python好处
Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理:…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...

MongoDB学习和应用(高效的非关系型数据库)
一丶 MongoDB简介 对于社交类软件的功能,我们需要对它的功能特点进行分析: 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具: mysql:关系型数据库&am…...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...

【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...

Mysql中select查询语句的执行过程
目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析(Parser) 2.4、执行sql 1. 预处理(Preprocessor) 2. 查询优化器(Optimizer) 3. 执行器…...
JavaScript基础-API 和 Web API
在学习JavaScript的过程中,理解API(应用程序接口)和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能,使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...

AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机
这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机,因为在使用过程中发现 Airsim 对外部监控相机的描述模糊,而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置,最后在源码示例中找到了,所以感…...

STM32HAL库USART源代码解析及应用
STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...