一、为什么需要Helm?

Kubernetes目前已成为容器编排的事实标准,随着传统架构向微服务容器化架构的转变,从一个巨大的单体的应用切分为多个微服务,每个微服务可独立部署和扩展,实现了敏捷开发和快速部署,但是由于从大一个应用变成了多个微服务,导致服务数大幅增加,对于Kubernetes来说,针对每个服务需要部署如deployment、statufulset、service、pod 等资源文件,而对于一个复杂的应用来说,可能会有很多类似上面的资源文件,其中还有更新或回滚的需求,若要执行,需要修改和维护相关的大量资源文件,这时候,如何针对每个服务涉及到资源集合到一个整体来实现部署、升级和回滚是亟待需要解决的难题,Helm就是在这个背景下诞生的。

二、Helm的简介和使用场景

那么Helm是如何解决上述难题的呢?它其实是将Kubernetes资源(如deployment、statufulset、service、pod) 打包到一个chart中,而chart被打包并推送保存到chart仓库(repo),然后通过chart仓库用来存储和分享chart包。Helm可直接拉取并安装chart包,生成helm维度整体的应用,其应用会包含如deployment、statufulset、service、pod的资源,并支持以一个整体Helm应用的维度来进行版本控制、打包、发布、删除、更新等操作。针对用户来说主要适用如下场景:

1、将常用搭配、标准化的多个资源文件放在同一个chart包中,方便统一的版本控制、安装、部署、升级、回滚和删除

2、可以大大简化了使用Kubernetes部署的难度,降低了用户使用门槛,只需配置参数即可一键部署

三、Helm实践

本次演示Helm的版本号如下:

[root@k8s-master my-second-helm]# helm version
version.BuildInfo{Version:"v3.3.1", GitCommit:"249e5215cde0c3fa72e27eb7a30e8d55c9696144", GitTreeState:"clean", GoVersion:"go1.14.7"}

1、安装

1)制作chart包的形式

Helm 应用的安装既可以从远程的repo进行拉取chart包进行安装,repo中提供了很多官方的chart包,若无个性化的需求,可以类似公开镜像一样进行拉取并安装,若需要单独调整,可以在已有的chart包进行更新再次打包,然后拉取更新后的chart包进行安装,接下来先来实践下后者,我们先新建一个helm的目录,然后在此目录下执行如下命令:

[root@k8s-master helm]# helm create my-second-helm
Creating my-second-helm
[root@k8s-master helm]# ls
my-first-helm my-second-helm
[root@k8s-master helm]# cd my-second-helm/
[root@k8s-master my-second-helm]# ls
charts Chart.yaml templates values.yaml
[root@k8s-master helm]# tree my-second-helm
my-second-helm
├── charts
├── Chart.yaml
├── templates
│   ├── deployment.yaml
│   ├── _helpers.tpl
│   ├── hpa.yaml
│   ├── ingress.yaml
│   ├── NOTES.txt
│   ├── serviceaccount.yaml
│   ├── service.yaml
│   └── tests
│   └── test-connection.yaml
└── values.yaml directories, files

我们在前面的操作中只是指定了这个文件夹的名字my-second-helm,但是在这个文件下默认创建了多个目录和文件,接下里我们一起看下默认的文件中都包含哪些内容,各自充当什么作用,先一起看下Chart.yaml这个文件

[root@k8s-master my-second-helm]# cat Chart.yaml
apiVersion: v2
name: my-second-helm
description: A Helm chart for Kubernetes # A chart can be either an 'application' or a 'library' chart.
#
# Application charts are a collection of templates that can be packaged into versioned archives
# to be deployed.
#
# Library charts provide useful utilities or functions for the chart developer. They're included as
# a dependency of application charts to inject those utilities and functions into the rendering
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
type: application # This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.1. # This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
appVersion: 1.16.

可以看到Chart.yaml这个文件主要是用来对chart进行的描述,声明了当前 Chart 的名称、版本等基本信息,如果我们自己制作的chart有相关的描述都可以写入到文件,这些信息会在该 Chart 被放入仓库后,供用户浏览检索,方便用户了解这个chart。

templates这个目录下,我们看到了大家比较熟悉的资源,我们看下deployment.yaml的构成

[root@k8s-master templates]# cat deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "my-second-helm.fullname" . }}
labels:
{{- include "my-second-helm.labels" . | nindent }}
spec:
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }}
{{- end }}
selector:
matchLabels:
{{- include "my-second-helm.selectorLabels" . | nindent }}
template:
metadata:
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent }}
{{- end }}
labels:
{{- include "my-second-helm.selectorLabels" . | nindent }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent }}
{{- end }}
serviceAccountName: {{ include "my-second-helm.serviceAccountName" . }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent }}
containers:
- name: {{ .Chart.Name }}
securityContext:
{{- toYaml .Values.securityContext | nindent }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort:
protocol: TCP
livenessProbe:
httpGet:
path: /
port: http
readinessProbe:
httpGet:
path: /
port: http
resources:
{{- toYaml .Values.resources | nindent }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent }}
{{- end }}

细心的读者可能发现了,这个kind为deployment的资源与我们平常自己写的有些出入,主要是出现了很多类似{}的内容,如:replicas: {{ .Values.replicaCount }},经常我们是用replicas: 数字的形式,而这里已经换成了变量,而整个文件出现了很多类似的变量,想必读者也猜到了原来helm是通过设置变量来统一管理很多需要输入的值,若有多个文件引用同一个变量,就再也不用同时修改多个文件了,细心的读者可能会发现,即便对K8s不太了解的用户,也可以仅设置变量的值也可以轻松部署应用,岂不可以大大降低部署的难度,确实如此,这就是helm的一个主要的特点,让部署变的简单,特别是常用的标准的配置我们可将其制作成chart一键部署,让我们再回到replicas: {{ .Values.replicaCount }}这个变量上,既然存在变量,那变量的设值在哪里呢? 我们可以看到变量的组成中存在Values,而和我们templates同级别的目录选还存在一个很重要的文件values.yaml,我们看下这个文件里面的内容:

[root@k8s-master my-second-helm]# cat values.yaml
# Default values for my-second-helm.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates. replicaCount: image:
repository: nginx
pullPolicy: IfNotPresent
# Overrides the image tag whose default is the chart appVersion.
tag: "" imagePullSecrets: []
nameOverride: ""
fullnameOverride: "" serviceAccount:
# Specifies whether a service account should be created
create: true
# Annotations to add to the service account
annotations: {}
# The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template
name: "" podAnnotations: {} podSecurityContext: {}
# fsGroup: securityContext: {}
# capabilities:
# drop:
# - ALL
# readOnlyRootFilesystem: true
# runAsNonRoot: true
# runAsUser: service:
type: ClusterIP
port: ingress:
enabled: false
annotations: {}
# kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"
hosts:
- host: chart-example.local
paths: []
tls: []
# - secretName: chart-example-tls
# hosts:
# - chart-example.local resources: {}
# We usually recommend not to specify default resources and to leave this as a conscious
# choice for the user. This also increases chances charts run on environments with little
# resources, such as Minikube. If you do want to specify resources, uncomment the following
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 100m
# memory: 128Mi autoscaling:
enabled: false
minReplicas:
maxReplicas:
targetCPUUtilizationPercentage:
# targetMemoryUtilizationPercentage: nodeSelector: {} tolerations: [] affinity: {}

可以看到这个文件包含的是整个chart中各个资源下变量的值,如replicaCount: 1,前面replicas: {{ .Values.replicaCount }},因此上面的deployment的replicas为1,其他变量的值类似,其中{}表示未指定,用户可根据需要进行自定义。

接下来我们通过vim 修改下value.yaml文件中replicaCount: 2内容然后进行安装部署,但是安装部署之前需要先打包,我们在上面的操作都是针对目录和文件的,helm只能针对包进行安装,因此我们需先打包,打包之前,最好先验证下我们之前在各个文件输入的值是否合法,可以通过操作进行校验

[root@k8s-master my-second-helm]# helm lint --strict my-second-helm
==> Linting my-second-helm
Error unable to check Chart.yaml file in chart: stat my-second-helm/Chart.yaml: no such file or directory Error: chart(s) linted, chart(s) failed
[root@k8s-master my-second-helm]# cd ..
[root@k8s-master helm]# ls
my-first-helm my-second-helm
[root@k8s-master helm]# helm lint --strict my-second-helm
==> Linting my-second-helm
[INFO] Chart.yaml: icon is recommended chart(s) linted, chart(s) failed

可以看到在进行校验的时候,需要回到chart的根目录,0 chart(s) failed显示这个chart的之前输入的value值应无问题,接下来可以执行打包操作了,如下所示,红色字体就是我们打包后的结果

[root@k8s-master helm]# helm package my-second-helm
Successfully packaged chart and saved it to: /home/James/zhanglei/helm/my-second-helm-0.1..tgz
[root@k8s-master helm]# ls
my-first-helm my-second-helm my-second-helm-0.1.0.tgz

这个就是我们所说的chart包,接下来终于可以执行安装的操作了

[root@k8s-master helm]# helm install my-second-helm-test my-second-helm-0.1..tgz
NAME: my-second-helm-test
LAST DEPLOYED: Sat Sep ::
NAMESPACE: default
STATUS: deployed # 状态
REVISION: 1
NOTES:
. Get the application URL by running these commands:
export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=my-second-helm,app.kubernetes.io/instance=my-second-helm-test" -o jsonpath="{.items[0].metadata.name}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl --namespace default port-forward $POD_NAME :
[root@k8s-master helm]# helm list
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
my-second-helm-test default -- ::18.480694046 + CST deployed my-second-helm-0.1. 1.16.

可以看到在install后面指定的就是部署名称,在helm list中可追溯到时通过哪个版本的chart包进行的安装,可以看到状态为deployed,我们之前设定了deployment的副本实例数为2,我们一起来验证下:

[root@k8s-master helm]# kubectl get pod -o wide |grep my-second-helm
my-second-helm-test-566f5d8757-x27zf 1/1 Running 0 5m25s 10.122.235.244 k8s-master <none> <none>
my-second-helm-test-566f5d8757-zdm47 1/1 Running 0 5m25s 10.122.235.247 k8s-master <none> <none>

可以看到2个Pod已经running了,我们测试这个nginx如下所示为正常了,也就是说我们通过helm install chart包的方式成功安装了NGINX的应用

[root@k8s-master helm]# curl 10.122.235.244:
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p> <p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p>
</body>

至此,我们演示了通过在本地目录里面新建了一个默认的chart目录,然后对value中的值进行修改,最后的再次打包,然后安装的全过程,有读者不免发问了,这个过程太麻烦了,我只需要类型像公有镜像,并不想制作chart,是否可以远程直接拉取chart包安装?答案是:可以!接下来我将介绍第二种创建helm 应用的方式。

2)远程拉取chart包

但是在拉取公有的chart包之前,需要先配置好chart repo,如下所示是我已经配置好的chart repo,里面提供常用的chart包

[root@k8s-master my-first-helm]# helm repo list
NAME URL
stable http://mirror.azure.cn/kubernetes/charts
incubator http://mirror.azure.cn/kubernetes/charts-incubator
svc-cat http://mirror.azure.cn/kubernetes/svc-catalog-charts

我们在正式拉取chart包之前,很多时候想在对应的仓库中先查找下有想要的chart包,可以通过如下操作进行查看下,比如我想查看下有无nginx的chart

[root@k8s-master my-first-helm]# helm search repo nginx
NAME CHART VERSION APP VERSION DESCRIPTION
stable/nginx-ingress 1.41. v0.34.1 DEPRECATED! An nginx Ingress controller that us...
stable/nginx-ldapauth-proxy 0.1. 1.13. nginx proxy with ldapauth
stable/nginx-lego 0.3. Chart for nginx-ingress-controller and kube-lego
stable/gcloud-endpoints 0.1. DEPRECATED Develop, deploy, protect and monitor...

可以看到,通过search命令,可查询到仓库中已有的NGINX的chart包,其中stable是repo的类型,CHART VERSION:chart包的版本,APP VERSION:应用版本,DESCRIPTION:针对此chart包的描述,看到这里是不是有印象,这正式是我们在上文提到Chart.yaml文件里面的信息,接下来我们尝试直接从远程仓库进行拉取并完成安装的操作

[root@k8s-master helm]# helm install nginx-test stable/nginx-ingress
WARNING: This chart is deprecated
NAME: nginx-test
LAST DEPLOYED: Sat Sep ::
NAMESPACE: default
STATUS: deployed
REVISION:
TEST SUITE: None
NOTES:
*******************************************************************************************************
* DEPRECATED, please use https://github.com/kubernetes/ingress-nginx/tree/master/charts/ingress-nginx *
******************************************************************************************************* The nginx-ingress controller has been installed.
It may take a few minutes for the LoadBalancer IP to be available.
You can watch the status by running 'kubectl --namespace default get services -o wide -w nginx-test-nginx-ingress-controller' An example Ingress that makes use of the controller: apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
name: example
namespace: foo
spec:
rules:
- host: www.example.com
http:
paths:
- backend:
serviceName: exampleService
servicePort:
path: /
# This section is only required if TLS is to be enabled for the Ingress
tls:
- hosts:
- www.example.com
secretName: example-tls If TLS is enabled for the Ingress, a Secret containing the certificate and key must also be provided: apiVersion: v1
kind: Secret
metadata:
name: example-tls
namespace: foo
data:
tls.crt: <base64 encoded cert>
tls.key: <base64 encoded key>
type: kubernetes.io/tls
[root@k8s-master helm]# helm list
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
my-second-helm-test default -- ::18.480694046 + CST deployed my-second-helm-0.1. 1.16.
nginx-test default -- ::59.084999904 + CST deployed nginx-ingress-1.41. v0.34.1

可以看到helm应用已经部署成功其应用名称为nginx-test。

2、升级

1)通过修改文件内容升级

可以针对chart目录的文件内容更新后再进行升级,如vim values.yaml文件,我们将之前replicaCount的值设置为4

[root@k8s-master my-second-helm]# vim values.yaml 

# Default values for my-second-helm.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates. replicaCount:
[root@k8s-master my-second-helm]# helm upgrade -f values.yaml my-second-helm-test ./
Release "my-second-helm-test" has been upgraded. Happy Helming! # 显示升级成功
NAME: my-second-helm-test
LAST DEPLOYED: Sun Sep ::
NAMESPACE: default
STATUS: deployed
REVISION: 5 # release的版本号为5
NOTES:
. Get the application URL by running these commands:
export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=my-second-helm,app.kubernetes.io/instance=my-second-helm-test" -o jsonpath="{.items[0].metadata.name}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl --namespace default port-forward $POD_NAME :
[root@k8s-master my-second-helm]# kubectl get pod |grep my-second
my-second-helm-test-566f5d8757-8v8wc / Running 6m32s
my-second-helm-test-566f5d8757-kfh5s / Running 11h
my-second-helm-test-566f5d8757-s4286 / Running 86s
my-second-helm-test-566f5d8757-t2hhx / Running 11h

如上看到4个pod实例已经正常Running了,升级成功。

2)通过--set参数升级

其格式为:helm upgrade -f 指定目录/指定文件 --set 指定文件参数=value  部署名称 chart目录

[root@k8s-master helm]# helm upgrade -f my-second-helm/values.yaml --set replicaCount= my-second-helm-test ./my-second-helm
Release "my-second-helm-test" has been upgraded. Happy Helming!
NAME: my-second-helm-test
LAST DEPLOYED: Sun Sep ::
NAMESPACE: default
STATUS: deployed
REVISION: 6 # 版本6
NOTES:
. Get the application URL by running these commands:
export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=my-second-helm,app.kubernetes.io/instance=my-second-helm-test" -o jsonpath="{.items[0].metadata.name}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl --namespace default port-forward $POD_NAME :
[root@k8s-master helm]# kubectl get pod | grep my-se
my-second-helm-test-566f5d8757-8v8wc / Running 32m
my-second-helm-test-566f5d8757-kfh5s / Running 12h
my-second-helm-test-566f5d8757-t2hhx / Running 12h

在上个版本5中我们在values.yaml修改replicaCount的值为4,版本6中通过--set的方式我们修改了replicaCount的值为3,这个是否会同步到values.yaml中呢?

[root@k8s-master my-second-helm]# cat values.yaml
# Default values for my-second-helm.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates. replicaCount:

通过查看,replicaCount的值任然是版本5的值,并未发生改变,也就是说通过--set的值并不会影响到chart目录下源文件的值,另外从这种方式的升级来看,我们得知helm应用的升级是针对已经部署后的应用进行升级,并非针对chart版本的版本进行升级,这些地方都需要注意下!

3、回滚

升级操作成功后,每升级一次版本都会加1,在上面的例子里版本号已经6了,若我们想回到版本5该如何进行操作呢?我们先看下整个release的部署历史:

[root@k8s-master helm]# helm history my-second-helm-test
REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION
Sat Sep :: superseded my-second-helm-0.1. 1.16. Install complete
Sun Sep :: superseded my-second-helm-0.1. 1.16. Upgrade complete
Sun Sep :: superseded my-second-helm-0.1. 1.16. Upgrade complete
Sun Sep :: superseded my-second-helm-0.1. 1.16. Upgrade complete
Sun Sep :: superseded my-second-helm-0.1. 1.16. Upgrade complete
Sun Sep :: deployed my-second-helm-0.1. 1.16. Upgrade complete

可以看到针对同一个release来说,最终生效的只有一个版本,其状态为:deployed,其他版本为superseded的状态,接下来我们将版本6回滚到版本5

[root@k8s-master my-second-helm]# helm rollback my-second-helm-test
Rollback was a success! Happy Helming!
[root@k8s-master my-second-helm]# kubectl get pod |grep my-second-test
[root@k8s-master my-second-helm]# kubectl get pod |grep my-second
my-second-helm-test-566f5d8757-8v8wc / Running 51m
my-second-helm-test-566f5d8757-kfh5s / Running 12h
my-second-helm-test-566f5d8757-njqbn / Running 61s
my-second-helm-test-566f5d8757-t2hhx / Running 12h

版本5:4个Pod,版本6:3个Pod,可以看到命令执行完成之后立马就回滚且生效了,而回滚的操作命令也很简单,其格式为:helm rollback 部署名称 版本号

4、删除

若想删除已经部署成功的helm应用该如何操作呢?helm应用的删除其chart下的资源如Pod是否会保留?我们带着这些问题实践下:

[root@k8s-master my-second-helm]# helm delete my-second-helm-test
release "my-second-helm-test" uninstalled
[root@k8s-master my-second-helm]# kubectl get all |grep my-second-helm
[root@k8s-master my-second-helm]#

删除的格式为:helm delete 部署名称, 经验证,一旦删除helm的应用,其关联生成的所有资源会被全部删除掉,也就是说,helm提供给用户是一个集合了所需资源的整体应用,其新建和删除也都是以整体应用为维度。

四、总结

本文介绍了什么是Helm,在哪些场景下适用Helm,然后介绍了Helm应用的安装、部署、升级、回滚和删除等操作,Helm应用是一个资源的集合,以整体为用户提供服务,通过这个服务,可以大大简化用户部署的难度,另外还针对应用的版本进行了历史管理,升级和回滚的操作减少了用户自己重新部署和维护版本的成本,在产品设计中,我们可将整个部署helm的流程体现在UI化达到进一步降低部署应用的门槛,校验chart》安装chart-》部署-》升级-》回滚-》删除,设计的重点保证这个业务主流程信息可以清晰的传递给用户,针对重点的操作,需要在页面中重点凸显出来,且要方便用户实际进行操作。

作者简介:云计算容器\Docker\K8s\Serverless方向产品经理,学点技术,为更好地设计产品。

【原创】Kuberneters-HelmV3.3.1入门介绍及实践的更多相关文章

  1. 初识Hadoop入门介绍

    初识hadoop入门介绍 Hadoop一直是我想学习的技术,正巧最近项目组要做电子商城,我就开始研究Hadoop,虽然最后鉴定Hadoop不适用我们的项目,但是我会继续研究下去,技多不压身. < ...

  2. .NET读写Excel工具Spire.Xls使用(1)入门介绍

    原文:[原创].NET读写Excel工具Spire.Xls使用(1)入门介绍 在.NET平台,操作Excel文件是一个非常常用的需求,目前比较常规的方法有以下几种: 1.Office Com组件的方式 ...

  3. MySQL入门介绍(mysql-8.0.13)

    MySQL入门介绍(mysql-8.0.13单机部署) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.MySQL数据库介绍 1>.MySQL是一种开放源代码的关系型数据库 ...

  4. C# BackgroundWorker组件学习入门介绍

    C# BackgroundWorker组件学习入门介绍 一个程序中需要进行大量的运算,并且需要在运算过程中支持用户一定的交互,为了获得更好的用户体验,使用BackgroundWorker来完成这一功能 ...

  5. [Python爬虫] 在Windows下安装PhantomJS和CasperJS及入门介绍(上)

    最近在使用Python爬取网页内容时,总是遇到JS临时加载.动态获取网页信息的困难.例如爬取CSDN下载资源评论.搜狐图片中的“原图”等,此时尝试学习Phantomjs和CasperJS来解决这个问题 ...

  6. [Python爬虫] scrapy爬虫系列 <一>.安装及入门介绍

    前面介绍了很多Selenium基于自动测试的Python爬虫程序,主要利用它的xpath语句,通过分析网页DOM树结构进行爬取内容,同时可以结合Phantomjs模拟浏览器进行鼠标或键盘操作.但是,更 ...

  7. [原创]Java静态代码检查工具介绍

    [原创]Java静态代码检查工具介绍 一  什么是静态代码检查? 静态代码分析是指无需运行被测代码,仅通过分析或检查源程序的语法.结构.过程.接口等来检查程序的正确性,找出代码隐藏的错误和缺陷,如参数 ...

  8. JavaScript入门介绍(二)

    JavaScript入门介绍 [函数] 函数function 是Javascript的基础模块单元,用于代码的复用.信息影藏和组合调用. function a(){} 函数对象Function Lit ...

  9. JavaScript入门介绍(一)

    JavaScript入门介绍 [经常使用的调试工具][w3school.com.cn在线编辑] [Chrome浏览器 开发调试工具]按F121.代码后台输出调试:console.log("t ...

随机推荐

  1. Android Studio Gradle build 报错:Received status code 400 from server: Bad Request

    错误提示如下 Could not GET 'https://dl.google.com/dl/android/maven2/com/android/tools/build/gradle/3.1.2/ ...

  2. 攻防世界-web(进阶)-NewsCenter

    打开文件发现有个搜索框,考虑是XSS或SQL注入,输入弹框语句不显示考虑到SQL注入,抓包将抓包信息保存为txt,用sqlmap爆破. 输入:sqlmap -r “sql.txt”,输出如下数据库版本 ...

  3. 图的DFS与BFS

    图的DFS与BFS(C++) 概述 大一学生,作为我的第一篇Blog,准备记录一下图的基本操作:图的创建与遍历.请大佬多多包涵勿喷. 图可以采用邻接表,邻接矩阵,十字链表等多种储存结构进行储存,这里为 ...

  4. [Hadoop] mapper数量的控制

    确定map任务数时依次优先参考如下几个原则: 1)      每个map任务使用的内存不超过800M,尽量在500M以下 比如处理256MB数据需要的时间为10分钟,内存为800MB,此时如果处理12 ...

  5. 了解JS压缩图片,这一篇就够了

    前言 公司的移动端业务需要在用户上传图片是由前端压缩图片大小,再上传到服务器,这样可以减少移动端上行流量,减少用户上传等待时长,优化用户体验. 插播一下,本文案例已整理成插件,已上传npm ,可通过 ...

  6. windows服务器下,mysql运行一段时间之后忽然无法连接,但是mysql服务启动正常

    出现这种情况以前都是重启服务器可以解决,但是治标不治本,一段时间之后仍然会出现此问题. 此问题不是mysql应用程序的问题而是windows server system 的配置问题.因此需要修改win ...

  7. JavaScript正则表达式的模式匹配教程,并且附带充足的实战代码

    JavaScript正则表达式的模式匹配 引言 正文 一.正则表达式定义 二.正则表达式的使用 三.RegExp直接量 (1)正则表达式初体验 (2)深入了解正则 字符类 重复 选择 分组与引用 指定 ...

  8. Python日期时间(详细)

    获取当前时间戳 import time t = time.time() millis1 = int(t) print('10位时间戳:{}'.format(millis1)) millis2 = in ...

  9. Linux环境下没有权限操作文件或目录

    linux下有超级用户(root)和普通用户,普通用户不能直接操作没有权限的目录,如果出现了没有权限的提示,可以尝试用su命令解决. 比如: #mkdir aaa 我要创建一个aaa的文件夹,没有操作 ...

  10. rlpyt(Deep Reinforcement Learning in PyTorch)

    rlpyt: A Research Code Base for Deep Reinforcement Learning in PyTorch Github:https://github.com/ast ...