【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,…...
Android多线程学习:线程池(一)
一、概念 线程池:创建并维护一定数量的空闲线程,当有需要执行的任务,就交付给线程池中的一个线程,任务执行结束后,该线程也不会死亡,而是回到线程池中重新变为空闲状态。 线程池优点: 1、重用…...
网络安全(黑客技术)—小白自学笔记
1.网络安全是什么 网络安全可以基于攻击和防御视角来分类,我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术,而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 2.网络安全市场 一、是市场需求量高; 二、则是发展相对成熟入…...
掌握核心技巧就能创建完美的目录!如何在Word中自动创建目录
目录是Word布局的一个重要因素,尤其是在编写较长的文档时。那么,你如何在你的作品中添加目录呢?在这篇文章中,我将分享一些基于Word2016自动创建目录的经验。希望它能或多或少地帮到你。 自动创建目录 1、输入目录文本的名称&am…...
正则表达式中re.match、re.search、re.findall的用法和区别
这位作者的例子写的非常好,记录一下,目前用到的比较多的是findall 正则表达式中re.match、re.search、re.findall的用法和区别_<re.match object; span(0, 270), match<a href"/-CSDN博客...
算法题:买卖股票的最佳时机含手续费(动态规划解法贪心解法-详解)
这道题有两种解法:动态规划 or 贪心算法。 贪心算法的提交结果要比动态规划好一些,总体上动态规划的解法更容易想到。(完整题目附在了最后) 1、动态规划解法 设置两个数,dp[0]表示遍历到股票prices[i]时手里没有股…...
【gcc】RtpTransportControllerSend学习笔记 4:码率分配
本文是woder大神 的文章的学习笔记。 大神的webrtc源码分析(8)-拥塞控制(上)-码率预估 详尽而具体,堪称神作。 gcc保障带宽公平性,预估码率后要分配码率,实现qos效果: webrtc源码分析(9)-拥塞控制(下)-码率分配 是 woder 大神进一步给出的另一篇神作。 本文是对(https://w…...
「专题速递」AR协作、智能NPC、数字人的应用与未来
元宇宙是一个融合了虚拟现实、增强现实、人工智能和云计算等技术的综合概念。它旨在创造一个高度沉浸式的虚拟环境,允许用户在其中交互、创造和共享内容。在元宇宙中,人们可以建立虚拟身份、参与虚拟社交,并享受无限的虚拟体验。 作为互联网大…...
什么是基于意图的网络(IBN)
基于意图的网络是一种网络技术,它根据业务意图(来自网络管理员的服务请求)配置 IT 基础架构,无需任何人工干预,它不断提供关键的网络见解,并不断调整硬件配置以确保满足意图,它将网络从以设备为…...
知识增强语言模型提示 零样本知识图谱问答10.8
知识增强语言模型提示 零样本知识图谱问答 摘要介绍相关工作方法零样本QA的LM提示知识增强的LM提示与知识问题相关的知识检索 摘要 大型语言模型(LLM)能够执行 零样本closed-book问答任务 ,依靠其在预训练期间存储在参数中的内部知识。然而&…...
虚拟现实项目笔记:SDK、Assimp、DirectX Sample Browser、X86和X64
文章目录 SDK是什么Assimp是什么DirectX Sample Browser是什么X86和X64生成解决方案和重新生成解决方案 SDK是什么 SDK是Software Development Kit的英文缩写,意思是软件开发包。 软件开发包中往往包含有多种辅助进行软件开发的内容,包括一些软件开发工…...
网站建设每月工作多少/北京seo收费
本节内容 迭代器&生成器装饰器Json & pickle 数据序列化软件目录结构规范作业:ATM项目开发1.列表生成式,迭代器&生成器 列表生成式 孩子,我现在有个需求,看列表[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],我要求你把列表里的每个值加1&…...
海淀商城网站建设/产品推广软件有哪些
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼gjqzaqmlpfunction Draw(a1,a2,a3,x)t0:0.5:x;y1exp(-a1*t);y2exp(-a2*t);y3exp(-a3*t);plot(t,y1,-bo,t,y2,:r*,t,y3,-.g^);cell_string{1}[\fontsize{14}\leftarrow\ita num2str(a1)];cell_string{2}[\fontsize{14}\leftarrow\it…...
有一台服务器怎么赚钱/聊城seo培训
依赖包:pip install paramiko源码demo:from time import *import paramiko# 定义一个类,表示一台远端linux主机class Linux(object):# 通过IP, 用户名,密码,超时时间初始化一个远程Linux主机def __init__(self, ip, username, pas…...
网站开发完了备案/深圳市企业网站seo营销工具
灵动微MM32F0020搭载M0内核,工作频率可达48兆赫兹的32位MCU, 提供32KB Flash和2KB SRAM。MM32F0020系列单片机适用于各类汽车,工业和消费市场,其典型应用包括充电器、电池管理、散热风扇、烟感、玩具、电机以及8/16位MCU升级替换。 客户在使…...
网站开发web前端工程师/百度推广查询
方法一:参数:(1)add 增加路由 del 删除路由(2)-net 设置到某个网段的路由 gw 出口网关IP地址-host 设置到某台主机的路由 dev 出口网关物理设备名(3)route -n 查看路由表例子:添加路由route add -net 192.168.0.0/24 gw 192.168.0.1ro…...
国外网站备案流程/百度指数查询工具
opencart作为商城系统,而商城系统肯定采用很多图片来装饰网站,那么,图片多就延迟了加载时间。怎么才能提高速度呢?除了开启GZIP压缩和图片本身的大小控制之外,我们还可以利用图片延迟加载!在页脚加入两段JS…...