k8s运行容器之deployment(三)
deployment
我们已经知道k8s是通过各种controller来管理pod的生命周期。为了满足不同业务场景,k8s开发了Deployment、ReplicaSet、DaemonSet、StatefuleSet、Job 等多种 Controller。我们首先学习最常用的 Deployment。
运行一个deployment
- [root@ken ~]# kubectl run httpd-ken1--generator=run-pod/v1 --image=httpd --replicas=2
下面详细分析 Kubernetes 都做了些什么工作。
- [root@ken ~]# kubectl get deployment
- NAME READY UP-TO-DATE AVAILABLE AGE
- httpd-ken 2/2 2 2 35m
kubectl get deplouyment命令可以查看 httpd-ken 的状态,输出显示两个副本正常运行。
接下来我们用 kubectl describe deployment 了解更详细的信息。
- [root@ken ~]# kubectl describe deployment httpd-ken
- Name: httpd-ken
- Namespace: default
- CreationTimestamp: Tue, 29 Jan 2019 15:27:40 +0800
- Labels: run=httpd-ken
- Annotations: deployment.kubernetes.io/revision: 1
- Selector: run=httpd-ken
- Replicas: 2 desired | 2 updated | 2 total | 2 available | 0 unavailable
- StrategyType: RollingUpdate
- MinReadySeconds: 0
- RollingUpdateStrategy: 25% max unavailable, 25% max surge
- Pod Template:
- Labels: run=httpd-ken
- Containers:
- httpd-ken:
- Image: httpd
- Port: <none>
- Host Port: <none>
- Environment: <none>
- Mounts: <none>
- Volumes: <none>
- Conditions:
- Type Status Reason
- ---- ------ ------
- Available True MinimumReplicasAvailable
- Progressing True NewReplicaSetAvailable
- OldReplicaSets: <none>
- NewReplicaSet: httpd-ken-5c949b96f (2/2 replicas created)
- Events:
- Type Reason Age From Message
- ---- ------ ---- ---- -------
- Normal ScalingReplicaSet 18m deployment-controller Scaled up replica set httpd-ken-5c949b96f to 2
大部分内容都是自解释的,我们重点看最下面部分。这里告诉我们创建了一个 ReplicaSet httpd-ken-5c949b96,Events 是 Deployment 的日志,记录了 ReplicaSet 的启动过程。
通过上面的分析,也验证了 Deployment 通过 ReplicaSet 来管理 Pod 的事实。接着我们将注意力切换到 httpd-ken-5c949b96,执行 kubectl describe replicaset:
- [root@ken ~]# kubectl get replicaset
- NAME DESIRED CURRENT READY AGE
- httpd-ken-5c949b96f 2 2 2 20m
两个副本已经就绪,用 kubectl describe replicaset 查看详细信息:
- [root@ken ~]# kubectl describe replicaset
- Name: httpd-ken-5c949b96f
- Namespace: default
- Selector: pod-template-hash=5c949b96f,run=httpd-ken
- Labels: pod-template-hash=5c949b96f
- run=httpd-ken
- Annotations: deployment.kubernetes.io/desired-replicas: 2
- deployment.kubernetes.io/max-replicas: 3
- deployment.kubernetes.io/revision: 1
- Controlled By: Deployment/httpd-ken
- Replicas: 2 current / 2 desired
- Pods Status: 2 Running / 0 Waiting / 0 Succeeded / 0 Failed
- Pod Template:
- Labels: pod-template-hash=5c949b96f
- run=httpd-ken
- Containers:
- httpd-ken:
- Image: httpd
- Port: <none>
- Host Port: <none>
- Environment: <none>
- Mounts: <none>
- Volumes: <none>
- Events:
- Type Reason Age From Message
- ---- ------ ---- ---- -------
- Normal SuccessfulCreate 20m replicaset-controller Created pod: httpd-ken-5c949b96f-twdsd
- Normal SuccessfulCreate 20m replicaset-controller Created pod: httpd-ken-5c949b96f-9cd52
Controlled By 指明此 ReplicaSet 是由 Deployment httpd-ken 创建。Events 记录了两个副本 Pod 的创建。接着我们来看 Pod,执行 kubectl get pod:
- [root@ken ~]# kubectl get pod
- NAME READY STATUS RESTARTS AGE
- httpd-ken-5c949b96f-9cd52 1/1 Running 0 22m
- httpd-ken-5c949b96f-twdsd 1/1 Running 0 22m
两个副本 Pod 都处于 Running 状态,用 kubectl describe pod 查看更详细的信息:
- root@ken ~]# kubectl describe pod
- Name: httpd-ken-5c949b96f-9cd52
- Namespace: default
- Priority: 0
- PriorityClassName: <none>
- Node: host1/172.20.10.7
- Start Time: Tue, 29 Jan 2019 15:46:45 +0800
- Labels: pod-template-hash=5c949b96f
- run=httpd-ken
- Annotations: <none>
- Status: Running
- IP: 10.244.1.3
- Controlled By: ReplicaSet/httpd-ken-5c949b96f
- Containers:
- httpd-ken:
- Container ID: docker://e59bda9941a16f20027c89a0d8fa8e17797b517f6f5461e905c0d29b57369dde
- Image: httpd
- Image ID: docker-pullable://httpd@sha256:44daa8e932a32ab6e50636d769ca9a60ad412124653707e5ed59c0209c72f9b3
- Port: <none>
- Host Port: <none>
- State: Running
- Started: Tue, 29 Jan 2019 15:47:10 +0800
- Ready: True
- Restart Count: 0
- Environment: <none>
- Mounts:
- /var/run/secrets/kubernetes.io/serviceaccount from default-token-vb7lm (ro)
- Conditions:
- Type Status
- Initialized True
- Ready True
- ContainersReady True
- PodScheduled True
- Volumes:
- default-token-vb7lm:
- Type: Secret (a volume populated by a Secret)
- SecretName: default-token-vb7lm
- Optional: false
- QoS Class: BestEffort
- Node-Selectors: <none>
- Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s
- node.kubernetes.io/unreachable:NoExecute for 300s
- Events:
- Type Reason Age From Message
- ---- ------ ---- ---- -------
- Normal Scheduled 23m default-scheduler Successfully assigned default/httpd-ken-5c949b96f-9cd52 to host1
- Normal Pulling 23m kubelet, host1 pulling image "httpd"
- Normal Pulled 22m kubelet, host1 Successfully pulled image "httpd"
- Normal Created 22m kubelet, host1 Created container
- Normal Started 22m kubelet, host1 Started container
Controlled By 指明此 Pod 是由 ReplicaSet httpd-ken-5c949b96f创建。Events 记录了 Pod 的启动过程。如果操作失败(比如 image 不存在),也能在这里查看到原因。
总结一下这个过程:
用户通过 kubectl 创建 Deployment。
Deployment 创建 ReplicaSet。
ReplicaSet 创建 Pod
也可以看出,对象的命名方式是:子对象的名字 = 父对象名字 + 随机字符串或数字。
命令vs配置文件
k8s支持两种创建资源的方式:
1.用 kubectl 命令直接创建,比如:
kubectl run nginx-deployment –image=nginx:1.7.9 –replicas=2
在命令行中通过参数指定资源的属性。
2. 通过配置文件和 kubectl apply 创建,要完成前面同样的工作,可执行命令:
kubectl apply -f nginx.yml
nginx.yml 的内容为:
资源的属性写在配置文件中,文件格式为 YAML。
下面对这两种方式进行比较。
基于命令的方式:
简单直观快捷,上手快。
适合临时测试或实验。
基于配置文件的方式:
配置文件描述了 What,即应用最终要达到的状态。
配置文件提供了创建资源的模板,能够重复部署。
可以像管理代码一样管理部署。
适合正式的、跨环境的、规模化部署。
这种方式要求熟悉配置文件的语法,有一定难度。
后面我们都将采用配置文件的方式,大家需要尽快熟悉和掌握。
kubectl apply 不但能够创建 Kubernetes 资源,也能对资源进行更新,非常方便。不过 Kubernets 还提供了几个类似的命令,例如 kubectl create、kubectl replace、kubectl edit 和 kubectl patch。
为避免造成不必要的困扰,我们会尽量只使用 kubectl apply,
此命令已经能够应对超过 90% 的场景,事半功倍。
deployment yaml
既然要用 YAML 配置文件部署应用,现在就很有必要了解一下 Deployment 的配置格式,其他 Controller(比如 DaemonSet)非常类似。
① apiVersion 是当前配置格式的版本。
先执行kubectl api-resources找到所有的资源
在执行命令 kubectl explain deploy即可获取到版本和类型信息
② kind 是要创建的资源类型,这里是 Deployment。
③ metadata 是该资源的元数据,name 是必需的元数据项。
④ spec 部分是该 Deployment 的规格说明。
⑤ replicas 指明副本数量,默认为 1。
⑥ template 定义 Pod 的模板,这是配置文件的重要部分。
⑦ metadata 定义 Pod 的元数据,至少要定义一个 label。label 的 key 和 value 可以任意指定。
⑧ spec 描述 Pod 的规格,此部分定义 Pod 中每一个容器的属性,name 和 image 是必需的。
注意:最后name前面加个横线是因为container后面是一个列表
此 nginx.yml 是一个最简单的 Deployment 配置文件,后面我们学习 Kubernetes 各项功能时会逐步丰富这个文件。
执行 kubectl apply -f nginx.yml:
- [root@ken ~]# kubectl apply -f nginx.yml
- deployment.extensions/nginx-deployment created
查看nginx-deployment各种资源
- [root@ken ~]# kubectl get deployment
- NAME READY UP-TO-DATE AVAILABLE AGE
- httpd-ken 2/2 2 2 73m
- nginx-deployment 2/2 2 2 107s
- [root@ken ~]# kubectl get replicaset
- NAME DESIRED CURRENT READY AGE
- httpd-ken-5c949b96f 2 2 2 54m
- nginx-deployment-65998d8886 2 2 2 111s
- [root@ken ~]# kubectl get pod -o wide
- NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
- httpd-ken-5c949b96f-9cd52 1/1 Running 0 54m 10.244.1.3 host1 <none> <none>
- httpd-ken-5c949b96f-twdsd 1/1 Running 0 54m 10.244.2.3 host2 <none> <none>
- nginx-deployment-65998d8886-9qrrv 1/1 Running 0 2m4s 10.244.2.4 host2 <none> <none>
- nginx-deployment-65998d8886-vnbgt 1/1 Running 0 2m4s 10.244.1.4 host1 <none> <none>
Deployment、ReplicaSet、Pod 都已经就绪。如果要删除这些资源,执行 kubectl delete deployment nginx-deployment 或者 kubectl delete -f nginx.yml (编写的nginx.yml文件不会被删除)。
- [root@ken ~]# kubectl delete -f nginx.yml
- deployment.extensions "nginx-deployment" deleted
Scale Up/Down
伸缩(Scale Up/Down)是指在线增加或减少 Pod 的副本数。
Deployment nginx-deployment 初始是两个副本。
- [root@ken ~]# kubectl apply -f nginx.yml
- [root@ken ~]# kubectl get pod -o wide
- NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
- nginx-deployment-65998d8886-5b5rc 1/1 Running 0 84s 10.244.1.5 host1 <none> <none>
- nginx-deployment-65998d8886-tnpcx 1/1 Running 0 84s 10.244.2.5 host2 <none> <none>
k8s-node1 和 k8s-node2 上各跑了一个副本。现在修改 nginx.yml,将副本改成 5 个。
再次执行kubectl apply
- [root@ken ~]# kubectl apply -f nginx.yml
- deployment.extensions/nginx-deployment configured
查看pod
- [root@ken ~]# kubectl get pod -o wide
- NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
- nginx-deployment-65998d8886-4hfgp 1/1 Running 0 3m 10.244.1.7 host1 <none> <none>
- nginx-deployment-65998d8886-5b5rc 1/1 Running 0 5m48s 10.244.1.5 host1 <none> <none>
- nginx-deployment-65998d8886-btrsq 1/1 Running 0 3m 10.244.2.6 host2 <none> <none>
- nginx-deployment-65998d8886-tnpcx 1/1 Running 0 5m48s 10.244.2.5 host2 <none> <none>
- nginx-deployment-65998d8886-x4pbd 1/1 Running 0 3m 10.244.1.6 host1 <none> <none>
三个新副本被创建并调度到 k8s-node1 和 k8s-node2 上。
接下来修改配置文件,将副本数减少为 3 个,重新执行 kubectl apply:
- [root@ken ~]# kubectl apply -f nginx.yml
- deployment.extensions/nginx-deployment configured
- [root@ken ~]# kubectl get pod -o wide
- NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
- nginx-deployment-65998d8886-5b5rc 1/1 Running 0 7m6s 10.244.1.5 host1 <none> <none>
- nginx-deployment-65998d8886-btrsq 1/1 Running 0 4m18s 10.244.2.6 host2 <none> <none>
- nginx-deployment-65998d8886-tnpcx 1/1 Running 0 7m6s 10.244.2.5 host2 <none> <none>
可以看到两个副本被删除,最终保留了 3 个副本。
模拟故障
上面我们有 3 个 nginx 副本分别运行在 k8s-node1 和 k8s-node2 上。现在模拟 k8s-node2 故障,关闭该节点(poweroff)。
首先查看节点
- [root@ken ~]# kubectl get node
- NAME STATUS ROLES AGE VERSION
- host1 Ready <none> 5h25m v1.13.2
- host2 NotReady <none> 5h43m v1.13.2
- ken Ready master 6h18m v1.13.2
发现host2状态为NotReady
等待一段时间,Kubernetes 会检查到 k8s-node2 不可用,将 k8s-node2 上的 Pod 标记为 Terminating状态,并在 k8s-node1 上新创建两个 Pod,维持总副本数为 3。
- [root@ken ~]# kubectl get pod -o wide
- NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
- nginx-deployment-65998d8886-5b5rc 1/1 Running 0 16m 10.244.1.5 host1 <none> <none>
- nginx-deployment-65998d8886-8647d 1/1 Running 0 79s 10.244.1.8 host1 <none> <none>
- nginx-deployment-65998d8886-btrsq 1/1 Terminating 0 13m 10.244.2.6 host2 <none> <none>
- nginx-deployment-65998d8886-qp6jj 1/1 Running 0 79s 10.244.1.9 host1 <none> <none>
- nginx-deployment-65998d8886-tnpcx 1/1 Terminating 0 16m 10.244.2.5 host2 <none> <none>
当 k8s-node2 恢复后, Terminating的 Pod 会被删除,不过已经运行的 Pod 不会重新调度回 k8s-node2。
- [root@ken ~]# kubectl get node
- NAME STATUS ROLES AGE VERSION
- host1 Ready <none> 5h33m v1.13.2
- host2 Ready <none> 5h51m v1.13.2
- ken Ready master 6h26m v1.13.2
- [root@ken ~]# kubectl get pod -o wide
- NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
- nginx-deployment-65998d8886-5b5rc 1/1 Running 0 19m 10.244.1.5 host1 <none> <none>
- nginx-deployment-65998d8886-8647d 1/1 Running 0 4m33s 10.244.1.8 host1 <none> <none>
- nginx-deployment-65998d8886-qp6jj 1/1 Running 0 4m33s 10.244.1.9 host1 <none> <none>
删除 nginx-deployment:
- [root@ken ~]# kubectl delete -f nginx.yml
- deployment.extensions "nginx-deployment" deleted
label 控制 Pod 的位置
默认配置下,Scheduler 会将 Pod 调度到所有可用的 Node。不过有些情况我们希望将 Pod 部署到指定的 Node,比如将有大量磁盘 I/O 的 Pod 部署到配置了 SSD 的 Node;或者 Pod 需要 GPU,需要运行在配置了 GPU 的节点上。
Kubernetes 是通过 label 来实现这个功能的。
label 是 key-value 对,各种资源都可以设置 label,灵活添加各种自定义属性。比如执行如下命令标注 k8s-node1 是配置了 SSD 的节点。
第一步:定义标签
disk为自定义字符串
- [root@ken ~]# kubectl label node host1 disk=ssd
第二步:查看标签
- [root@ken ~]# kubectl get node --show-labels
- NAME STATUS ROLES AGE VERSION LABELS
- host1 Ready <none> 8h v1.13.2 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disk=ssd,kubernetes.io/hostname=host1
- host2 Ready <none> 8h v1.13.2 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=host2
- ken Ready master 8h v1.13.2 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=ken,node-role.kubernetes.io/master=
disk=ssd 已经成功添加到 host1,除了 disk,Node 还有几个 Kubernetes 自己维护的 label。
第三步:配置nginx.yml
有了 disk 这个自定义 label,接下来就可以指定将 Pod 部署到 host1。编辑 nginx.yml:
在 Pod 模板的 spec 里通过 nodeSelector 指定将此 Pod 部署到具有 label disktype=ssd 的 Node 上。
注意:1. nodeSelector需要与containers位置保持一致
2. S必须大写
第四步:部署
部署 Deployment
- [root@ken ~]# kubectl apply -f nginx.yml
- deployment.extensions/nginx-deployment created
第五步:查看 Pod 的运行节点
- [root@ken ~]# kubectl get pod -o wide
- NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
- nginx-deployment-5d8db4598d-2gdmz 0/1 ContainerCreating 0 102s <none> host1 <none> <none>
- nginx-deployment-5d8db4598d-cq55q 0/1 ContainerCreating 0 102s <none> host1 <none> <none>
- nginx-deployment-5d8db4598d-qjh4x 0/1 ContainerCreating 0 102s <none> host1 <none> <none>
全部 3个副本都运行在 host1 上,符合我们的预期。
要删除 label disktype,执行如下命令:
kubectl label node k8s-node1 disktype-
– 即删除。
- [root@ken ~]# kubectl label node host1 disk-
- node/host1 labeled
- [root@ken ~]# kubectl get node --show-labels
- NAME STATUS ROLES AGE VERSION LABELS
- host1 NotReady <none> 8h v1.13.2 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=host1
- host2 Ready <none> 8h v1.13.2 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=host2
- ken Ready master 9h v1.13.2 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=ken,node-role.kubernetes.io/master=
不过此时 Pod 并不会重新部署,依然在 host1 上运行。
- [root@ken ~]# kubectl get pod -o wide
- NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
- nginx-deployment-5d8db4598d-2dbw9 1/1 Running 0 39s 10.244.1.12 host1 <none> <none>
- nginx-deployment-5d8db4598d-4brh5 1/1 Running 0 39s 10.244.1.11 host1 <none> <none>
- nginx-deployment-5d8db4598d-p87mj 1/1 Running 0 39s 10.244.1.13 host1 <none> <none>
除非在 nginx.yml 中删除 nodeSelector 设置,然后通过 kubectl apply 重新部署。
不需要删除之前的deployment,直接部署即可
Kubernetes 自己会删除之前的 Pod 并调度和运行新的 Pod。
- [root@ken ~]# kubectl apply -f nginx.yml
- [root@ken ~]# kubectl get pod -o wide
- NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
- nginx-deployment-5d8db4598d-p87mj 0/1 Terminating 0 2m 10.244.1.13 host1 <none> <none>
- nginx-deployment-65998d8886-t5nmv 1/1 Running 0 7s 10.244.2.9 host2 <none> <none>
- nginx-deployment-65998d8886-wz7c2 1/1 Running 0 4s 10.244.2.10 host2 <none> <none>
- nginx-deployment-65998d8886-xdlz4 1/1 Running 0 6s 10.244.1.14 host1 <none> <none>
Continue Reading
k8s运行容器之deployment(三)的更多相关文章
- k8s运行容器之deployment(三)--技术流ken
deployment 我们已经知道k8s是通过各种controller来管理pod的生命周期.为了满足不同业务场景,k8s开发了Deployment.ReplicaSet.DaemonSet.Stat ...
- k8s运行容器之Job(四)--技术流ken
Job 容器按照持续运行的时间可分为两类:服务类容器和工作类容器. 服务类容器通常持续提供服务,需要一直运行,比如 http server,daemon 等.工作类容器则是一次性任务,比如批处理程序, ...
- k8s运行容器之Job(四)
Job 容器按照持续运行的时间可分为两类:服务类容器和工作类容器. 服务类容器通常持续提供服务,需要一直运行,比如 http server,daemon 等.工作类容器则是一次性任务,比如批处理程序, ...
- k8s运行容器之Job应用(6)
容器按照持续运行的时间可分为两类:服务类容器和工作类容器. 服务类容器通常持续提供服务,需要一直运行,比如 http server,daemon 等.工作类容器则是一次性任务,比如批处理程序,完成后容 ...
- k8s工作负载资源之deployment
首先我们要理解:一个应用跑在k8s集群上了,那么这个应用就是一个工作负载(workloads). 在k8s中会用pod的来承载这个应用,那么负责管理这个pod的东西就叫工作负载资源(workload ...
- Java并发编程:并发容器之ConcurrentHashMap(转载)
Java并发编程:并发容器之ConcurrentHashMap(转载) 下面这部分内容转载自: http://www.haogongju.net/art/2350374 JDK5中添加了新的concu ...
- Java并发编程:并发容器之ConcurrentHashMap
转载: Java并发编程:并发容器之ConcurrentHashMap JDK5中添加了新的concurrent包,相对同步容器而言,并发容器通过一些机制改进了并发性能.因为同步容器将所有对容器状态的 ...
- 【转】Java并发编程:并发容器之ConcurrentHashMap
JDK5中添加了新的concurrent包,相对同步容器而言,并发容器通过一些机制改进了并发性能.因为同步容器将所有对容器状态的访问都串行化了,这样保证了线程的安全性,所以这种方法的代价就是严重降低了 ...
- [知识点]C++中STL容器之set
零.STL目录 1.容器之map 2.容器之vector 3.容器之set 一.前言 继上期的vector之后,我们又迎来了另一个类数组的STL容器——set. 二.用途与特性 set,顾名思义,集合 ...
随机推荐
- AMD 5700 XT显卡装ubuntu18.04.* 驱动的问题解决(全)
公司开发需要测试新的 AMD显卡,由于测试服务器上的显卡是英伟达的显卡所以换完后要安装相应的驱动.由于之前装机的同事装的ubuntu是18.04.5 恰巧18.04.5在amd官网上没有相匹配的驱动( ...
- DDD与Repository
Repository已经不是什么新鲜概念了.DDD模型自2004年提出,发展至今已经16年了.但是不少企业却无法实施,其原因也很简单:DDD是基于需求的,而很多并不理解需求:DDD是容易实现的,而很多 ...
- Lambda表达式的几种实现过程
1.无参数+语句(代码块):适用于匿名内部类中方法无参数的情况 private void threadTest(){ //普通写法 new Thread(new Runnable(){ @Overri ...
- 轻松解除官方对博客后台设置页面3段html代码的限制:iframe alert flagcounter etc.的禁用
今天我发现我的flagcounter不能用了 iframe也不能用了,无奈╮(╯_╰)╭ 第一反应是Ctrl U viewsource看看源码出了什么问题 结果竟然是这样, 因为页首和侧边栏的html ...
- Alink漫谈(十九) :源码解析 之 分位点离散化Quantile
Alink漫谈(十九) :源码解析 之 分位点离散化Quantile 目录 Alink漫谈(十九) :源码解析 之 分位点离散化Quantile 0x00 摘要 0x01 背景概念 1.1 离散化 1 ...
- C++置换的玩笑
小蒜头又调皮了.这一次,姐姐的实验报告惨遭毒手. 姐姐的实验报告上原本记录着从 1 到 n 的序列,任意两个数字间用空格间隔.但是“坑姐”的蒜头居然把数字间的空格都给删掉了,整个数字序列变成一个长度为 ...
- Jmeter 常用函数(18)- 详解 __isDefined
如果你想查看更多 Jmeter 常用函数可以在这篇文章找找哦 https://www.cnblogs.com/poloyy/p/13291704.htm 作用 判断 Jmeter 变量是否存在,1 就 ...
- golang安装及vscode编辑器配置
安装Go语言及搭建Go语言开发环境 下载 下载地址:https://studygolang.com/dl 系统选择: 根据不同系统下载安装包: 安装 Windows MAC安装 点开可执行程序 下一步 ...
- Mysql锁【转】
一.概述 数据库锁定机制简单来说,就是数据库为了保证数据的一致性,而使各种共享资源在被并发访问变得有序所设计的一种规则.对于任何一种数据库来说都需要有相应的锁定机制,所以MySQL自然也不能例外. M ...
- jQuery源码分析系列(三)Sizzle选择器引擎-下
选择函数:select() 看到select()函数,if(match.length === 1){}存在的意义是尽量简化执行步骤,避免compile()函数的调用. 简化操作同样根据tokenize ...