Kubernetes服务pod的健康检测liveness和readiness详解

接下来给大家讲解下在K8S上,我们如果对我们的业务服务进行健康检测。

Health Check、restartPolicy

这里我们再进一步,来聊聊K8s上面服务的健康检测特性。在K8s上,强大的自愈能力是这个容器编排引擎的非常重要的一个特性,自愈的默认实现方式是通过自动重启发生故障的容器,使之恢复正常。除此之外,我们还可以利用Liveness 和 Readiness检测机制来设置更为精细的健康检测指标,从而实现如下的需求:

  • 零停机部署
  • 避免部署无效的服务镜像
  • 更加安全地滚动升级

下面我们先来实践学习下K8s的Healthz Check功能,我们先来学习下K8s默认的健康检测机制:

每个容器启动时都会执行一个进程,此进程是由Dockerfile的CMD 或 ENTRYPOINT来指定,当容器内进程退出时返回状态码为非零,则会认为容器发生了故障,K8s就会根据restartPolicy来重启这个容器,以达到自愈的效果。

下面我们来动手实践下,模拟一个容器发生故障时的场景 :

# 先来生成一个pod的yaml配置文件,并对其进行相应修改
# kubectl run busybox --image=busybox --dry-run=client -o yaml > testHealthz.yaml
# vim testHealthz.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: busybox
name: busybox
spec:
containers:
- image: busybox
name: busybox
resources: {}
args:
- /bin/sh
- -c
- sleep 10; exit 1 # 并添加pod运行指定脚本命令,模拟容器启动10秒后发生故障,退出状态码为1
dnsPolicy: ClusterFirst
restartPolicy: OnFailure # 将默认的Always修改为OnFailure
status: {}
重启策略 说明
Always 当容器失效时,由kubelet自动重启该容器
OnFailure 当容器终止运行且退出码不为0时,由kubelet自动重启该容器
Never 不论容器运行状态如何,kubelet都不会重启该容器

执行配置创建pod

# kubectl apply -f testHealthz.yaml
pod/busybox created # 观察几分钟,利用-w 参数来持续监听pod的状态变化
# kubectl get pod -w
NAME READY STATUS RESTARTS AGE
busybox 0/1 ContainerCreating 0 4s
busybox 1/1 Running 0 6s
busybox 0/1 Error 0 16s
busybox 1/1 Running 1 22s
busybox 0/1 Error 1 34s
busybox 0/1 CrashLoopBackOff 1 47s
busybox 1/1 Running 2 63s
busybox 0/1 Error 2 73s
busybox 0/1 CrashLoopBackOff 2 86s
busybox 1/1 Running 3 109s
busybox 0/1 Error 3 2m
busybox 0/1 CrashLoopBackOff 3 2m15s
busybox 1/1 Running 4 3m2s
busybox 0/1 Error 4 3m12s
busybox 0/1 CrashLoopBackOff 4 3m23s
busybox 1/1 Running 5 4m52s
busybox 0/1 Error 5 5m2s
busybox 0/1 CrashLoopBackOff 5 5m14s 上面可以看到这个测试pod被重启了5次,然而服务始终正常不了,就会保持在CrashLoopBackOff了,等待运维人员来进行下一步错误排查
注:kubelet会以指数级的退避延迟(10s,20s,40s等)重新启动它们,上限为5分钟
这里我们是人为模拟服务故障来进行的测试,在实际生产工作中,对于业务服务,我们如何利用这种重启容器来恢复的机制来配置业务服务呢,答案是`liveness`检测

Liveness

Liveness检测让我们可以自定义条件来判断容器是否健康,如果检测失败,则K8s会重启容器,我们来个例子实践下,准备如下yaml配置并保存为liveness.yaml:

apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness
spec:
restartPolicy: OnFailure
containers:
- name: liveness
image: busybox
args:
- /bin/sh
- -c
- touch /tmp/healthy; sleep 30; rm -f /tmp/healthy; sleep 600
livenessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 10 # 容器启动 10 秒之后开始检测
periodSeconds: 5 # 每隔 5 秒再检测一次

启动进程首先创建文件 /tmp/healthy,30 秒后删除,在我们的设定中,如果 /tmp/healthy 文件存在,则认为容器处于正常状态,反正则发生故障。

livenessProbe 部分定义如何执行 Liveness 检测:

检测的方法是:通过 cat 命令检查 /tmp/healthy 文件是否存在。如果命令执行成功,返回值为零,K8s 则认为本次 Liveness 检测成功;如果命令返回值非零,本次 Liveness 检测失败。

initialDelaySeconds: 10 指定容器启动 10 之后开始执行 Liveness 检测,我们一般会根据应用启动的准备时间来设置。比如某个应用正常启动要花 30 秒,那么 initialDelaySeconds 的值就应该大于 30。

periodSeconds: 5 指定每 5 秒执行一次 Liveness 检测。K8s 如果连续执行 3 次 Liveness 检测均失败,则会杀掉并重启容器。

接着来创建这个Pod:

# kubectl apply -f liveness.yaml
pod/liveness created

从配置文件可知,最开始的 30 秒,/tmp/healthy 存在,cat 命令返回 0,Liveness 检测成功,这段时间 kubectl describe pod liveness 的 Events部分会显示正常的日志

# kubectl describe pod liveness
......
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 53s default-scheduler Successfully assigned default/liveness to 10.0.1.203
Normal Pulling 52s kubelet Pulling image "busybox"
Normal Pulled 43s kubelet Successfully pulled image "busybox"
Normal Created 43s kubelet Created container liveness
Normal Started 42s kubelet Started container liveness

35 秒之后,日志会显示 /tmp/healthy 已经不存在,Liveness 检测失败。再过几十秒,几次检测都失败后,容器会被重启。

Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 3m53s default-scheduler Successfully assigned default/liveness to 10.0.1.203
Normal Pulling 73s (x3 over 3m52s) kubelet Pulling image "busybox"
Normal Pulled 62s (x3 over 3m43s) kubelet Successfully pulled image "busybox"
Normal Created 62s (x3 over 3m43s) kubelet Created container liveness
Normal Started 62s (x3 over 3m42s) kubelet Started container liveness
Warning Unhealthy 18s (x9 over 3m8s) kubelet Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory
Normal Killing 18s (x3 over 2m58s) kubelet Container liveness failed liveness probe, will be restarted

除了 Liveness 检测,Kubernetes Health Check 机制还包括 Readiness 检测。

Readiness

我们可以通过Readiness检测来告诉K8s什么时候可以将pod加入到服务Service的负载均衡池中,对外提供服务,这个在生产场景服务发布新版本时非常重要,当我们上线的新版本发生程序错误时,Readiness会通过检测发布,从而不导入流量到pod内,将服务的故障控制在内部,在生产场景中,建议这个是必加的,Liveness不加都可以,因为有时候我们需要保留服务出错的现场来查询日志,定位问题,告之开发来修复程序。

Readiness 检测的配置语法与 Liveness 检测完全一样,下面是个例子:

apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness
spec:
restartPolicy: OnFailure
containers:
- name: liveness
image: busybox
args:
- /bin/sh
- -c
- touch /tmp/healthy; sleep 30; rm -f /tmp/healthy; sleep 600
readinessProbe: # 这里将livenessProbe换成readinessProbe即可,其它配置都一样
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 10 # 容器启动 10 秒之后开始检测
periodSeconds: 5 # 每隔 5 秒再检测一次

保存上面这个配置为readiness.yaml,并执行它生成pod:

# kubectl apply -f readiness.yaml
pod/liveness created # 观察,在刚开始创建时,文件并没有被删除,所以检测一切正常
# kubectl get pod
NAME READY STATUS RESTARTS AGE
liveness 1/1 Running 0 50s # 然后35秒后,文件被删除,这个时候READY状态就会发生变化,K8s会断开Service到pod的流量
# kubectl describe pod liveness
......
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 56s default-scheduler Successfully assigned default/liveness to 10.0.1.203
Normal Pulling 56s kubelet Pulling image "busybox"
Normal Pulled 40s kubelet Successfully pulled image "busybox"
Normal Created 40s kubelet Created container liveness
Normal Started 40s kubelet Started container liveness
Warning Unhealthy 5s (x2 over 10s) kubelet Readiness probe failed: cat: can't open '/tmp/healthy': No such file or directory # 可以看到pod的流量被断开,这时候即使服务出错,对外界来说也是感知不到的,这时候我们运维人员就可以进行故障排查了
# kubectl get pod
NAME READY STATUS RESTARTS AGE
liveness 0/1 Running 0 61s

下面对 Liveness 检测和 Readiness 检测做个比较:

Liveness 检测和 Readiness 检测是两种 Health Check 机制,如果不特意配置,Kubernetes 将对两种检测采取相同的默认行为,即通过判断容器启动进程的返回值是否为零来判断检测是否成功。

两种检测的配置方法完全一样,支持的配置参数也一样。不同之处在于检测失败后的行为:Liveness 检测是重启容器;Readiness 检测则是将容器设置为不可用,不接收 Service 转发的请求。

Liveness 检测和 Readiness 检测是独立执行的,二者之间没有依赖,所以可以单独使用,也可以同时使用。用 Liveness 检测判断容器是否需要重启以实现自愈;用 Readiness 检测判断容器是否已经准备好对外提供服务。

Health Check 在 业务生产中滚动更新(rolling update)的应用场景

对于运维人员来说,将服务的新项目代码更新上线,确保其稳定运行是一项很关键,且重复性很高的任务,在传统模式下,我们一般是用saltsatck或者ansible等批量管理工具来推送代码到各台服务器上进行更新,那么在K8s上,这个更新流程就被简化了,在后面高阶章节我会讲到CI/CD自动化流程,大致就是开发人员开发好代码上传代码仓库即会触发CI/CD流程,这之间基本无需运维人员的参与。那么在这么高度自动化的流程中,我们运维人员怎么确保服务能稳定上线呢?Health Check里面的Readiness 能发挥很关键的作用,这个其实在上面也有讲过,这里我们再以实例来说一遍,加深印象:

我们准备一个deployment资源的yaml文件

# cat myapp-v1.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
name: mytest
spec:
replicas: 10 # 这里准备10个数量的pod
selector:
matchLabels:
app: mytest
template:
metadata:
labels:
app: mytest
spec:
containers:
- name: mytest
image: busybox
args:
- /bin/sh
- -c
- sleep 10; touch /tmp/healthy; sleep 30000
readinessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 10
periodSeconds: 5

运行这个配置

# kubectl apply -f myapp-v1.yaml --record
deployment.apps/mytest created # 等待一会,可以看到所有pod已正常运行
# kubectl get pod
NAME READY STATUS RESTARTS AGE
mytest-d9f48585b-2lmh2 1/1 Running 0 3m22s
mytest-d9f48585b-5lh9l 1/1 Running 0 3m22s
mytest-d9f48585b-cwb8l 1/1 Running 0 3m22s
mytest-d9f48585b-f6tzc 1/1 Running 0 3m22s
mytest-d9f48585b-hb665 1/1 Running 0 3m22s
mytest-d9f48585b-hmqrw 1/1 Running 0 3m22s
mytest-d9f48585b-jm8bm 1/1 Running 0 3m22s
mytest-d9f48585b-kxm2m 1/1 Running 0 3m22s
mytest-d9f48585b-lqpr9 1/1 Running 0 3m22s
mytest-d9f48585b-pk75z 1/1 Running 0 3m22s

接着我们来准备更新这个服务,并且人为模拟版本故障来进行观察,新准备一个配置myapp-v2.yaml

# cat myapp-v2.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
name: mytest
spec:
strategy:
rollingUpdate:
maxSurge: 35% # 滚动更新的副本总数最大值(以10的基数为例):10 + 10 * 35% = 13.5 --> 14
maxUnavailable: 35% # 可用副本数最大值(默认值两个都是25%): 10 - 10 * 35% = 6.5 --> 7
replicas: 10
selector:
matchLabels:
app: mytest
template:
metadata:
labels:
app: mytest
spec:
containers:
- name: mytest
image: busybox
args:
- /bin/sh
- -c
- sleep 30000 # 可见这里并没有生成/tmp/healthy这个文件,所以下面的检测必然失败
readinessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 10
periodSeconds: 5

很明显这里因为我们更新的这个v2版本里面不会生成/tmp/healthy文件,那么自动是无法通过Readiness 检测的,详情如下:

# kubectl apply -f myapp-v2.yaml --record
deployment.apps/mytest configured # kubectl get deployment mytest
NAME READY UP-TO-DATE AVAILABLE AGE
mytest 7/10 7 7 4m58s
# READY 现在正在运行的只有7个pod
# UP-TO-DATE 表示当前已经完成更新的副本数:即 7 个新副本
# AVAILABLE 表示当前处于 READY 状态的副本数 # kubectl get pod
NAME READY STATUS RESTARTS AGE
mytest-7657789bc7-5hfkc 0/1 Running 0 3m2s
mytest-7657789bc7-6c5lg 0/1 Running 0 3m2s
mytest-7657789bc7-c96t6 0/1 Running 0 3m2s
mytest-7657789bc7-nbz2q 0/1 Running 0 3m2s
mytest-7657789bc7-pt86c 0/1 Running 0 3m2s
mytest-7657789bc7-q57gb 0/1 Running 0 3m2s
mytest-7657789bc7-x77cg 0/1 Running 0 3m2s
mytest-d9f48585b-2bnph 1/1 Running 0 5m4s
mytest-d9f48585b-965t4 1/1 Running 0 5m4s
mytest-d9f48585b-cvq7l 1/1 Running 0 5m4s
mytest-d9f48585b-hvpnq 1/1 Running 0 5m4s
mytest-d9f48585b-k89zs 1/1 Running 0 5m4s
mytest-d9f48585b-wkb4b 1/1 Running 0 5m4s
mytest-d9f48585b-wrkzf 1/1 Running 0 5m4s
# 上面可以看到,由于 Readiness 检测一直没通过,所以新版本的pod都是Not ready状态的,这样就保证了错误的业务代码不会被外界请求到 # kubectl describe deployment mytest
# 下面截取一些这里需要的关键信息
......
Replicas: 10 desired | 7 updated | 14 total | 7 available | 7 unavailable
......
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 5m55s deployment-controller Scaled up replica set mytest-d9f48585b to 10
Normal ScalingReplicaSet 3m53s deployment-controller Scaled up replica set mytest-7657789bc7 to 4 # 启动4个新版本的pod
Normal ScalingReplicaSet 3m53s deployment-controller Scaled down replica set mytest-d9f48585b to 7 # 将旧版本pod数量降至7
Normal ScalingReplicaSet 3m53s deployment-controller Scaled up replica set mytest-7657789bc7 to 7 # 新增3个启动至7个新版本

综合上面的分析,我们很真实的模拟一次K8s上次错误的代码上线流程,所幸的是这里有Health Check的Readiness检测帮我们屏蔽了有错误的副本,不至于被外面的流量请求到,同时保留了大部分旧版本的pod,因此整个服务的业务并没有因这此更新失败而受到影响。

接下来我们详细分析下滚动更新的原理,为什么上面服务新版本创建的pod数量是7个,同时只销毁了3个旧版本的pod呢?

原因就在于这段配置:

我们不显式配置这段的话,默认值均是25%

  strategy:
rollingUpdate:
maxSurge: 35%
maxUnavailable: 35%

滚动更新通过参数maxSurge和maxUnavailable来控制pod副本数量的更新替换。

maxSurge

这个参数控制滚动更新过程中pod副本总数超过设定总副本数量的上限。maxSurge 可以是具体的整数(比如 3),也可以是百分比,向上取整。maxSurge 默认值为 25%

在上面测试的例子里面,pod的总副本数量是10,那么在更新过程中,总副本数量的上限大最值计划公式为:

10 + 10 * 35% = 13.5 --> 14

我们查看下更新deployment的描述信息:

Replicas: 10 desired | 7 updated | 14 total | 7 available | 7 unavailable

旧版本available 的数量7个 + 新版本unavailable`的数量7个 = 总数量 14 total

maxUnavailable

这个参数控制滚动更新过程中不可用的pod副本总数量的值,同样,maxUnavailable 可以是具体的整数(比如 3),也可以是百分百,向下取整。maxUnavailable 默认值为 25%。

在上面测试的例子里面,pod的总副本数量是10,那么要保证正常可用的pod副本数量为:

10 - 10 * 35% = 6.5 --> 7

所以我们在上面查看的描述信息里,7 available 正常可用的pod数量值就为7

maxSurge 值越大,初始创建的新副本数量就越多;maxUnavailable 值越大,初始销毁的旧副本数量就越多。

正常更新理想情况下,我们这次版本发布案例滚动更新的过程是:

  1. 首先创建4个新版本的pod,使副本总数量达到14个
  2. 然后再销毁3个旧版本的pod,使可用的副本数量降为7个
  3. 当这3个旧版本的pod被 成功销毁后,可再创建3个新版本的pod,使总的副本数量保持为14个
  4. 当新版本的pod通过Readiness 检测后,会使可用的pod副本数量增加超过7个
  5. 然后可以继续销毁更多的旧版本的pod,使整体可用的pod数量回到7个
  6. 随着旧版本的pod销毁,使pod副本总数量低于14个,这样就可以继续创建更多的新版本的pod
  7. 这个新增销毁流程会持续地进行,最终所有旧版本的pod会被新版本的pod逐渐替换,整个滚动更新完成

而我们这里的实际情况是在第4步就卡住了,新版本的pod数量无法能过Readiness 检测。上面的描述信息最后面的事件部分的日志也详细说明了这一切:

Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 5m55s deployment-controller Scaled up replica set mytest-d9f48585b to 10
Normal ScalingReplicaSet 3m53s deployment-controller Scaled up replica set mytest-7657789bc7 to 4 # 启动4个新版本的pod
Normal ScalingReplicaSet 3m53s deployment-controller Scaled down replica set mytest-d9f48585b to 7 # 将旧版本pod数量降至7
Normal ScalingReplicaSet 3m53s deployment-controller Scaled up replica set mytest-7657789bc7 to 7 # 新增3个启动至7个新版本

这里按正常的生产处理流程,在获取足够的新版本错误信息提交给开发分析后,我们可以通过kubectl rollout undo 来回滚到上一个正常的服务版本:

# 先查看下要回滚版本号前面的数字,这里为1
# kubectl rollout history deployment mytest
deployment.apps/mytest
REVISION CHANGE-CAUSE
1 kubectl apply --filename=myapp-v1.yaml --record=true
2 kubectl apply --filename=myapp-v2.yaml --record=true # kubectl rollout undo deployment mytest --to-revision=1
deployment.apps/mytest rolled back # kubectl get deployment mytest
NAME READY UP-TO-DATE AVAILABLE AGE
mytest 10/10 10 10 96m # kubectl get pod
NAME READY STATUS RESTARTS AGE
mytest-d9f48585b-2bnph 1/1 Running 0 96m
mytest-d9f48585b-8nvhd 1/1 Running 0 2m13s
mytest-d9f48585b-965t4 1/1 Running 0 96m
mytest-d9f48585b-cvq7l 1/1 Running 0 96m
mytest-d9f48585b-hvpnq 1/1 Running 0 96m
mytest-d9f48585b-k89zs 1/1 Running 0 96m
mytest-d9f48585b-qs5c6 1/1 Running 0 2m13s
mytest-d9f48585b-wkb4b 1/1 Running 0 96m
mytest-d9f48585b-wprlz 1/1 Running 0 2m13s
mytest-d9f48585b-wrkzf 1/1 Running 0 96m

OK,到这里为止,我们真实的模拟了一次有问题的版本发布及回滚,并且可以看到,在这整个过程中,虽然出现了问题,但我们的业务依然是没有受到任何影响的,这就是K8s的魅力所在。

pod小怪战斗(作业)

# 把上面整个更新及回滚的案例,自己再测试一遍,注意观察其中的pod变化,加深理解

Kubernetes服务pod的健康检测liveness和readiness详解的更多相关文章

  1. Kubernetes K8S之固定节点nodeName和nodeSelector调度详解

    Kubernetes K8S之固定节点nodeName和nodeSelector调度详解与示例 主机配置规划 服务器名称(hostname) 系统版本 配置 内网IP 外网IP(模拟) k8s-mas ...

  2. Kubernetes中Pod的健康检查

    本文介绍 Pod 中容器健康检查相关的内容.配置方法以及实验测试,实验环境为 Kubernetes 1.11,搭建方法参考kubeadm安装kubernetes V1.11.1 集群 0. 什么是 C ...

  3. Kubernetes Pod中容器的Liveness、Readiness和Startup探针

    我最新最全的文章都在南瓜慢说 www.pkslow.com,欢迎大家来喝茶! 1 探针的作用 在Kubernetes的容器生命周期管理中,有三种探针,首先要知道,这探针是属于容器的,而不是Pod: 存 ...

  4. Kubernetes K8S之通过helm部署metrics-server与HPA详解

    Kubernetes K8S之通过helm部署metrics-server与 Horizontal Pod Autoscaling (HPA)详解 主机配置规划 服务器名称(hostname) 系统版 ...

  5. Linux/CentOS 服务安装/卸载,开机启动chkconfig命令详解|如何让MySQL、Apache开机启动?

    chkconfig chkconfig在命令行操作时会经常用到.它可以方便地设置和查询不同运行级上的系统服务.这个可要好好掌握,用熟练之后,就可以轻轻松松的管理好你的启动服务了. 注:谨记chkcon ...

  6. mysql服务性能优化 my.cnf my.ini配置说明详解(16G内存)

    sort_buffer_size,join_buffer_size,read_buffer_size参数对应的分配内存也是每个连接独享 这配置已经优化的不错了,如果你的mysql没有什么特殊情况的话, ...

  7. k8s入坑之路(7)kubernetes设计精髓List/Watch机制和Informer模块详解

    1.list-watch是什么 List-watch 是 K8S 统一的异步消息处理机制,保证了消息的实时性,可靠性,顺序性,性能等等,为声明式风格的API 奠定了良好的基础,它是优雅的通信方式,是 ...

  8. nagios系列(五)之nagios图形显示的配置及自定义插件检测密码是否修改详解

    nagios图形显示的配置 在服务端安装相关软件 #1.图形显示管理的依赖库 yum install cairo pango zlib zlib-devel freetype freetype-dev ...

  9. SpringCloud学习系列之二 ----- 服务消费者(Feign)和负载均衡(Ribbon)使用详解

    前言 本篇主要介绍的是SpringCloud中的服务消费者(Feign)和负载均衡(Ribbon)功能的实现以及使用Feign结合Ribbon实现负载均衡. SpringCloud Feign Fei ...

随机推荐

  1. python3 循环位移动

    python3 中  >> 为算术右移位,高位补符号位: <<为左移位,低位补0: 1 # 假如将一个无符号的数据val,长度为N,需要循环移动n位.可以利用下面的公式: 2 ...

  2. python3 虚拟环境 venv

    创建一个虚拟环境: python -m venv test            (test 为创建的虚拟环境目录) 激活虚拟环境: test\Scripts\activate            ...

  3. C语言变量及其生命周期

    变量类型以及作用域和生命周期 变量的作用域 变量的作用域就该变量可以被访问的区间,变量的作用域可以分为以下四种: 进程作用域(全局):在当前进程的任何一个位置都可以访问 函数作用域:当流程转移到函数后 ...

  4. golang 性能优化分析:benchmark 结合 pprof

    前面 2 篇 golang 性能优化分析系列文章: golang 性能优化分析工具 pprof (上) golang 性能优化分析工具 pprof (下) 一.基准测试 benchmark 简介 在 ...

  5. Python - 关于类(self/cls) 以及 多进程通讯的思考

    Python-多进程中关于类以及类实例的一些思考 目录 Python-多进程中关于类以及类实例的一些思考 1. 背景 2. Python 类中的函数 - staticmethod / classmet ...

  6. C#与Python交互方式

    前言: 在平时工作中,需求有多种实现方式:根据不同的需求可以采用不同的编程语言来实现.发挥各种语言的强项 如:Python的强项是:数据分析.人工智能等 .NET 开发桌面程序界面比Python更简单 ...

  7. 为什么要进行系统拆分?如何进行系统拆分?拆分后不用dubbo可以吗?

    分布式系统,我用一句话给你解释一下,实在没时间多唠了,就是原来20万行代码的系统,现在拆分成20个小系统,每个小系统1万行代码.原本代码之间直接就是基于spring调用,现在拆分开来了,20个小系统部 ...

  8. 数栈运维实例:Oracle数据库运维场景下,智能运维如何落地生根?

    从马车到汽车是为了提升运输效率,而随着时代的发展,如今我们又希望用自动驾驶把驾驶员从开车这项体力劳动中解放出来,增加运行效率,同时也可减少交通事故发生率,这也是企业对于智能运维的诉求. 从人工运维到自 ...

  9. scrapy爬虫框架调用百度地图api数据存入数据库

    scrapy安装配置不在本文 提及, 1.在开始爬取之前,必须创建一个新的Scrapy项目.进入自定义的项目目录中,运行下列命令 scrapy startproject mySpider 其中, my ...

  10. Python脚本破解Linux口令(crypt模块)

    环境 Kali Linux ,python版本2.7.13 . 我们利用Linux系统中的 crypt 模块模拟了Linux系统中用户密码的加密,在Windows中是不存在这个库的. 在Linux系统 ...