K8S系列文章之 自动化运维利器 Fabric
Fabric 主要用在应用部署与系统管理等任务的自动化,简单轻量级,提供有丰富的 SSH 扩展接口。在 Fabric 1.x 版本中,它混杂了本地及远程两类功能;但自 Fabric 2.x 版本起,它分离出了独立的 Invoke 库,来处理本地的自动化任务,而 Fabric 则聚焦于远程与网络层面的任务。
为了做到这点,Fabric 主要依赖另一大核心组件 Paramiko,它是基于 SSH 协议的远程控制模块,Fabric 在其基础上封装出了更加友好的接口,可以远程执行 Shell 命令、传输文件、批量操作服务器、身份认证、多种配置与设置代理,等等。
一、Fabric 的版本区分
Fabric 自身存在着 2 个大版本:Fabric 1 和 Fabric 2,而在这个库的基础上,还有两个很容易混淆的相关库:Fabric2 和 Fabric3(注意这里的数字是库名的一部分)。
它们的区分如下:
Fabric 1.x:支持 Python 2.5-2.7,但不支持 Python 3
Fabric 2.x:支持 Python 2.7 与 3.4+,但不兼容 Fabric 1.x 的 fabfile
Fabric2:等同于 Fabric 2.x,为了使不同版本共存(装一个 1.x 旧版本,再装它作为新版本)
Fabric3:一个基于 Fabric 1.x 的 fork(非官方),兼容 Python 2&3,兼容 Fabric1.x 的 fabfile
综上可见,我们推荐使用官方的 Fabric 2.x 系列版本,但同时要注意,某些过时的教程可能是基于早期版本的(或非官方的 Fabric3,也是基于 Fabric 1.x),需要注意识别。
例如,在 Fabric 1.x 系列中这么写导入:from fabric.api import run;在新版本中将报错:“ImportError: No module named api”(PS:可根据是否有 fabric.api 来判断 Fabric 的版本,就像在 Python 中根据 print 语句或 print 函数来判断版本一样)。同时,由于新版本不支持老版本的 fabfile,在使用时就可能报错:“No idea what 'xxx' is!”
Fabric 2 是非兼容性版本,相比于前个版本,它主要改进的点有:
支持 Python 2.7 与 3.4+
线程安全,取消了多进程的并发实现
API 围绕 fabric.connection.Connection 进行了重组
全面修改了命令行解析器,允许在每个任务的基础上使用规则的 GNU/POSIX 风格的标志和选项(不再需要 fab mytask:weird = custom,arg = format)
可以声明前置任务与后置任务
……(官方列了 10几条 [1],本文不一一罗列)
之前介绍过的 invoke,就是在开发 Fabric 2 时被分离出来的,具体的原因可参见 这个回答 [2]。总而言之,在使用 Fabric 时,应该注意版本差异的问题。
二、Fabric 的基本用法
安装PIP
pip是Python包管理工具 可以安装各类软件
yum -y install python-pip
升级PIP
pip install --upgrade pip
检查PIP版本
pip --versionpip 19.3.1 from /usr/lib/python2.7/site-packages/pip (python 2.7)
安装docker compose,自行更改版本号.
pip install -U docker-compose==1.24.1
检查docker compose版本
docker-compose version
安装fabric
1、安装
首先是安装:pip intall fabric ,安装后,可在命令行窗口查看版本信息:
>>> fab -V
Fabric 2.5.0
Paramiko 2.7.1
Invoke 1.4.0
执行“fab -V”,以上结果可看出我安装的是 Fabric 2.5.0 版本,同时可看到它的两个核心依赖库 Paramiko 及 Invoke 的版本信息。
2、一个简单的例子
Fabric 主要用于远程任务,即要对远程服务器进行操作,下面是一个简单的例子:# 可使用任意的文件名
from fabric import Connectionhost_ip = '47.xx.xx.xx' # 服务器地址
user_name = 'root' # 服务器用户名
password = '****' # 服务器密码
cmd = 'date' # shell 命令,查询服务器上的时间con = Connection(host_ip, user_name, connect_kwargs={'password': password})
result = con.run(cmd, hide=True)print(result)
以上代码,通过账号+密码登录到远程服务器,然后执行date命令,查看服务器的时间,执行结果:
Command exited with status 0.
=== stdout ===
Fri Feb 14 15:33:05 CST 2020(no stderr)
现在打印的结果中,除了服务器时间,还有一些无关的信息。这是因为它打印的“result”是一个"fabric.runners.Result"类,我们可以把其中的信息解析出来:
print(result.stdout) # Fri Feb 14 15:33:05 CST 2020
print(result.exited) # 0
print(result.ok) # True
print(result.failed) # False
print(result.command) # date
print(result.connection.host) # 47.xx.xx.xx
上述代码使用了 Connection 类及其 run() 方法,可在连接的服务器上运行 shell 命令。如果需要用管理员权限,则需替换成 sudo() 方法。如果要在本地执行 shell 命令,则需替换成 local() 方法。
除此之外,还有 get()、put() 等方法,详见下文介绍。
3、命令行用法
上例代码可写在任意的 .py 脚本中,然后运行该脚本,或者稍微封装下再导入到其它脚本中使用。
另外,Fabric 还是个命令行工具,可以通过fab命令来执行任务。我们稍微改造一下上例的代码:# 文件名:fabfile.py
from fabric import Connection
from fabric import taskhost_ip = '47.xx.xx.xx' # 服务器地址
user_name = 'root' # 服务器用户名
password = '****' # 服务器密码
cmd = 'date' # shell 命令,查询服务器上的时间@task
def test(c):"""Get date from remote host."""con = Connection(host_ip, user_name, connect_kwargs={'password': password})result = con.run(cmd, hide=True)print(result.stdout) # 只打印时间
解释一下,主要的改动点有:
fabfile.py 文件名:入口代码的脚本名必须用这个名字
@task 装饰器:需要从 fabric 中引入这个装饰器,它是对 invoke 的 @task 装饰器的封装,实际用法跟 invoke 一样(注意:它也需要有上下文参数“c”,但实际上它并没有在代码块中使用,而是用了 Connection 类的实例)
然后,在该脚本同级目录的命令行窗口中,可以查看和执行相应的任务:
>>> fab -l
Available tasks:test Get date from remote host.>>> fab test
Fri Feb 14 16:10:24 CST 2020
fab 是 Invoke 的扩展实现,继承了很多原有功能,所以执行“fab --help”,与之前介绍的“inv --help”相比,你会发现它们的很多参数与解释都是一模一样的。
fab 针对远程服务的场景,添加了几个命令行选项(已标蓝),其中:
--prompt-for-login-password:令程序在命令行中输入 SSH 登录密码(上例在代码中指定了 connect_kwargs.password 参数,若用此选项,可要求在执行时再手工输入密码)
--prompt-for-passphrase:令程序在命令行中输入 SSH 私钥加密文件的路径
-H 或 --hosts:指定要连接的 host 名
-i 或 --identity:指定 SSH 连接所用的私钥文件
-S 或 --ssh-config:指定运行时要加载的 SSH 配置文件
关于 Fabric 的命令行接口,更多内容可查看 文档 [3]。
4、交互式操作
远程服务器上若有交互式提示,要求输入密码或“yes”之类的信息,这就要求 Fabric 能够监听并作出回应。
以下是一个简单示例。引入 invoke 的 Responder,初始化内容是一个正则字符串和回应信息,最后赋值给 watchers 参数:
from invoke import Responder
from fabric import Connection
c = Connection('host')
sudopass = Responder(pattern=r'\[sudo\] password:',response='mypassword\n')
c.run('sudo whoami', pty=True, watchers=[sudopass])
5、传输文件
本地与服务器间的文件传输是常见用法。Fabric 在这方面做了很好的封装,Connection 类中有以下两个方法可用:
get(*args, **kwargs):拉取远端文件到本地文件系统或类文件(file-like)对象
put(*args, **kwargs):推送本地文件或类文件对象到远端文件系统
在已建立连接的情况下,示例:
# (略)
con.get('/opt/123.txt', '123.txt')
con.put('test.txt', '/opt/test.txt')
第一个参数指的是要传输的源文件,第二个参数是要传输的目的地,可以指定成文件名或者文件夹(为空或 None 时,使用默认路径):
# (略)
con.get('/opt/123.txt', '') # 为空时,使用默认路径
con.put('test.txt', '/opt/') # 指定路径 /opt/
get() 方法的默认存储路径是os.getcwd ,而 put() 方法的默认存储路径是 home 目录。
6、服务器批量操作
对于服务器集群的批量操作,最简单的实现方法是用 for 循环,然后逐一建立 connection 和执行操作,类似这样:
for host in ('web1', 'web2', 'mac1'):
result = Connection(host).run('uname -s')
但有时候,这样的方案会存在问题:
如果存在多组不同的服务器集群,需要执行不同操作,那么需要写很多 for 循环
如果想把每组操作的结果聚合起来(例如字典形式,key-主机,value-结果),还得在 for 循环之外添加额外的操作
for 循环是顺序同步执行的,效率太低,而且缺乏异常处理机制(若中间出现异常,会导致跳出后续操作)
对于这些问题,Fabric 提出了 Group 的概念,可将一组主机定义成一个 Group,它的 API 方法跟 Connection 一样,即一个 Group 可简化地视为一个 Connection。
然后,开发者只需要简单地操作这个 Group,最后得到一个结果集即可,减少了自己在异常处理及执行顺序上的工作。
Fabric 提供了一个 fabric.group.Group 基类,并由其派生出两个子类,区别是:
SerialGroup(*hosts, **kwargs):按串行方式执行操作
ThreadingGroup(*hosts, **kwargs):按并发方式执行操作
Group 的类型决定了主机集群的操作方式,我们只需要做出选择即可。然后,它们的执行结果是一个fabric.group.GroupResult类,它是 dict 的子类,存储了每个主机 connection 及其执行结果的对应关系。
>>> from fabric import SerialGroup
>>> results = SerialGroup('web1', 'web2', 'mac1').run('uname -s')
>>> print(results)
<GroupResult: {<Connection 'web1'>: <CommandResult 'uname -s'>,<Connection 'web2'>: <CommandResult 'uname -s'>,<Connection 'mac1'>: <CommandResult 'uname -s'>,
}>
另外,GroupResult 还提供了 failed 与 succeeded 两个属性,可以取出失败/成功的子集。由此,也可以方便地批量进行二次操作。 原文
三、Fabric 的进阶用法
1、身份认证
Fabric 使用 SSH 协议来建立远程会话,它是一种相对安全的基于应用层的加密传输协议。
基本来说,它有两种级别的安全认证方式:
基于口令的身份认证:使用账号与密码来登录远程主机,安全性较低,容易受到“中间人”攻击
基于密钥的身份认证:使用密钥对方式(公钥放服务端,私钥放客户端),不会受到“中间人”攻击,但登录耗时较长
前文在举例时,我们用了第一种方式,即通过指定 connect_kwargs.password 参数,使用口令来登录。
Fabric 当然也支持采用第二种方式,有三种方法来指定私钥文件的路径,优先级如下:
优先查找 connect_kwargs.key_filename 参数,找到则用作私钥
其次查找命令行用法的 --identify 选项
最后默认使用操作系统的 ssh_config 文件中的IdentityFile 的值
如果私钥文件本身还被加密过,则需要使用 connect_kwargs.passphrase 参数。
2、配置文件
Fabric 支持把一些参数项与业务代码分离,即通过配置文件来管理它们,例如前面提到的密码和私钥文件,可写在配置文件中,避免与代码耦合。
Fabric 基本沿用了 Invoke 的配置文件体系(官方文档中列出了 9 层),同时增加了一些跟 SSH 相关的配置项。支持的文件格式有 .yaml、.yml、.json 与 .py(按此次序排优先级),推荐使用 yaml 格式(后缀可简写成 yml)。
其中,比较常用的配置文件有:
系统级的配置文件:/etc/fabric.yml
用户级的配置文件:~/.fabric.yml(Windows 在 C:\Users\xxx 下)
项目级的配置文件:/myproject/fabric.yml
以上文件的优先级递减,由于我本机是 Windows,为了方便,我在用户目录建一个".fabric.yml"文件,内容如下:
# filename:.fabric.ymluser: root
connect_kwargs:password: xxxx
# 若用密钥,则如下
# key_filename:
# - your_key_file
我们把用户名和密码抽离出来了,所以 fabfile 中就可以删掉这些内容:
# 文件名:fabfile.py
from fabric import Connection
from fabric import taskhost_ip = '47.xx.xx.xx' # 服务器地址
cmd = 'date' # shell 命令,查询服务器上的时间@task
def test(c):"""Get date from remote host."""con = Connection(host_ip)result = con.run(cmd, hide=True)print(result.stdout)
然后,在命令行中执行:
>>> fab test
Tue Feb 18 10:33:38 CST 2020
配置文件中还可以设置很多参数,详细可查看 文档 [4]。
3、网络网关
如果远程服务是网络隔离的,无法直接被访问到(处在不同局域网),这时候需要有网关/代理/隧道,这个中间层的机器通常被称为跳板机或堡垒机。
Fabric 中有两种网关解决方案,对应到 OpenSSH 客户端的两种选项:
ProxyJump:简单,开销少,可嵌套
ProxyCommand:开销大,不可嵌套,更灵活
在创建 Fabric 的 Connection 对象时,可通过指定 gateway 参数来应用这两种方案:
ProxyJump 方式就是在一个 Connection 中嵌套一个 Connection 作为前者的网关,后者使用 SSH 协议的direct-tcpip 为前者打开与实际远程主机的连接,而且后者还可以继续嵌套使用自己的网关。
from fabric import Connectionc = Connection('internalhost', gateway=Connection('gatewayhost'))
ProxyCommand 方式是客户端在本地用 ssh 命令(类似“ssh -W %h:%p gatewayhost”),创建一个子进程,该子进程与服务端进行通信,同时它能读取标准输入和输出。
其他参考文档
pip install Fabric # 安装
pip freeze > requirements.txt # 把安装包写入文件中
一个官网例子:
def hello(name='sitin'):print("Hello world %s!" % name)
使用fab执行一下效果如下:
这里面我们需要知道fab是fabric安装的命令行工具,我们主要是通过它进行操作。
我个人平时用的比较多的命令有:
run 远端执行命令
local 本地执行命令
cd 远端切换目录
lcd 本地切换
@task 装饰器声明函数为fab task
简单的脚本我觉得是已经够用了,复杂一点需要更多操作了,详情见后文。
部署步骤
通常情况下,作为一个Python工程师我们发布代码需要做的事儿常见的有以下几点:
- git pull 拉取最新代码,比如master分支(或者develop分支)
- tar 打包最新代码
- rsync增量同步到远端服务器,去掉一些不需要的本地目录
- 备份数据库或者备份代码
- supervisor指定重启远端一个或多个服务,通过交互式指令判断
- sentry查看日志正常与否
除了最后一步,这里面所有的操作我们都在fabfile.py就进行操作了,一般情况下fabfile.py放在项目根目录,当然你放在其他地方也没有什么问题。通过-f进行指定就行。
概要讲了,下面请参看我们的一个实战例子
一个例子
from fabric.api import (with_settings,hosts,cd, # 远端lcd, # 本地切换目录run, # 执行env, ) EST_ENV = '127.0.0.1' TEST_USER = 'test' env.forward_agent = True# 允许本地 SSH 代理连接远程终端时跳转 @hosts(TEST_ENV) # 指定远程操作的机器地址 @with_settings(user=TEST_USER) # 用来临时设定 env 变量,可以等同于 with settings def deploy_test():# 发布测试环境local('git pull --rebase upsgream dev') # local执行本地命令拉取代码到本地,这个可以用CI自动发布,就不用拉取到本地。local('rsync -r . --exclude=tmp/ --exclude=backup/ sitin@yourip:/data/your_project') # 上传代码with cd('/data/your_project'): # 表示所有操作在这个目录下面run('docker-compose pull test') # test镜像名backup_db() # 这里其实就是一个普通备份函数run('docker-compose stop test') # 执行远端命令同local相反run('docker-compose rm -f test')run('docker-compose run --rm test python manage.py migrate') # db同步run('docker-compose up -d test')
在终端执行命令
fab deploy_test # 就能进行发布了测试环境了
fab deploy_product # 如果有就能发布了
通常情况下测试,开发,服务器与线上操作不太一样,我们可以通过上面方式进行操作。除了上面的操作之后,如果我们测试线上完全一直或者多台服务器,可以通过指定不同角色来进行选择服务器的发布。
env.roledefs = { 'test': ['test@yourip'], # 指定多台机器 'dev': ['dev@yourip'], 'prod': ['opt@yourip2'],}def deploy(branch=master): pass
fab -R test(上面定义的角色) deploy -f fabfile.py
deploy这里还可以指定发布哪个分支的代码
这样指定某一个角色的服务器,某一个分支进行发布非常简单方便,对于经常使用的复杂命令操作我们还可以作为缩写命令来进行操作。
相关文章:

K8S系列文章之 自动化运维利器 Fabric
Fabric 主要用在应用部署与系统管理等任务的自动化,简单轻量级,提供有丰富的 SSH 扩展接口。在 Fabric 1.x 版本中,它混杂了本地及远程两类功能;但自 Fabric 2.x 版本起,它分离出了独立的 Invoke 库,来处理…...

flask--->CBV/模板/请求响应/session
CBV 1 cbv写法-1 写个类,继承MethodView-2 在类中写跟请求方式同名的方法-3 注册路由:app.add_url_rule(/home, view_funcHome.as_view(home)) #home是endpoint,就是路由别名2 cbv加装饰器-方式一:class Home(MethodView):decor…...

Go语言基础:运算符、文件操作、接口、Packages、if else、for循环
文章目录 1.运算符2.文件操作3.接口4.Packages5.If else6.For循环 1.运算符 func main() {// 算术运算符a, b : 3, 7c : a bd : a - be : a * bf : a / bg : a % baa--fmt.Println(c, d, e, f, g)// 关系运算符fmt.Println(a b)fmt.Println(a ! b)fmt.Println(a < b)fmt.…...

2308C++学习简单协程文档
调试 用gdb/lldb p __coro_frame p __promise试 Try有三种状态:无状态,有异常,有值. 条件变量 主要区别在简单异步中条件变量面向Lazy协程.在条件变量上阻塞协程时,不会阻塞当前线程.用于多个协程间交互协作.基于协程版条件变量,多个协程可实现典型生产者消费者模型. 通知…...

C++笔记之从数组指针到函数数组指针(使用using name和std::function)
C笔记之从数组指针到函数数组指针(使用using name和std::function) 参考笔记: C之指针探究(三):指针数组和数组指针 C之指针探究(十三):函数指针数组 C之指针探究(二):一级指针和一维数组 C之指针探究(十一):函数名的…...

【数据结构】常见的排序算法
常见的排序算法 常见的排序算法插入排序之直接插入排序时间复杂度特性总结 插入排序之希尔排序时间复杂度 选择排序之直接选择排序特性总结 选择排序之堆排序时间复杂度特性总结 交换排序之冒泡排序特性总结 交换排序之快速排序hoare版本挖坑法双指针法快速排序的优化1…...

CentOS 安装 Jenkins
本文目录 1. 安装 JDK2. 获取 Jenkins 安装包3. 将安装包上传到服务器4. 修改 Jenkins 配置5. 启动 Jenkins6. 打开浏览器访问7. 获取并输入 admin 账户密码8. 跳过插件安装9. 添加管理员账户 1. 安装 JDK Jenkins 需要依赖 JDK,所以先安装 JDK1.8。输入以下命令&a…...

前端如何设置表格边框样式和单元格间距?
聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 实现思路⭐ 代码演示⭐ 注意事项⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅!这个专栏是为那些对Web开发感兴…...

Ubuntu 22.04安装搜狗输入法
Ubuntu 22.04安装搜狗输入法 ubtuntu 22.04安装搜狗输入法 1. 添加中文语言支持2. 安装fcitx输入法框架3. 设置fcitx为系统输入法4. 设置fcitx开机启动,并卸载ibus输入法框架5. 安装搜狗输入法6. 重启电脑,调出搜狗输入法 1. 添加中文语言支持 Setti…...

【C++】初阶 --- 内联函数(inline)
文章目录 🥞内联函数🍟1、C语言实现"宏函数"🍟2、内联函数的概念🍟3、内联函数的特性🍟4、总结 🥞内联函数 🍟1、C语言实现"宏函数" 🥰用C语言先来实现普通的…...

VGGNet剪枝实战:使用VGGNet训练、稀疏训练、剪枝、微调等,剪枝出只有3M的模型
摘要 本文讲解如何实现VGGNet的剪枝操作。剪枝的原理:在BN层网络中加入稀疏因子,训练使得BN层稀疏化,对稀疏训练的后的模型中所有BN层权重进行统计排序,获取指定保留BN层数量即取得排序后权重阈值thres。遍历模型中的BN层权重&am…...

【iOS】GCD深入学习
关于GCD和队列的简单介绍请看:【iOS】GCD学习 本篇主要介绍GCD中的方法。 栅栏方法:dispatch_barrier_async 我们有时候需要异步执行两组操作,而且第一组操作执行完之后,才能开始执行第二组操作,当然操作组里也可以包含一个或者…...

Webpack开启本地服务器;HMR热模块替换;devServer配置;开发与生成环境的区分与配置
目录 1_开启本地服务器1.1_开启本地服务器原因1.2_webpack-dev-server 2_HMR热模块替换2.1_认识2.2_开启HMR2.3_框架的HMR 3_devServer配置3.1_host配置3.2_port、open、compress 4_开发与生成环境4.1_如何区分开发环境4.2_入口文件解析4.3_区分开发和生成环境配置 1_开启本地服…...

opencv 31-图像平滑处理-方框滤波cv2.boxFilter()
方框滤波(Box Filtering)是一种简单的图像平滑处理方法,它主要用于去除图像中的噪声和减少细节,同时保持图像的整体亮度分布。 方框滤波的原理很简单:对于图像中的每个像素,将其周围的一个固定大小的邻域内…...

Kubernetes关于cpu资源分配的设计
kubernetes资源 在K8s中定义Pod中运行容器有两个维度的限制: 资源需求(Requests):即运行Pod的节点必须满足运行Pod的最基本需求才能运行Pod。如 Pod运行至少需要2G内存,1核CPU。(软限制)资源限额(Limits):即运行Pod期间,可能内存使用量会增加,那最多能使用多少内存,这…...

Flink读取mysql数据库(java)
代码如下: package com.weilanaoli.ruge.vlink.flink;import com.ververica.cdc.connectors.mysql.source.MySqlSource; import com.ververica.cdc.connectors.mysql.table.StartupOptions; import com.ververica.cdc.debezium.JsonDebeziumDeserializationSchema; import org…...

小程序学习(五):WXSS模板语法
1.什么是WXSS WXSS是一套样式语言,用于美化WXML的组件样式,类似于网页开发中的CSS 2.WXSS和CSS的关系 WXSS模板样式-rpx 3.什么是rpx尺寸单位 4.rpx的实现原理 5.rpx与px之间的单位换算* WXSS模板样式-样式导入 6.什么是样式导入 使用WXSS提供的import语法,可以导入外联的样式…...

注解 @JsonFormat 与 @DateTimeFormat 的使用
文章目录 JsonFormat (双端互传)DateTimeFormat (前端传后端日期格式转化)情况一 前端是时间组件 <el-date-picker 或其他情况二 前端未设置组件 JsonFormat (双端互传) com.fasterxml.jackson.annotation.JsonFormat; 将字符串的时间转换成Date类型…...

Python实现决策树算法:完整源码逐行解析
决策树是一种常用的机器学习算法,它可以用来解决分类和回归问题。决策树的优点是易于理解和解释,可以处理数值和类别数据,可以处理缺失值和异常值,可以进行特征选择和剪枝等操作。决策树的缺点是容易过拟合,对噪声和不…...

Linux文本三剑客---grep、sed、awk
目录标题 1、grep1.1 命令格式1.2命令功能1.3命令参数1.4grep实战演练 2、sed2.1 认识sed2.2命令格式2.3常用选项options2.4地址定界2.5 编辑命令command2.6用法演示2.6.1常用选项options演示2.6.2地址界定演示2.6.3编辑命令command演示 3、awk3.1认识awk3.2常用命令选项3.3awk…...

局域网VoIP网络电话测试
0. 环境 ubuntu18或者ubuntu22 - SIP服务器 win10 - SIP客户端1 ubuntu18 - SIP客户端2 1. SIP服务器搭建asterisk 1.0 环境 虚拟机ubuntu18 或者ubuntu22 1.1 直接安装 sudo apt-get install asterisk 1.2 配置用户信息 分为两个部分,第一部分是修改genera…...

el-table 去掉边框(修改颜色)
原始: 去掉表格的border属性,每一行下面还会有一条线,并且不能再拖拽表头 为了满足在隐藏表格边框的情况下还能拖动表头,修改相关css即可,如下代码 <style lang"less"> .table {//避免单元格之间出现白…...

redis与MongoDB的区别
1.Redis与MongoDB的概念 1.1 MongoDB MongoDB 是由C语言编写的,是一个基于分布式文件存储的开源数据库系统。 在高负载的情况下,添加更多的节点,可以保证服务器性能。 MongoDB 旨在为WEB应用提供可扩展的高性能数据存储解决方案。 MongoDB …...

CSS设置高度
要设置 article.content 的恰当高度,您可以使用 CSS 来控制元素的外观。有几种方法可以设置元素的高度,具体取决于你的需求和布局。 以下是几种常见的方法: 1. 固定高度:你可以直接为 article.content 设置一个固定的高度值&…...

开源免费用|Apache Doris 2.0 推出跨集群数据复制功能
随着企业业务的发展,系统架构趋于复杂、数据规模不断增大,数据分布存储在不同的地域、数据中心或云平台上的现象越发普遍,如何保证数据的可靠性和在线服务的连续性成为人们关注的重点。在此基础上,跨集群复制(Cross-Cl…...

【docker】docker-compose服务编排
目录 一、服务编排概念二、docker compose2.1 定义2.2 使用步骤2.3 docker-compose安装2.4 docker-compose卸载 三、编排示例 一、服务编排概念 1.微服务架构的应用系统中一般包含若干个微服务,每个微服务一般都会部署多个实例,如果每个微服务都要手动启…...

EdgeBox_tx1_A200 PyTorch v1.9.0 环境部署
大家好,我是虎哥,今天远程帮助几个小伙伴在A200 控制器上安装PyTorch v1.9.0 torchvision v0.10.0,中间也是经历了很多波折,当然,大部分是网络问题和版本适配问题,所以完事后,将自己完整可用的过…...

【雕爷学编程】MicroPython动手做(33)——物联网之天气预报
天气(自然现象) 是指某一个地区距离地表较近的大气层在短时间内的具体状态。而天气现象则是指发生在大气中的各种自然现象,即某瞬时内大气中各种气象要素(如气温、气压、湿度、风、云、雾、雨、闪、雪、霜、雷、雹、霾等ÿ…...

分库分表之基于Shardingjdbc+docker+mysql主从架构实现读写分离 (三)
本篇主要说明: 1. 因为这个mysql版本是8.0,所以当其中一台mysql节点挂掉之后,主从同步,甚至双向数据同步都失效了,所以本篇主要记录下当其中的节点挂掉之后如何再次生效。另外推荐大家使用mysql5.7的版本,这…...

探秘企业DevOps一体化平台建设终极形态丨IDCF
笔者从事为企业提供研发效能改进解决方案相关工作十几年,为国内上百家企业提供过DevOps咨询及解决方案落地解决方案,涉及行业包括:金融、通信、制造、互联网、快销等多种行业。 DevOps的核心是研发效能改进,效能的提升离不开强大…...