当前位置: 首页 > news >正文

openkruise 缩容_Kubernetes应用管理器OpenKruise

OpenKruise

OpenKruise 是 Kubernetes 的一个标准扩展,它可以配合原生 Kubernetes 使用,并为管理应用容器、sidecar、镜像分发等方面提供更加强大和高效的能力。

核心功能

原地升级

原地升级是一种可以避免删除、新建 Pod 的升级镜像能力。它比原生 Deployment/StatefulSet 的重建 Pod 升级更快、更高效,并且避免对 Pod 对其他不需要更新的容器造成干扰。

Sidecar 管理

支持在一个单独的 CR 中定义 sidecar 容器,OpenKruise 能够帮你把这些 Sidecar 容器注入到所有符合条件的 Pod 中。这个过程和 Istio 的注入很相似,但是你可以管理任意你关心的 Sidecar。

跨多可用区部署

定义一个跨多个可用区的全局 workload,容器,OpenKruise 会帮你在每个可用区创建一个对应的下属 workload。你可以统一管理他们的副本数、版本、甚至针对不同可用区采用不同的发布策略。

CRD 列表

CloneSet

提供更加高效、确定可控的应用管理和部署能力,支持优雅原地升级、指定删除、发布顺序可配置、并行/灰度发布等丰富的策略,可以满足更多样化的应用场景。

Advanced StatefulSet

基于原生 StatefulSet 之上的增强版本,默认行为与原生完全一致,在此之外提供了原地升级、并行发布(最大不可用)、发布暂停等功能。

SidecarSet

对 sidecar 容器做统一管理,在满足 selector 条件的 Pod 中注入指定的 sidecar 容器。

UnitedDeployment

通过多个 subset workload 将应用部署到多个可用区。

BroadcastJob

配置一个 job,在集群中所有满足条件的 Node 上都跑一个 Pod 任务。

Advanced DaemonSet

基于原生 DaemonSet 之上的增强版本,默认行为与原生一致,在此之外提供了灰度分批、按 Node label 选择、暂停、热升级等发布策略。

AdvancedCronJob

一个扩展的 CronJob 控制器,目前 template 模板支持配置使用 Job 或 BroadcastJob。

以上在官方文档都有介绍,本文主要着重实战,先讲CloneSet,其他控制器后面会陆续更新。。。

部署Kruise到Kubernetes集群

这里使用helm来安装Kruise

1、现在kruise Chart

wget https://github.com/openkruise/kruise/releases/download/v0.7.0/kruise-chart.tgz

tar -zxf kruise-chart.tgz

cd kruise

[root@ kruise]# ls -l

total 16

-rw-r--r-- 1 root root  311 Dec 20 15:09 Chart.yaml

-rw-r--r-- 1 root root 4052 Dec 20 15:09 README.md

drwxr-xr-x 2 root root 4096 Dec23 10:18 templates

-rw-r--r-- 1 root root  659 Dec 20 15:09 values.yaml

2、修改values.yaml,默认不用修改也行

3、执行部署

[root@qd01-stop-k8s-master001 kruise]# kubectlcreatens kruise

namespace/kruise created

[root@qd01-stop-k8s-master001 kruise]# helm install kruise -n kruise -f values.yaml  .

W1223 10:22:13.562088 1589994 warnings.go:67] apiextensions.k8s.io/v1beta1 CustomResourceDefinition isdeprecatedinv1.16+, unavailableinv1.22+; use apiextensions.k8s.io/v1 CustomResourceDefinition

。。。。。。。

NAME: kruise

LASTDEPLOYED: WedDec23 10:22:12 2020

NAMESPACE: kruise

STATUS: deployed

REVISION: 1

TEST SUITE: None

这里会看到一堆的deprecated信息,因为新版的kubernetes对CRD的版本会淘汰,可以根据自己的集群版本修改CRD的API版本即可

4、检查kruise部署状态

[root@qd01-stop-k8s-master001 kruise]# helm ls -n kruise

NAMENAMESPACE       REVISION        UPDATED                                 STATUS          CHART           APP VERSION

kruise  kruise          1               2020-12-23 10:22:12.963651877 +0800 CST deployed        kruise-0.7.0

可以看到,集群中有的kruise crd类型

[root@qd01-stop-k8s-master001 kruise]# kubectl get crd|grep  kruise

advancedcronjobs.apps.kruise.io                       2020-12-23T02:22:13Z

broadcastjobs.apps.kruise.io                          2020-12-23T02:22:13Z

clonesets.apps.kruise.io                              2020-12-23T02:22:13Z

daemonsets.apps.kruise.io                             2020-12-23T02:22:13Z

sidecarsets.apps.kruise.io                            2020-12-23T02:22:13Z

statefulsets.apps.kruise.io                           2020-12-23T02:22:13Z

uniteddeployments.apps.kruise.io                      2020-12-23T02:22:13Z

下面我们开始来使用这些管理器

CloneSet

CloneSet 控制器提供了高效管理无状态应用的能力,它可以对标原生的 Deployment,但 CloneSet 提供了很多增强功能。

1、我们先创建一个简单的CloneSet,yaml如下

apiVersion: apps.kruise.io/v1alpha1

kind: CloneSet

metadata:

labels:

app: nginx-alpine

name: nginx-alpine

spec:

replicas: 5

selector:

matchLabels:

app: nginx-alpine

template:

metadata:

labels:

app: nginx-alpine

spec:

containers:

- name: nginx

image: nginx:alpine

2、部署

[root@qd01-stop-k8s-master001 demo]# kubectl apply -f  CloneSet.yaml

cloneset.apps.kruise.io/nginx-alpine created

[root@qd01-stop-k8s-master001 demo]# kubectl get po |grep nginx

nginx-alpine-29g7n                          1/1     Running   0          45s

nginx-alpine-bvgqm                          1/1     Running   0          45s

nginx-alpine-q9tlw                          1/1     Running   0          45s

nginx-alpine-s2t46                          1/1     Running   0          44s

nginx-alpine-sslvf                          1/1     Running   0          44s

从输出结果看,和原生的Deployment没有啥区别

#注意,这里如果get deployment是看不到nginx-alpine这个应用的,需要get cloneset才能看到

[root@qd01-stop-k8s-master001 demo]# kubectl get deployment

[root@qd01-stop-k8s-master001 demo]# kubectl get cloneset

NAMEDESIRED   UPDATED   UPDATED_READY   READY   TOTAL   AGE

nginx-alpine   5         5         5               5       5       2m16s

CloneSet 允许用户配置 PVC 模板 volumeClaimTemplates,用来给每个 Pod 生成独享的 PVC,这是 Deployment 所不支持的。 如果用户没有指定这个模板,CloneSet 会创建不带 PVC 的 Pod。

3、现在来创建一个带有 PVC 模板的例子

apiVersion: apps.kruise.io/v1alpha1

kind: CloneSet

metadata:

labels:

app: nginx-2

name: nginx-2

spec:

replicas: 5

selector:

matchLabels:

app: nginx-2

template:

metadata:

labels:

app: nginx-2

spec:

containers:

- name: nginx

image: nginx:alpine

volumeMounts:

- name: data-vol

mountPath: /usr/share/nginx/html

volumeClaimTemplates:

- metadata:

name: rbd

spec:

accessModes: [ "ReadWriteOnce"]

storageClassName: rbd

resources:

requests:

storage: 2Gi

部署

[root@qd01-stop-k8s-master001 demo]# kubectl apply -f  CloneSet.yaml

cloneset.apps.kruise.io/nginx-2 created

[root@qd01-stop-k8s-master001 demo]# kubectl get pv|grep data-vol

pvc-0fde19f3-ea4b-47e0-81be-a8e43812e47b   2Gi        RWO            DeleteBounddefault/data-vol-nginx-2-t55h8                  rbd                     83s

pvc-72accf10-57a6-4418-a1bc-c64633b84434   2Gi        RWO            DeleteBounddefault/data-vol-nginx-2-t49mk                  rbd                     82s

pvc-8fc8b9a5-afe8-446a-9190-08fcee0ec9f6   2Gi        RWO            DeleteBounddefault/data-vol-nginx-2-jw2zp                  rbd                     84s

pvc-c9fba396-e357-43e8-9510-616f698da765   2Gi        RWO            DeleteBounddefault/data-vol-nginx-2-b5fdd                  rbd                     84s

pvc-e5302eab-a9f2-4a71-a5a3-4cd43205e8a0   2Gi        RWO            DeleteBounddefault/data-vol-nginx-2-l54dz                  rbd                     84s

[root@qd01-stop-k8s-master001 demo]# kubectl get po|grep nginx

nginx-2-b5fdd                               1/1     Running   0          97s

nginx-2-jw2zp                               1/1     Running   0          97s

nginx-2-l54dz                               1/1     Running   0          97s

nginx-2-t49mk                               1/1     Running   0          96s

nginx-2-t55h8                               1/1     Running   0          96s

从部署结果可以看到,每个pod都创建了一个PVC,这个是原生的Deployment不能实现的。

注意:

每个被自动创建的 PVC 会有一个 ownerReference 指向 CloneSet,因此 CloneSet 被删除时,它创建的所有 Pod 和 PVC 都会被删除。

每个被 CloneSet 创建的 Pod 和 PVC,都会带一个 apps.kruise.io/cloneset-instance-id: xxx 的 label。关联的 Pod 和 PVC 会有相同的 instance-id,且它们的名字后缀都是这个 instance-id。

如果一个 Pod 被 CloneSet controller 缩容删除时,这个 Pod 关联的 PVC 都会被一起删掉。

如果一个 Pod 被外部直接调用删除或驱逐时,这个 Pod 关联的 PVC 还都存在;并且 CloneSet controller 发现数量不足重新扩容时,新扩出来的 Pod 会复用原 Pod 的 instance-id 并关联原来的 PVC。

当 Pod 被重建升级时,关联的 PVC 会跟随 Pod 一起被删除、新建。

当 Pod 被原地升级时,关联的 PVC 会持续使用。

4、指定 Pod 缩容

当一个 CloneSet 被缩容时,有时候用户需要指定一些 Pod 来删除。这对于 StatefulSet 或者 Deployment 来说是无法实现的,因为 StatefulSet 要根据序号来删除 Pod,而 Deployment/ReplicaSet 目前只能根据控制器里定义的排序来删除。

CloneSet 允许用户在缩小 replicas 数量的同时,指定想要删除的 Pod 名字。

现在我们来修改上面例子的部署文件,指定删除nginx-2-t55h8这个Pod

apiVersion: apps.kruise.io/v1alpha1

kind: CloneSet

metadata:

labels:

app: nginx-2

name: nginx-2

spec:

replicas: 4

scaleStrategy:

podsToDelete:

- nginx-2-t55h8

然后更新yaml文件

[root@qd01-stop-k8s-master001 demo]# kubectl apply -f CloneSet.yaml

cloneset.apps.kruise.io/nginx-2 configured

[root@qd01-stop-k8s-master001 demo]# kubectl get po|grep nginx

nginx-2-b5fdd                               1/1     Running   0          11m

nginx-2-jw2zp                               1/1     Running   0          11m

nginx-2-l54dz                               1/1     Running   0          11m

nginx-2-t49mk                               1/1     Running   0          11m

现在看输入结果,已经没有nginx-2-t55h8这个Pod了

这个功能很实用,比如某台机器故障了,或者负载太高,你想删除指定的pod。

5、升级功能

CloneSet 提供了和 Advanced StatefulSet 相同的 3 个升级方式,默认为 ReCreate:

ReCreate: 控制器会删除旧 Pod 和它的 PVC,然后用新版本重新创建出来。

InPlaceIfPossible: 控制器会优先尝试原地升级 Pod,如果不行再采用重建升级。目前,只有修改 spec.template.metadata.* 和 spec.template.spec.containers[x].image 这些字段才可以走原地升级。

InPlaceOnly: 控制器只允许采用原地升级。因此,用户只能修改上一条中的限制字段,如果尝试修改其他字段会被 Kruise 拒绝。

现在我们来尝试原地升级Pod功能,把nginx镜像由nginx:alpine 升级为 nginx:latest

首先修改yaml文件,这里只粘贴出文件的修改的部分

apiVersion: apps.kruise.io/v1alpha1

kind: CloneSet

...

spec:

replicas: 4

updateStrategy:

type: InPlaceIfPossible

inPlaceUpdateStrategy:

gracePeriodSeconds: 10

......

spec:

containers:

- name: nginx

image: nginx

执行升级

[root@qd01-stop-k8s-master001 demo]# kubectl apply -f CloneSet.yaml

cloneset.apps.kruise.io/nginx-2 configured

使用 kubectl describe查看升级过程

Events:

Type     Reason                  Age                FromMessage

----     ------                  ----               ----                     -------

Warning  FailedScheduling        59m                default-scheduler        0/22 nodes are available: 22 pod has unbound immediate PersistentVolumeClaims.

Warning  FailedScheduling        59m                default-scheduler        0/22 nodes are available: 22 pod has unbound immediate PersistentVolumeClaims.

Warning  FailedScheduling        59m                default-scheduler        0/22 nodes are available: 22 pod has unbound immediate PersistentVolumeClaims.

Normal   Scheduled               59m                default-scheduler        Successfully assigneddefault/nginx-2-l54dztoqd01-stop-k8s-node007.ps.easou.com

Normal   SuccessfulAttachVolume  59m                attachdetach-controller  AttachVolume.Attach succeeded forvolume"pvc-e5302eab-a9f2-4a71-a5a3-4cd43205e8a0"

Normal   Pulling                 58m                kubelet                  Pulling image "nginx:alpine"

Normal   Pulled                  58m                kubelet                  Successfully pulled image "nginx:alpine"in6.230045975s

Normal   Killing                 55s                kubelet                  Container nginx definition changed, will be restarted

Normal   Pulling                 55s                kubelet                  Pulling image "nginx"

Normal   Pulled                  26s                kubelet                  Successfully pulled image "nginx"in29.136659264s

Normal   Created                 23s (x2 over 58m)  kubelet                  Created container nginx

Normal   Started                 23s (x2 over 58m)  kubelet                  Started container nginx

从输出可以看到,Container nginx definition changed, will be restarted,Pod并没有删除在重建,而是在原来的基础上直接更新了镜像文件,并重启了服务。

原地升级减少了删除重建环节,节省了升级时间和资源调度频率。。。

6、Partition 分批灰度

Partition 的语义是 保留旧版本 Pod 的数量或百分比,默认为 0。这里的 partition 不表示任何 order 序号。

在发布过程中设置了 partition:

如果是数字,控制器会将 (replicas - partition) 数量的 Pod 更新到最新版本。

如果是百分比,控制器会将 (replicas * (100% - partition)) 数量的 Pod 更新到最新版本。

现在我将上面的例子的 image 更新为 nginx:1.19.6-alpine 并且设置 partition=3

kind: CloneSet

metadata:

labels:

app: nginx-2

name: nginx-2

spec:

replicas: 5

updateStrategy:

type: InPlaceIfPossible

inPlaceUpdateStrategy:

gracePeriodSeconds: 10

partition: 3

selector:

matchLabels:

app: nginx-2

template:

metadata:

labels:

app: nginx-2

spec:

containers:

- name: nginx

image: nginx:1.19.6-alpine

查看结果

Status:

Available Replicas:      5

Collision Count:         0

Label Selector:          app=nginx-2

Observed Generation:     6

Ready Replicas:          5

Replicas:                5

UpdateRevision:         nginx-2-7b44cb9c8

Updated Ready Replicas:  2

Updated Replicas:        2

Events:

Type    Reason                      Age    FromMessage

----    ------                      ----   ----                 -------

Normal  SuccessfulUpdatePodInPlace  45m    cloneset-controller  successfully updatepod nginx-2-l54dzin-place(revision nginx-2-5879fd9f7)

Normal  SuccessfulUpdatePodInPlace  44m    cloneset-controller  successfully updatepod nginx-2-t49mkin-place(revision nginx-2-5879fd9f7)

Normal  SuccessfulUpdatePodInPlace  43m    cloneset-controller  successfully updatepod nginx-2-b5fddin-place(revision nginx-2-5879fd9f7)

Normal  SuccessfulUpdatePodInPlace  43m    cloneset-controller  successfully updatepod nginx-2-jw2zpin-place(revision nginx-2-5879fd9f7)

Normal  SuccessfulCreate            22m    cloneset-controller  succeed tocreatepod nginx-2-zpp8z

Normal  SuccessfulUpdatePodInPlace  5m22s  cloneset-controller  successfully updatepod nginx-2-zpp8zin-place(revision nginx-2-7b44cb9c8)

Normal  SuccessfulUpdatePodInPlace  4m55s  cloneset-controller  successfully updatepod nginx-2-jw2zpin-place(revision nginx-2-7b44cb9c8)

[root@qd01-stop-k8s-master001 demo]# kubectl get pod -L controller-revision-hash

NAMEREADY   STATUS    RESTARTS   AGE   CONTROLLER-REVISION-HASH

nginx-2-b5fdd                               1/1     Running   1          99m   nginx-2-5879fd9f7

nginx-2-jw2zp                               1/1     Running   2          99m   nginx-2-7b44cb9c8

nginx-2-l54dz                               1/1     Running   1          99m   nginx-2-5879fd9f7

nginx-2-t49mk                               1/1     Running   1          99m   nginx-2-5879fd9f7

nginx-2-zpp8z                               1/1     Running   1          19m   nginx-2-7b44cb9c8

从输出信息我们可以看到,Update Revision已经更新为nginx-2-7b44cb9c8,而Pod中只有两个Pod升级了。

由于我们设置了 partition=3,控制器只升级了 2 个 Pod。

Partition 分批灰度功能完善了原生的Pod升级方式,使得升级能够进行更灵活,能够进行灰度上线。超赞。。。

7、最后再演示下发布暂停

用户可以通过设置 paused 为 true 暂停发布,不过控制器还是会做 replicas 数量管理:

首先,我们将示例中image改为nginx:1.18.0 并设置副本数为10,修改后更新yaml,运行结果如下:

[root@qd01-stop-k8s-master001 demo]#  kubectl get po -o=jsonpath='{range .items[*]}{"\n"}{.metadata.name}{":\t"}{range .spec.containers[*]}{.image}{", "}{end}{end}'|sort

nginx-2-7lzx9:  nginx:1.18.0,

nginx-2-b5fdd:  nginx:1.18.0,

nginx-2-jw2zp:  nginx:1.18.0,

nginx-2-l54dz:  nginx:1.18.0,

nginx-2-nknrt:  nginx:1.18.0,

nginx-2-rgmsc:  nginx:1.18.0,

nginx-2-rpr5z:  nginx:1.18.0,

nginx-2-t49mk:  nginx:1.18.0,

nginx-2-v2bpx:  nginx:1.18.0,

nginx-2-zpp8z:  nginx:1.18.0,

现在我们修改yaml文件,将image修改为nginx:alpine 执行更新,运行如下

[root@qd01-stop-k8s-master001 demo]#  kubectl get po -o=jsonpath='{range .items[*]}{"\n"}{.metadata.name}{":\t"}{range .spec.containers[*]}{.image}{", "}{end}{end}'|sort

nginx-2-7lzx9:  nginx:1.18.0,

nginx-2-b5fdd:  nginx:1.18.0,

nginx-2-jw2zp:  nginx:1.18.0,

nginx-2-l54dz:  nginx:1.18.0,

nginx-2-nknrt:  nginx:alpine,

nginx-2-rgmsc:  nginx:alpine,

nginx-2-rpr5z:  nginx:alpine,

nginx-2-t49mk:  nginx:1.18.0,

nginx-2-v2bpx:  nginx:alpine,

nginx-2-zpp8z:  nginx:1.18.0,

现在看到,有4个pod的image已经更新为nginx:alpine 然后我们再次修改yaml文件,添加paused: true

spec:

replicas: 10

updateStrategy:

paused: true

type: InPlaceIfPossible

inPlaceUpdateStrategy:

gracePeriodSeconds: 10

再次执行apply,更新yaml,再次查看更新进度,发现pod并没有继续更新了,已经暂停升级image了

[root@qd01-stop-k8s-master001 demo]#  kubectl get po -o=jsonpath='{range .items[*]}{"\n"}{.metadata.name}{":\t"}{range .spec.containers[*]}{.image}{", "}{end}{end}'|sort

nginx-2-7lzx9:  nginx:1.18.0,

nginx-2-b5fdd:  nginx:1.18.0,

nginx-2-jw2zp:  nginx:1.18.0,

nginx-2-l54dz:  nginx:1.18.0,

nginx-2-nknrt:  nginx:alpine,

nginx-2-rgmsc:  nginx:alpine,

nginx-2-rpr5z:  nginx:alpine,

nginx-2-t49mk:  nginx:1.18.0,

nginx-2-v2bpx:  nginx:alpine,

nginx-2-zpp8z:  nginx:1.18.0,

最后把paused: true取消,再次apply yaml文件,升级会继续。。。

[root@qd01-stop-k8s-master001 demo]#  kubectl get po -o=jsonpath='{range .items[*]}{"\n"}{.metadata.name}{":\t"}{range .spec.containers[*]}{.image}{", "}{end}{end}'|sort

nginx-2-7lzx9:  nginx:alpine,

nginx-2-b5fdd:  nginx:alpine,

nginx-2-jw2zp:  nginx:alpine,

nginx-2-l54dz:  nginx:alpine,

nginx-2-nknrt:  nginx:alpine,

nginx-2-rgmsc:  nginx:alpine,

nginx-2-rpr5z:  nginx:alpine,

nginx-2-t49mk:  nginx:alpine,

nginx-2-v2bpx:  nginx:alpine,

nginx-2-zpp8z:  nginx:alpine,

以上就是整个发布暂停的演示,这个功能好处就是;我们在升级的过程中可以随时中断升级。

除此之外,CloneSet还有很多特性,例如:MaxUnavailable 最大不可用数量、MaxSurge 最大弹性数量、升级顺序、打散策略、生命周期钩子等,鉴于文章篇幅,这些特性不再演示了,有需要的可以查看官方文档。

【编辑推荐】

【责任编辑:姜华 TEL:(010)68476606】

点赞 0

相关文章:

  • arduino as5048工作原理_Arduino 真的可以用来开发产品吗?分享一个电子工程师的Arduino使用心得分享!...
  • jquery 多个文本框赋值_jquery为input赋值方法总结
  • nslookup 包含在那个包中_nslookup详解(name server lookup)( 域名查询)
  • double 去掉小数点_怎么去掉double后面的零0及取得double的小数部分的有效位 | 学步园...
  • 对一个字段赋值默认值_Java入门基础学习,成为一个Java程序员的必备知识
  • adb 重命名_adb无法连接设备?只需要这五步就能解决
  • sklearn中lstm_LSTM的时序应用
  • python中字符串之间的比较_【python】比较字符串中不同的地方
  • 双摄像头另一个有什么用_手机双摄像头为什么有前后和后双两种?各有什么用?...
  • deepin应用分发_Deepin应用商店发布2020年度十佳应用 QQ音乐荣誉上榜
  • apk提取加密素材_WDF资源加密及解密工具 – 素材防偷专用工具(附带教程)
  • linux pandas教程_Pandas 学习笔记
  • 爬虫爬评书吧_爬虫学习:xpath爬取评书网
  • orcad如何设置模块化设计_使用OrCAD设计多个相同功能模块电路可以使用层次化设计...
  • python中定制类_Python定制类的方法总结
  • [nginx文档翻译系列] 控制nginx
  • 「前端」从UglifyJSPlugin强制开启css压缩探究webpack插件运行机制
  • 77. Combinations
  • FastReport在线报表设计器工作原理
  • happypack两次报错的问题
  • java B2B2C 源码多租户电子商城系统-Kafka基本使用介绍
  • Javascripit类型转换比较那点事儿,双等号(==)
  • javascript面向对象之创建对象
  • LeetCode算法系列_0891_子序列宽度之和
  • MySQL用户中的%到底包不包括localhost?
  • PHP 使用 Swoole - TaskWorker 实现异步操作 Mysql
  • PyCharm搭建GO开发环境(GO语言学习第1课)
  • Transformer-XL: Unleashing the Potential of Attention Models
  • 从零开始的无人驾驶 1
  • 从输入URL到页面加载发生了什么
  • 订阅Forge Viewer所有的事件
  • 浅谈Kotlin实战篇之自定义View图片圆角简单应用(一)
  • 如何设计一个比特币钱包服务
  • 什么是Javascript函数节流?
  • 腾讯大梁:DevOps最后一棒,有效构建海量运营的持续反馈能力
  • 一个JAVA程序员成长之路分享
  • 在Docker Swarm上部署Apache Storm:第1部分
  • python最赚钱的4个方向,你最心动的是哪个?
  • ​​​​​​​ubuntu16.04 fastreid训练过程
  • ​用户画像从0到100的构建思路
  • ​总结MySQL 的一些知识点:MySQL 选择数据库​
  • ###C语言程序设计-----C语言学习(3)#
  • #LLM入门|Prompt#1.8_聊天机器人_Chatbot
  • #NOIP 2014# day.1 生活大爆炸版 石头剪刀布
  • #pragma pack(1)
  • #我与Java虚拟机的故事#连载05:Java虚拟机的修炼之道
  • (06)Hive——正则表达式
  • (Python) SOAP Web Service (HTTP POST)
  • (附源码)springboot 校园学生兼职系统 毕业设计 742122
  • (附源码)计算机毕业设计SSM教师教学质量评价系统
  • (剑指Offer)面试题34:丑数
  • (六) ES6 新特性 —— 迭代器(iterator)
  • (十三)Flask之特殊装饰器详解
  • (十三)Java springcloud B2B2C o2o多用户商城 springcloud架构 - SSO单点登录之OAuth2.0 根据token获取用户信息(4)...
  • (学习日记)2024.03.25:UCOSIII第二十二节:系统启动流程详解