kubernetes(k8s) 知识总结(第2期)

news2024/11/23 7:34:42

1. “控制器”思想 

kube-controller-manager 是一系列控制器的集合,这些控制器被放在 Kubernetes 项目的 pkg/controller 目录,这些控制器都以独有的方式负责某种编排功能。它们都遵循一个通用的编排模式——控制循环

以 Deployment 为例介绍它对控制器模型的实现:

(1)Deployment 控制器从 etcd 中获取所有携带了 app: nginx 标签的 Pod,然后统计它们的数量,这就是实际状态。

(2)Deployment 对象的 Replicas 字段的值就是期望状态。

(3)Deployment 控制器比较两个状态,然后根据结果确定是创建 Pod 还是删除已有的 Pod。

一个 Kubernetes 对象的主要编排逻辑是在对比阶段完成的,这个操作称为调谐(reconcile)。调谐的过程称作调谐循环或者同步循环。

Deployment 定义的 template 字段在 Kubernetes 中有一个专属的名字:PodTemplate。

2. Deployment & ReplicaSet

如果你更新了 Deployment 的 Pod 模板,那么 Deployment 就要遵循一种叫作滚动更新的方式,来升级现有容器。这个能力的实现依赖 Kubernetes 中的一个非常重要的概念:ReplicaSet。

例子:

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: nginx-set
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9

一个 ReplicaSet 对象是又副本数目的定义和一个 Pod 模板组成的。它的定义其实是一个 Deployment 的一个子集。更重要的是,Deployment 控制器实际上操纵的是 ReplicaSet 对象,而不是 Pod 对象。看下边的 Deployment 定义:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

 Deployment、ReplicaSet 和 Pod 的关系如下图所示:

 ReplicaSet 负责通过控制器模式保证系统中 Pod 的个数永远等于指定个数。这也是 Deployment 只允许容器的 restartPolicy=Always 的原因:只有在容器保证自己始终处于 Running 状态的前提下,ReplicaSet 调整 Pod 的个数才有意义。在此基础上,Deployment 同样通过控制器模式来操作 ReplicaSet 的个数和属性,进而实现水平扩展/收缩和滚动更新。

水平扩展/收缩非常容易实现,Deployment Controller 只需要修改它所控制的 ReplicaSet 的 Pod 的副本数就可以了,这个指令是 kubectl scale:

kubectl scale deployment nginx-deployment --replicas=4

滚动更新的过程如下:

首先创建 Deployment:

$ kubectl create -f nginx-deployment.yaml --record

检查这个 Deployment 状态信息:

$ kubectl get deployments
NAME                DESIRED    CURRENT    UP-TO-DATE    AVAILABLE    AGE
nginx-deployment    3          0          0             0            1s

这几个字段的含义如下所示:

(1)DESIRED:用户期望的 Pod 副本个数(spec.replicas 的值)。

(2)CURRENT:当前处于 Running 状态的 Pod 的个数。

(3)UP-TO-DATE:当前处于最新版本的 Pod 的个数。所谓最新版本,指的是 Pod 的 Spec 部分与 Deployment 里 Pod 模板里定义的完全一致。

(4)AVAILABLE:当前已经可用的 Pod 的个数,即既是 Running 状态,又是最新版本,并且已处于 Ready(健康检查显示正常)状态的 Pod 的个数。

这个 AVAILABLE 字段描述的才是用户所期望的最终状态。

可以使用以下指令,实时查看 Deployment 对象的状态变化:

kubectl rollout status deployment/nginx-deployment

一段时间后,可以看到 Deployment 的 3 个 Pod 进入了 AVAILABLE 状态:

$ kubectl get deployments
NAME                DESIRED    CURRENT    UP-TO-DATE    AVAILABLE    AGE
nginx-deployment    3          3          3             3            20s

此时可以查看这个 Deployment 所控制的 ReplicaSet:

$ kubectl get rs
NAME                        DESIRED    CURRENT    READY    AGE
nginx-deployment-******     3          3          3        20s

在用户提交了一个 Deployment 对象后,Deployment Controller 会立即创建一个 Pod 副本数为 3 的 ReplicaSet。这个 ReplicaSet 的名字由 Deployment 的名字和一个随机字符串共同组成。这个随机字符串叫作 pod-template-hash。ReplicaSet 会把这个随机字符串加在它所控制的所有 Pod 的标签里,从而避免这些 Pod 与集群里其他 Pod 混淆。

ReplicaSet 的 DESIRED、CURRENT 和 READY 字段的含义和 Deployment 中是一致的。所以,Deployment 是在 ReplicaSet 的基础上添加了 UP-TO-DATE 这个跟版本有关的字段。

这时,修改 Deployment 中的 Pod 模板,就会自动触发“滚动更新”。Deployment Controller 会使用修改后的 Pod 模板创建一个新的 ReplicaSet,这个新的 ReplicaSet 初始 Pod 副本数为 0。随后,Deployment Controller 逐步将旧 ReplicaSet 管理的 Pod 的副本数从 3 变成 0,将新的 ReplicaSet 管理的 Pod 的副本数从 0 变成 3。为了保证服务的连续性,Deployment Controller 会确保在任何时间窗口内,只有指定比例的 Pod 处于离线状态,只有指定比例的新 Pod 被创建出来,这两个值默认都是 DESIRED 值的 25%。这个字段叫 RollingUpdateStrategy,其中 maxSurge 指定的是除 DESIRED 数量外,在一次滚动更新中 Deployment Controller 还能创建多少新的 Pod,而 maxUnavailable 指的是在一次滚动更新中 Deployment Controller 可以删除多少旧的 Pod。这两个配置还可以用百分比表示,表示的是 DESIRED 数量乘以百分比的值。

如图所示,Deployment Controller 实际控制的是 ReplicaSet 的数目,以及每个 ReplicaSet 的属性。一个应用的版本对应的正是一个 ReplicaSet,这个版本应用的 Pod 数量由 ReplicaSet 通过它自己的控制器(ReplicaSet Controller)来保证。通过多个这样的 ReplicaSet 对象,Kubernetes 项目就实现了对多个应用版本的描述。

在升级过程中,如果镜像出现错误,新版本的 ReplicaSet 的水平扩展将会停止,其中的 Pod 状态非 READY。旧版本的 ReplicaSet 的水平收缩也停止。这时,使用以下命令就可以回滚到上一个版本:

kubectl rollout undo deployment/nginx-deployment

 如果想回滚到更早之前的版本,可以先查看历史版本:

kubectl rollout history deployment/nginx-deployment

查看具体版本的细节:

kubectl rollout history deployment/nginx-deployment --revision=2

回滚:

kubectl rollout undo deployment/nginx-deployment --to-revision=2

如果担心每次更新系统都会产生新的 ReplicaSet,导致资源浪费,可以使用一种方法让我们的多次操作只产生一个 ReplicaSet,先执行以下指令:

kubectl rollout pause deployment/nginx-deployment

之后就可以随意使用 kubectl edit 或 kubectl set image 修改 Deployment 了,修改之后执行:

kubectl rollout resume deployment/nginx-deployment

Deployment 有一个 spec.revisionHistoryLimit 字段,可以控制历史版本个数。

3. StatefulSet

分布式应用的多个实例之间往往有依赖关系,比如主从关系、主备关系;还有数据存储类应用的多个实例往往会在本地磁盘保存一份数据。这种实例之间有不对等关系,以及实力对外部数据有依赖关系的应用,就是有状态应用

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  serviceName: "nginx"
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.9.1
        ports:
        - containerPort: 80
          name: web

这个 YAML 文件和 Deployment 的唯一区别就是多了一个 serviceName=nginx 字段,这个字段的作用就是告诉 StatefulSet 控制器,在执行控制循环时请使用 nginx 这个 Headless Service 来保证 Pod 可解析。

StatefulSet 给它所管理的所有 Pod 的名字进行了编号,这些编号是从 0 开始累加的,不重复。每个 Pod 对应不同的 Headless Service,也就意味着每个 Pod 拥有独一无二的 IP 地址。

StatefulSet 这个控制器的主要作用之一,就是使用 Pod 模板创建 Pod 时对它们进行编号,并且按照编号顺序逐一完成创建工作。而当 StatefulSet 的“控制循环”发现 Pod 的实际状态与期望状态不一致,需要新建或者删除 Pod 以进行“调谐”时,它会严格按照这些 Pod 编号的顺序逐一完成这些操作。通过 Headless Service 的方式,StatefulSet 为每一个 Pod 创建了一个固定并且稳定的 DNS 记录,来作为它的访问入口。

想使用一个 Volume,只需要以下两步:

第一步,定义一个 PVC,声明想要的 Volume 属性:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pv-claim
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

第二步,在应用的 Pod 中声明使用这个 PVC:

apiVersion: v1
kind: Pod
metadata:
  name: pv-pod
spec:
  containers:
    - name: pv-container
      image: nginx
      ports:
        - containerPort: 80
          name: "http-server"
      volumeMounts:
        - mountPath: "/usr/share/nginx/html"
          name: pv-storage
  volumes:
    - name: pv-storage
      persistentVolumeClaim:
        claimName: pv-claim

 在这个 Pod 的 Volumes 定义中,只需要声明它的类型是 persistentVolumeClaim,然后指定 PVC 的名字,完全不必关心 Volume 本身的定义。

此时,只要创建这个 PVC 对象,Kubernetes 就会自动为它绑定一个符合条件的 Volume。这些符合条件的 PV 来自运维人员维护的 PV 对象:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-volume
  labels:
    type: local
spec:
  capacity:
    storage: 10Gi
  rbd:
    monitors:
    - '10.16.154.78:6789'
    - '10.16.154.82:6789'
    - '10.16.154.83:6789'
    pool: kube
    image: foo
    fsType: ext4
    readOnly: true
    user: admin
    keyring: /etc/ceph/keyring
    imageformat: "2"
    imagefeatures: "layering"

Kubernetes 就会为我们创建的 PVC 对象绑定这个 PV。

以上边的 StatefulSet 为例,添加一个 volumeClaimTemplates 字段:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  serviceName: "nginx"
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.9.1
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 1Gi

凡是被这个 StatefulSet 管理的 Pod,都会声明一个对应的 PVC,这个 PVC 的定义就来自 volumeClaimTemplates 字段。这个 PVC 的名字会被分配一个与这个 Pod 完全一致的编号。这个自动创建的 PVC 与 PV 绑定成功后就会进入 Bound 状态,这就意味着这个 Pod 可以挂在并使用这个 PV 了。

在创建了 StatefulSet 之后,集群里出现两个 PVC,命名格式都是<PVC 名字>-<StatefulSet 名字>-<编号>,且处于 Bound 状态。

梳理一下 StatefulSet 的工作原理:

首先,StatefulSet 的控制器直接管理的是 Pod。其次,Kubernetes 通过 Headless Service 为这些有编号的 Pod 在 DNS 服务器中生成带有相同编号的 DNS 记录。最后,StatefulSet 还为每个 Pod 分配并创建一个相同编号的 PVC。

4. DaemonSet

DaemonSet 的主要作用是在 Kubernetes 集群中运行一个 Daemon Pod。这个 Pod 有三个特征:

① 这个 Pod 在集群里的每一个节点上运行

② 每个节点上只有一个这样的 Pod 实例

③ 当有新节点加入 Kubernetes 集群后,该 Pod 会自动地在新节点上被创建出来;而当旧节点被删除后,它上面的 Pod 也会相应地被回收。

常用的例子有:

各种网络插件的 Agent 组件、各种存储插件的 Agent 组件、各种监控组件和日志组件必须在每一个节点上运行。

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd-elasticsearch
  namespace: kube-system
  labels:
    k8s-app: fluentd-logging
spec:
  selector:
    matchLabels:
      name: fluentd-elasticsearch
  template:
    metadata:
      labels:
        name: fluentd-elasticsearch
    spec:
      tolerations:
      - key: node-role.kubernetes.io/master
        effect: NoSchedule
      containers:
      - name: fluentd-elasticsearch
        image: quay.io/fluentd_elasticsearch/fluentd:v3.0.0
        resources:
          limits:
            memory: 200Mi
          requests:
            cpu: 100m
            memory: 200Mi
        volumeMounts:
        - name: varlog
          mountPath: /var/log
        - name: varlibdockercontainers
          mountPath: /var/lib/docker/containers
          readOnly: true
      terminationGracePeriodSeconds: 30
      volumes:
      - name: varlog
        hostPath:
          path: /var/log
      - name: varlibdockercontainers
        hostPath:
          path: /var/lib/docker/containers

这个 DaemonSet 管理的是一个 fluentd-elasticsearch 镜像的 Pod,功能是通过 fluentd 将 Docker 中的日志转发到 Elasticsearch 中。

可以看到,DaemonSet 跟 Deployment 非常相似,只不过没有 replicas 字段;他也使用 selector 选择管理所有携带了 name: fluentd-elasticsearch 标签的 Pod。这些 Pod 的模板也是用 template 字段定义的。在该字段中,定义了一个使用 fluentd-elasticsearch:1.20 镜像的容器,而且该容器挂载了两个 hostPath 类型的 Volume,分别对应宿主机的 /var/log 目录和 /var/lib/docker/containers 目录。

DaemonSet 如何保证每个节点上有且只有一个被管理的 Pod 呢?DaemonSet Controller 首先从 etcd 里获取所有的节点列表,然后遍历所有节点,这时,就很容易检查当前节点是否有一个携带了 name: fluentd-elasticsearch 标签的 Pod 在运行。

检查的结果可能有3种情况:

(1)没有这种 Pod,这就意味着要在该节点上创建这样一个 Pod

(2)有这种 Pod,但是数量大于1,说明要删除该节点上多余的 Pod

(3)正好只有一个这种 Pod,说明该节点是正常的

如何在指定节点上新建 Pod ?可以使用 nodeSelector。不过,nodeSelector 已经是一个将要被废除的字段了,最好使用 nodeAffinity 代替它:

apiVersion: v1
kind: Pod
metadata:
  name: with-node-affinity
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: metadata.name
            operator: In
            values:
            - node-ituring

requiredDuringSchedulingIgnoredDuringExecution 的意思是这个 nodeAffinity 必须在每次调度时予以考虑,也意味着可以设置在某些情况下不考虑这个 nodeAffinity。这个 Pod 将来只允许在 metadata.name 是 node-ituring 的节点上运行。 

此外,DaemonSet 还会给这个 Pod 自动加上另外一个与调度有关的字段:tolerations。这意味着这个 Pod 会“容忍”某些节点上的“污点”(Taint)。

apiVersion: v1
kind: Pod
metadata:
  name: with-toleration
spec:
  tolerations:
  - key: node.kubernetes.io/unschedulable
    operator: Exists
    effect: NoSchedule

这个 Toleration 的含义是:“容忍”所有被标记为 unschedulable “污点”的节点,“容忍”的效果是允许调度。在正常情况下,被加上 unschedulable “污点”的节点是不会有任何 Pod 被调度上去的。但是,DaemonSet 自动地给被管理的 Pod 加上了这个特殊的 Toleration, 就使得这些 Pod 可以忽略这项限制,继而保证每个节点上都会被调度一个 Pod。 

5. Job 与 CronJob

有一类作业属于“离线业务”,也叫 Batch Job(计算业务)。这种业务在计算完成后就直接退出了。

Job API 对象的定义非常简单,示例如下:

apiVersion: batch/v1
kind: Job
metadata:
  name: pi
spec:
  template:
    spec:
      containers:
      - name: pi
        image: resouer/ubuntu-bc
        command: ["sh", "-c", "echo 'scale=10000; 4*a(1)' | bc -l "]
      restartPolicy: Never
  backoffLimit: 4

在这个 Job 的 YAML 文件中,可以看到 Pod 模板:spec.template。在这个模板中,定义了一个 Ubuntu 镜像的容器,它运行的程序是:echo 'scale=10000; 4*a(1)' | bc -l 。

在一个 Job 对象创建后,它的 Pod 模板被自动加上了一个 controller-uid=<随机字符串> 这样的 Label。而这个 Job 对象本身被自动加上了这个 Label 对应的 Selector,从而保证了 Job 与它所管理的 Pod 之间的匹配关系。

在 Pod 模板中定义 restartPolicy=Never 的原因是离线计算的 Pod 永远不应该被重启。事实上,restartPolicy 在 Job 对象里只允许设置为 Never 和 OnFailure;而在 Deployment 对象里,restartPolicy 只允许设置为 Always。

如果一个离线作业失败了,Job Controller 就会不断尝试创建一个新 Pod。当然,这个尝试肯定不能无限进行下去。所以,就在 Job 对象的 spec.backoffLimit 字段里定义了重试次数为4,这个字段的默认值为6。

需要注意的是,Job Controller 重新创建 Pod 的间隔是呈指数级增加的,即下一次重新创建 Pod 的动作会分别发生在 10s、20s、40s... 后。

在 Job 的 API 对象里,有一个 spec.activeDeadlineSeconds 字段可以限制运行时长。一旦超过这个时间,这个 Job 的所有 Pod 都会被终止。并且,你可以在 Pod 的状态里看到终止的原因: reason: DeadlineExceeded。

在 Job 对象中,负责并行控制的参数有两个:

(1)spec.parallelism 定义的是一个 Job 在任意时间最多可以启动多少个 Pod 同时运行。

(2)spec.completions 定义的是 Job 至少要完成的 Pod 的数目。

下面,介绍一个非常有用的 Job 对象:CronJob:

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: hello
spec:
  schedule: "* * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: hello
            image: busybox
            args:
            - /bin/sh
            - -c
            - date; echo Hello from the Kubernetes cluster
          restartPolicy: OnFailure

最重要的关键词是 jobTemplate,这就意味着,CronJob 是一个 Job 对象的控制器。它创建和删除 Job 的依据是 schedule 字段定义的、一个标准的 Unix Cron 格式的表达式。

由于定时任务的特殊性,很可能某个 Job 还没有执行完,另一个新的 Job 就产生了。可以通过 spec.concurrencyPolicy 字段来定义具体的处理策略:

(1)concurrencyPolicy=Allow,这是默认情况,意味着这些 Job 可以同时存在。

(2)concurrencyPolicy=Forbid,这意味着不会创建新的 Pod。

(3)concurrencyPolicy=Replace,这意味着新产生的 Job 会替换旧的、未执行完的 Job。

如果某一次 Job 创建失败,这次创建就会被标记为“miss”。在指定时间窗口内 miss 的数目达到 100 时,CronJob 会停止再创建这个 Job。这个时间窗口可以由 spec.startingDeadlineSeconds 字段指定。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/346891.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

最最普通程序员,如何利用工资攒够彩礼,成为人生赢家

今天我们不讲如何提升你的专业技能去涨工资&#xff0c;不讲面试技巧如何跳槽涨工资&#xff0c;不讲如何干兼职赚人生第一桶金&#xff0c;就讲一个最最普通的程序员&#xff0c;如何在工作几年后&#xff0c;可以攒够彩礼钱&#xff0c;婚礼酒席钱&#xff0c;在自己人生大事…

什么是网络流量分析(NTA),有什么好用的NTA软件

分析网络的稳定性首先要监控其性能、设备功能、网络速度以及许多网络管理员忽略的另一个方面&#xff1a;网络流量。网络流量分析 &#xff08;NTA&#xff09; 通常是考虑最少的方面&#xff0c;但它会影响许多问题&#xff0c;例如性能下降和用户速度缓慢。忽视它可能会让位于…

SQL语句实现找到一行中数据最大值(greatest)/最小值(least);mysql行转列

今日我在刷题时遇到这样一个题&#xff0c;它提到了以下需求&#xff1a; 有一场节目表演&#xff0c;五名裁判会对节目提供1-10分的打分&#xff0c;节目最终得分为去掉一个最高分和一个最低分后的平均分。 存在以下一张表performence_detail&#xff0c;包含字段有performa…

Docker安装RocketMQ 4.8

1拉取4.8镜像 docker pull foxiswho/rocketmq:4.8.0拉取控制台镜像 docker pull styletang/rocketmq-console-ng2创建rocketmq使用的共有网络&#xff0c;便于相互访问 docker network create rocketmq_network3启动rmqnamesrv docker run -d --name rmqnamesrv --network …

电脑录屏怎样不录到外界声音?调整这一个开关,即可实现

​有很多小伙伴希望自己电脑录屏的时候&#xff0c;不要录制自己的声音&#xff0c;而是通过后期配音的方式完成视频创作。电脑录屏怎样不录到外界声音&#xff1f;其实只需要调整这一个开关&#xff0c;就能实现不录外界声音&#xff0c;一起来看看吧。 不录外界声音1&#xf…

什么是 Java 泛型?

本文首发自「慕课网」&#xff0c;想了解更多IT干货内容&#xff0c;程序员圈内热闻&#xff0c;欢迎关注&#xff01; 作者| 慕课网精英讲师 ColorfulC 通过本篇文章你将了解到什么是泛型&#xff0c;为什么需要泛型&#xff0c;如何使用泛型&#xff0c;如何自定义泛型&…

记一次以小勃大,紧张刺激的渗透测试(2017年老文)

零、前言 有技术交流或渗透测试培训需求的朋友欢迎联系QQ/VX-547006660&#xff0c;需要代码审计、渗透测试、红蓝对抗网络安全相关业务可以看置顶博文 2000人网络安全交流群&#xff0c;欢迎大佬们来玩 群号820783253 一、起因 emmm&#xff0c;炎炎夏日到来&#xff0c;这…

libxlsxwriter数据验证

今天要分享的这个问题其实也属于excel的高级用法。我们想通过libxlsxwriter来实现一个能对用户的输入进行数据验证的表格功能。 内心os&#xff1a;小白最近是不是有点走火入魔了……我们真的会遇上这样的场景吗&#xff1a;需要通过代码生成一个表格&#xff0c;这个表格中还有…

智慧机场,或将成为航空领域数字孪生技术得完美应用

在《智慧民航建设路线图》文件中&#xff0c;民航局明确指出&#xff0c;智慧机场是实现智慧民航的四个核心抓手之一。这一战略性举措旨在推进数字化技术与航空产业的深度融合&#xff0c;为旅客提供更加智能化、便捷化、安全化的出行服务&#xff0c;进一步提升我国民航发展的…

IO流进阶

&#x1f3e1;个人主页 &#xff1a; 守夜人st &#x1f680;系列专栏&#xff1a;Java …持续更新中敬请关注… &#x1f649;博主简介&#xff1a;软件工程专业&#xff0c;在校学生&#xff0c;写博客是为了总结回顾一些所学知识点 目录IO流进阶缓冲流缓冲流概述字节缓冲流(…

【LeetCode】剑指 Offer(1)

目录 写在前面&#xff1a; 题目1&#xff1a;剑指 Offer 03. 数组中重复的数字 - 力扣&#xff08;Leetcode&#xff09; 题目的接口&#xff1a; 解题思路&#xff1a; 代码&#xff1a; 过啦&#xff01;&#xff01;&#xff01; 题目2&#xff1a;剑指 Offer 06. 从…

JavaEE初阶---TCP/IP协议

一:概述 本文是网络编程的理论基础,也是网络部分的重点和难点,在笔试,面试中,这部分内容也多有考察.二:详解 TCP/IP五层协议 应用层传输层网络层数据链路层物理层 2.1应用层 我们自己编写的代码,就是在应用层,这也是在实际开发中接触最多的层.应用层里有许多现成的协议 , 而在…

springboot(5)静态资源访问前缀+欢迎页+REST风格的传递参数

Springboot的访问规则是 先访问controller的请求&#xff0c;如果没有的话&#xff0c;我们在访问静态资源。 但是静态资源过多的情况下这样不好处理&#xff0c;所以我们可以加一个前缀&#xff0c;这样可以拦截掉非静态资源的请求&#xff0c;每次都可以准确快速无风险的访…

镀镍废水处理,企业污水处理,离子交换树脂在镀镍废水中的应用

传统沉淀法不能满足日益提的环保要求(如电镀表三镍含量要求0.1mg/l以下)。针对特定重金属离子的特点&#xff0c;利用螯合树脂的特种功能基团与重金属离子形成络合物的特性&#xff0c;实现重金属离子的回收利用及深度去除。 CH-90Na对除铜镍铅锌钴锰等具有特定的选择性&#x…

API的应用

API&#xff08;Application Programming Interface,应用程序编程接口&#xff09;是一些预先定义的函数&#xff0c;目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力&#xff0c;而又无需访问源码&#xff0c;或理解内部工作机制的细节 应用程序接口 想…

安卓|aar和jar打包引入流程演示

安卓|aar和jar打包引入流程演示aar和jar存在相关意义打包环境工具aar和jar|Module项目目录aar打包|引入总览步骤|aar配置打包创建java or kotlin类文件及资源|截图展示步骤|aar包引入jar打包|引入总览步骤|jar配置打包任务创建java类文件|截图展示步骤|jar包引入aar和jar运行在…

OpenTracing协议规范链接

一、官网链接 OpenTracing specificationhttps://opentracing.io/specification/不过目前OpenTracing项目已归档&#xff0c;不再维护。需要参考OpenTelemetry官网链接 Migrating from OpenTracing | OpenTelemetryBackward compatibility with OpenTracing has been a prior…

Promise 的理解

promise 是什么&#xff1f;promise 是JS 中进行异步编程的最新的解决方案从语法上来说&#xff1a;Promise 是一个构造函数从功能上来说&#xff1a;promise 对象时用来封装一个异步操作并可以获取其结果其三种状态&#xff0c;reasolve 、pendding、 rejectedPromise 的基本运…

计算机网络-ip数据报

在图中&#xff0c;网络层包含了四种协议&#xff1a;ARP、IP、ICMP、IGMP&#xff0c;由上下关系表明&#xff0c;ARP为IP协议服务&#xff0c;IP为ICMP和IGMP服务。 IP数据报格式 此处不区分数据报和分组的概念&#xff1a;当数据部分过长时&#xff0c;将数据部分拆分&…

2022年全国职业院校技能大赛A(1)

目录 模块A 基础设施设置与安全加固 一、项目和任务描述&#xff1a; 二、服务器环境说明 三、具体任务&#xff08;每个任务得分以电子答题卡为准&#xff09; A-1任务一 登录安全加固 1.密码策略&#xff08;Windows&#xff0c;Linux&#xff09; a.设置最短密码长度为…