Kubernetes之Scheduler详解

本文尝试从Kubernetes Scheduler的功能介绍、交互逻辑、伪代码实现、最佳实践、自定义Scheduler举例及其历史演进6个方面进行详细阐述。希望对您有所帮助!

一、Kubernetes Scheduler 功能

Kubernetes Scheduler 是 Kubernetes 集群的核心组件之一,负责将新创建的 Pod 分配到合适的节点上。它根据一系列规则和策略,确保集群资源的最佳利用和应用的高效运行。以下是 Kubernetes Scheduler 的功能详解。

1. Scheduler 工作流程

Kubernetes Scheduler 的工作流程主要包括以下几个步骤:

  1. 监听未分配的 Pod:Scheduler 监听 API Server,当有新的 Pod 被创建且未绑定到任何节点时,Scheduler 会将其加入调度队列中。
  2. 预选节点(Filtering):Scheduler 通过一系列过滤规则筛选出符合条件的节点。例如,节点是否有足够的资源(CPU、内存等)、节点是否满足 Pod 的亲和性/反亲和性规则等。
  3. 优选节点(Scoring):对通过过滤的节点进行打分,依据不同的优选规则对节点进行评分(如节点资源的剩余情况、Pod 分布等),最终选择得分最高的节点。
  4. 绑定 Pod 到节点:Scheduler 将 Pod 绑定到选定的节点,API Server 会更新 Pod 的状态。

2. Scheduler 的主要功能

节点过滤(Predicates)

节点过滤是调度过程中的第一步,主要包括以下几种过滤规则:

  • PodFitsResources:检查节点是否有足够的资源(CPU、内存等)供 Pod 使用。
  • PodFitsHostPorts:检查节点上是否有指定的主机端口可用。
  • PodFitsHost:检查 Pod 是否要求运行在特定的节点上。
  • NoDiskConflict:检查节点上是否有 Pod 使用了同一持久卷。
  • MatchNodeSelector:检查节点标签是否满足 Pod 的节点选择器要求。
  • CheckNodeUnschedulable:检查节点是否可调度。
  • PodToleratesNodeTaints:检查 Pod 是否容忍节点的污点。
节点优选(Priorities)

在通过过滤规则后,Scheduler 会对符合条件的节点进行打分,依据不同的优选规则对节点进行评分:

  • LeastRequestedPriority:优先选择资源请求最少的节点。
  • BalancedResourceAllocation:优先选择资源分配最平衡的节点。
  • NodePreferAvoidPodsPriority:优先选择没有被其他 Pod 标记为“避开”的节点。
  • NodeAffinityPriority:依据节点亲和性规则对节点进行打分。
  • TaintTolerationPriority:依据污点容忍规则对节点进行打分。
Pod 亲和性和反亲和性(Pod Affinity and Anti-Affinity)

Pod 亲和性和反亲和性允许用户定义更复杂的调度规则,以确保 Pod 能够调度到特定的节点或避免调度到某些节点。例如,可以定义 Pod 必须与某些标签的 Pod 在同一节点上,或者必须与某些标签的 Pod 不在同一节点上。

节点亲和性(Node Affinity)

节点亲和性允许用户定义 Pod 只能调度到某些特定的节点。它是节点选择器的更灵活和表达力更强的形式,可以基于节点的标签进行配置。

Taints 和 Tolerations

Taints 和 Tolerations 用于避免 Pod 被调度到不适合的节点。节点可以有污点(Taints),只有容忍这些污点(Tolerations)的 Pod 才能被调度到这些节点上。

3. 自定义 Scheduler

Kubernetes 允许用户编写和部署自定义的调度器,替代默认的调度器或与之共存。以下是编写自定义调度器的基本步骤:

  1. 创建调度器插件:基于 Kubernetes 提供的调度框架,创建新的调度插件。调度插件可以是过滤插件、打分插件、预绑定插件等。
  2. 配置调度器:在 kube-scheduler 配置文件中添加或修改调度插件。
  3. 部署自定义调度器:将自定义调度器部署到 Kubernetes 集群中,并在 Pod 定义中指定使用自定义调度器。

4. 调试和监控

Kubernetes Scheduler 提供了多种调试和监控工具,以便用户了解调度过程并解决调度问题。例如:

  • 调度事件日志:Scheduler 会记录调度过程中的事件日志,可以通过查看这些日志来了解调度过程。
  • 调度指标:Scheduler 提供了一些 Prometheus 指标,可以用来监控调度性能和调度决策。

通过上述功能和工具,Kubernetes Scheduler 能够实现灵活、高效的调度策略,满足不同应用的需求。

二、Kubernetes Scheduler与其他组件交互示意图

下图表示 Kubernetes Scheduler 与其他组件交互过程 。图示包括 API Server、Scheduler、Controller Manager、etcd、Kubelet 和节点。

示意图

User API Server Scheduler Controller Manager etcd Kubelet Node Create Pod Store Pod Spec Acknowledge Pod Creation Notify of Pending Pod Get Pod Spec Get Node Information Node Information Filter Nodes Score Nodes Bind Pod to Node Update Pod Binding Acknowledge Binding Notify of Pod Update Get Pod Spec Update Pod Status Notify of Pod Assignment Get Pod Spec Create and Start Pod Pod Running Update Pod Status Store Pod Status Pod Running User API Server Scheduler Controller Manager etcd Kubelet Node

交互流程解释

  1. 用户创建 Pod

    • 用户向 API Server 提交 Pod 创建请求。
    • API Server 将 Pod 的配置信息存储在 etcd 中,并确认创建成功。
  2. 调度 Pod

    • API Server 通知 Scheduler 有新的待调度 Pod。
    • Scheduler 从 API Server 获取 Pod 的配置信息,并从 etcd 获取集群中节点的信息。
    • Scheduler 过滤和打分节点,选择最合适的节点。
    • Scheduler 将 Pod 绑定到选定的节点,并通知 API Server。
  3. 更新 Pod 绑定信息

    • API Server 将 Pod 的绑定信息更新到 etcd。
    • Scheduler 确认绑定成功。
  4. 控制器管理 Pod

    • API Server 通知 Controller Manager Pod 的更新信息。
    • Controller Manager 从 etcd 获取 Pod 配置信息,并更新 Pod 的状态。
  5. Kubelet 启动 Pod

    • API Server 通知 Kubelet Pod 已分配到其管理的节点上。
    • Kubelet 从 etcd 获取 Pod 的配置信息。
    • Kubelet 在节点上创建并启动 Pod。
    • 节点返回 Pod 的运行状态给 Kubelet。
    • Kubelet 更新 Pod 的状态到 API Server。
  6. 存储 Pod 状态并通知用户

    • API Server 将 Pod 的运行状态存储到 etcd。
    • API Server 通知用户 Pod 处于运行状态。

通过这个交互示意图和解释,可以清晰地了解 Kubernetes Scheduler 与其他组件的交互流程和机制。

三、Kubernetes Scheduler伪代码实现

下面是一个使用 Go 语言编写的 Kubernetes Scheduler 功能的伪代码示例。此示例包括基本的调度流程,包括从 API Server 获取未调度的 Pod,筛选节点,评分节点,并将 Pod 绑定到选定的节点。

Kubernetes Scheduler 伪代码

package mainimport ("context""fmt""log""time""k8s.io/client-go/kubernetes""k8s.io/client-go/tools/clientcmd""k8s.io/client-go/util/homedir""path/filepath""k8s.io/kubernetes/pkg/scheduler""k8s.io/kubernetes/pkg/scheduler/framework/plugins/noderesources""k8s.io/kubernetes/pkg/scheduler/framework/plugins/registry""k8s.io/kubernetes/pkg/scheduler/framework/runtime"
)func main() {// 加载Kubernetes配置var kubeconfig stringif home := homedir.HomeDir(); home != "" {kubeconfig = filepath.Join(home, ".kube", "config")}config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)if err != nil {log.Fatalf("Error building kubeconfig: %s", err.Error())}// 创建Kubernetes客户端clientset, err := kubernetes.NewForConfig(config)if err != nil {log.Fatalf("Error creating Kubernetes client: %s", err.Error())}// 注册调度插件registry := registry.NewRegistry()pluginFactory := noderesources.NewFitregistry.Register("NodeResourcesFit", pluginFactory)// 创建调度框架schedulerFramework, err := runtime.NewFramework(registry, nil, nil)if err != nil {log.Fatalf("Error creating scheduler framework: %s", err.Error())}// 创建自定义调度器sched := scheduler.New(clientset,schedulerFramework,nil,context.TODO(),"custom-scheduler",)// 主调度循环for {pod := getPendingPod(clientset)if pod != nil {nodes := getNodes(clientset)filteredNodes := filterNodes(pod, nodes)if len(filteredNodes) > 0 {bestNode := scoreNodes(pod, filteredNodes)bindPodToNode(clientset, pod, bestNode)}}time.Sleep(1 * time.Second)}
}// 获取未调度的Pod
func getPendingPod(clientset *kubernetes.Clientset) *v1.Pod {pods, err := clientset.CoreV1().Pods("").List(context.TODO(), metav1.ListOptions{})if err != nil {log.Fatalf("Error listing pods: %s", err.Error())}for _, pod := range pods.Items {if pod.Spec.NodeName == "" {return &pod}}return nil
}// 获取所有节点
func getNodes(clientset *kubernetes.Clientset) []v1.Node {nodes, err := clientset.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{})if err != nil {log.Fatalf("Error listing nodes: %s", err.Error())}return nodes.Items
}// 节点过滤
func filterNodes(pod *v1.Pod, nodes []v1.Node) []v1.Node {var filteredNodes []v1.Nodefor _, node := range nodes {if nodeHasSufficientResources(pod, &node) {filteredNodes = append(filteredNodes, node)}}return filteredNodes
}// 检查节点是否有足够资源
func nodeHasSufficientResources(pod *v1.Pod, node *v1.Node) bool {// 实现资源检查逻辑,如CPU和内存是否足够return true
}// 节点评分
func scoreNodes(pod *v1.Pod, nodes []v1.Node) *v1.Node {var bestNode *v1.Nodevar highestScore intfor _, node := range nodes {score := calculateNodeScore(pod, &node)if score > highestScore {highestScore = scorebestNode = &node}}return bestNode
}// 计算节点分数
func calculateNodeScore(pod *v1.Pod, node *v1.Node) int {// 实现评分逻辑,如节点的资源利用率、亲和性等return 0
}// 绑定Pod到节点
func bindPodToNode(clientset *kubernetes.Clientset, pod *v1.Pod, node *v1.Node) {binding := &v1.Binding{ObjectMeta: metav1.ObjectMeta{Name: pod.Name, Namespace: pod.Namespace},Target: v1.ObjectReference{Kind: "Node",Name: node.Name,},}err := clientset.CoreV1().Pods(pod.Namespace).Bind(context.TODO(), binding, metav1.CreateOptions{})if err != nil {log.Fatalf("Error binding pod: %s", err.Error())} else {fmt.Printf("Successfully bound pod %s to node %s\n", pod.Name, node.Name)}
}

伪代码解释

  1. 主函数

    • 加载 Kubernetes 配置并创建 Kubernetes 客户端。
    • 注册调度插件并创建调度框架。
    • 创建自定义调度器,并进入主调度循环。
  2. 主调度循环

    • 获取未调度的 Pod。
    • 获取所有节点。
    • 过滤节点,找出符合条件的节点。
    • 对符合条件的节点进行评分,选择得分最高的节点。
    • 将 Pod 绑定到选定的节点。
  3. 辅助函数

    • getPendingPod:获取未调度的 Pod。
    • getNodes:获取所有节点。
    • filterNodes:根据资源要求过滤节点。
    • nodeHasSufficientResources:检查节点是否有足够资源。
    • scoreNodes:对符合条件的节点进行评分。
    • calculateNodeScore:计算节点的分数。
    • bindPodToNode:将 Pod 绑定到选定的节点。

这个伪代码示例展示了一个基本的自定义调度器的工作流程和关键函数。实际实现中,你可以根据具体需求扩展和修改这些函数。

下面是表示上述自定义 Kubernetes Scheduler 伪代码的调用图。这张图展示了调度器的主要流程,包括获取未调度的 Pod、获取节点、过滤节点、评分节点以及将 Pod 绑定到选定节点的过程。

Nodes
etcd
Kubernetes API
No
Yes
No
Yes
Communicates
Fetch Pods
Fetch Nodes
Bind Pod
Stores
Node1
Node2
Node3
Filter Nodes
Score Nodes
Pod & Node Information
API Server
Start Scheduler
Get Pending Pod
Get Nodes
Bind Pod to Node
Pod Found?
Filtered Nodes Found?
Select Best Node
Log Success

图解说明

  1. Start Scheduler

    • 调度器启动并进入主循环。
  2. Get Pending Pod

    • 从 API Server 获取未调度的 Pod。
  3. Pod Found?

    • 判断是否找到未调度的 Pod,如果没有找到则返回主循环继续检查。
  4. Get Nodes

    • 从 API Server 获取所有节点的信息。
  5. Filter Nodes

    • 根据资源要求和调度规则过滤节点。
  6. Filtered Nodes Found?

    • 判断是否有符合条件的节点,如果没有找到则返回主循环。
  7. Score Nodes

    • 对符合条件的节点进行评分。
  8. Select Best Node

    • 选择得分最高的节点。
  9. Bind Pod to Node

    • 将 Pod 绑定到选定的节点,并更新 API Server。
  10. Log Success

    • 记录绑定成功的日志。
  11. Communicates with Kubernetes API

    • 调度器通过 API Server 与 Kubernetes 交互,获取 Pod 和节点信息,更新绑定状态。
  12. etcd

    • API Server 将 Pod 和节点信息存储到 etcd 中。
  13. Nodes

    • 显示集群中的节点,调度器对这些节点进行过滤和评分。

该图直观地展示了自定义 Kubernetes Scheduler 的主要工作流程和与其他组件的交互。

四、自定义 Kubernetes Scheduler最佳实践

自定义 Kubernetes Scheduler 是一个高级主题,需要仔细考虑和实现,确保它能够有效地管理和调度 Pod 到集群中的节点。以下是一些关于自定义 Kubernetes Scheduler 的最佳实践:

1. 确定需求和场景

在开始之前,确保明确你的需求和场景。了解你想要实现的特定调度逻辑和策略,例如特定的资源分配、亲和性/反亲和性需求、定制化的节点选择算法等。理解这些需求将有助于指导你设计和实现自定义 Scheduler。

2. 使用 Kubernetes 提供的调度框架和插件

Kubernetes 提供了灵活的调度框架和各种插件,例如节点资源调度、亲和性/反亲和性、污点和容忍等。在自定义 Scheduler 时,可以基于现有的调度框架进行扩展和定制化,使用已有的调度插件或编写新的插件以满足特定需求。

3. 编写调度器代码

编写自定义 Scheduler 的代码时,考虑以下几点:

  • 初始化 Kubernetes 客户端:确保能够与 Kubernetes API Server 进行通信。
  • 注册调度插件:根据需要注册适合的调度插件,如节点资源调度插件、亲和性/反亲和性插件等。
  • 实现调度逻辑:在主循环中实现从 API Server 获取未调度的 Pod、获取节点列表、过滤和评分节点、绑定 Pod 到节点等核心调度逻辑。
  • 错误处理和日志记录:添加适当的错误处理机制,并记录调度过程中的关键事件和决策。

4. 测试和验证

在部署自定义 Scheduler 之前,进行充分的测试和验证是必不可少的步骤。确保你的 Scheduler 能够正确地处理各种场景和边界条件,例如不同类型的 Pod、不同的节点状态、并发调度等。

5. 部署和监控

部署自定义 Scheduler 到 Kubernetes 集群后,确保能够有效地监控其性能和行为。使用 Kubernetes 提供的监控工具(如 Prometheus)或自定义指标来收集调度器的运行数据,并及时调整和优化调度策略。

6. 考虑安全性和可扩展性

在设计和实现自定义 Scheduler 时,要考虑安全性和可扩展性。确保 Scheduler 的操作是安全的,并且可以在集群的规模和负载增加时保持稳定和高效。

示例实现

以下是一个简单的示例实现,展示了如何使用 Go 和 Kubernetes 客户端库来创建自定义 Scheduler:

  • 初始化 Kubernetes 客户端和调度器框架。
  • 注册节点资源调度插件。
  • 实现调度逻辑,包括节点过滤、评分和绑定 Pod 到节点。
  • 在主循环中运行调度器,并持续监视未调度的 Pod。
// 请参考前面给出的Go语言伪代码实现。

通过遵循这些最佳实践,你可以成功地设计、开发和部署自定义 Kubernetes Scheduler,以满足特定的业务需求和调度策略。

五、自定义Kubernetes Scheduler示例

自定义 Kubernetes Scheduler 允许你定义调度逻辑以满足特定需求。下面是如何创建、配置和部署自定义 Scheduler 的详细步骤。

步骤 1:编写自定义调度器

你可以使用 Go 语言编写自定义调度器。以下是一个基本的自定义调度器示例:

package mainimport ("context""fmt""log""time""k8s.io/client-go/kubernetes""k8s.io/client-go/tools/clientcmd""k8s.io/client-go/util/homedir""path/filepath""k8s.io/kubernetes/pkg/scheduler""k8s.io/kubernetes/pkg/scheduler/framework/plugins/noderesources""k8s.io/kubernetes/pkg/scheduler/framework/plugins/registry""k8s.io/kubernetes/pkg/scheduler/framework/runtime"
)func main() {var kubeconfig stringif home := homedir.HomeDir(); home != "" {kubeconfig = filepath.Join(home, ".kube", "config")}config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)if err != nil {log.Fatalf("Error building kubeconfig: %s", err.Error())}clientset, err := kubernetes.NewForConfig(config)if err != nil {log.Fatalf("Error creating Kubernetes client: %s", err.Error())}registry := registry.NewRegistry()pluginFactory := noderesources.NewFitregistry.Register("NodeResourcesFit", pluginFactory)schedulerFramework, err := runtime.NewFramework(registry, nil, nil)if err != nil {log.Fatalf("Error creating scheduler framework: %s", err.Error())}sched := scheduler.New(clientset,schedulerFramework,nil,context.TODO(),"custom-scheduler",)for {err := sched.Run(context.TODO())if err != nil {log.Printf("Error running scheduler: %s", err.Error())}time.Sleep(1 * time.Second)}
}

步骤 2:构建 Docker 镜像

为你的自定义调度器创建一个 Docker 镜像。首先,创建一个 Dockerfile:

FROM golang:1.17 as builderWORKDIR /go/src/custom-scheduler
COPY . .RUN go get -d -v ./...
RUN go build -o custom-scheduler .FROM alpine:latest
RUN apk --no-cache add ca-certificatesWORKDIR /root/
COPY --from=builder /go/src/custom-scheduler/custom-scheduler .CMD ["./custom-scheduler"]

然后构建镜像:

docker build -t custom-scheduler:latest .

步骤 3:创建 Kubernetes Deployment

创建一个 Deployment 来运行自定义调度器:

apiVersion: apps/v1
kind: Deployment
metadata:name: custom-schedulerlabels:app: custom-scheduler
spec:replicas: 1selector:matchLabels:app: custom-schedulertemplate:metadata:labels:app: custom-schedulerspec:containers:- name: custom-schedulerimage: custom-scheduler:latestimagePullPolicy: IfNotPresentcommand: ["./custom-scheduler"]serviceAccountName: system:scheduler

步骤 4:配置调度器名称

为你的 Pod 指定使用自定义调度器。在 Pod 定义中设置 schedulerName

apiVersion: v1
kind: Pod
metadata:name: example-pod
spec:schedulerName: custom-schedulercontainers:- name: example-containerimage: nginx

步骤 5:部署和验证

  1. 部署自定义调度器:

    kubectl apply -f custom-scheduler-deployment.yaml
    
  2. 创建一个使用自定义调度器的 Pod:

    kubectl apply -f example-pod.yaml
    
  3. 检查 Pod 是否使用自定义调度器成功调度:

    kubectl get pod example-pod -o jsonpath='{.spec.schedulerName}'
    

总结

通过以上步骤,你可以编写、构建、部署和使用自定义 Kubernetes Scheduler。这使你能够实现更灵活和特定需求的调度逻辑。

六、Kubernetes Scheduler历史演进

Kubernetes Scheduler 是 Kubernetes 集群管理系统的核心组件之一,它负责将未分配节点的 Pod 分配到合适的节点上。自 Kubernetes 项目启动以来,Kubernetes Scheduler 也经历了显著的演进。以下是 Kubernetes Scheduler 的历史演进:

1. Kubernetes 早期版本(2014-2015)

1.1. 初始设计
  • Kubernetes 于 2014 年开源,最初的调度器设计非常简单,主要基于静态调度策略,如 CPU 和内存资源。
  • 调度算法主要基于 “First Fit” 策略,即选择第一个满足资源要求的节点。
1.2. 调度器插件机制
  • 初始版本中,调度逻辑内嵌在调度器代码中,缺乏灵活性和扩展性。

2. Kubernetes 1.0(2015)

2.1. 初步稳定
  • Kubernetes 1.0 版本标志着 Kubernetes 的首次正式发布。
  • 调度器引入了更复杂的调度策略,如节点亲和性和反亲和性。

3. Kubernetes 1.2-1.5(2016-2017)

3.1. Pod 优先级和抢占
  • 引入 Pod 优先级和抢占机制,以便更好地处理资源紧张的场景。
  • 调度器能够根据优先级调整 Pod 的调度顺序。
3.2. 多调度器支持
  • Kubernetes 支持用户自定义调度器,使得在同一个集群中可以运行多个调度器实例。

4. Kubernetes 1.6-1.9(2017-2018)

4.1. 调度器扩展点
  • 引入调度器扩展点机制,使得用户可以插入自定义的调度策略和插件,增强调度器的可扩展性。
4.2. 事件驱动的调度
  • 调度器逐步从定期扫描变为事件驱动,更高效地响应 Pod 和节点状态的变化。

5. Kubernetes 1.10-1.13(2018-2019)

5.1. 调度框架(Scheduling Framework)
  • Kubernetes 1.11 引入了调度框架(Scheduling Framework),允许用户通过插件扩展调度器的行为。
  • 这一框架提供了多个扩展点,如预过滤、过滤、优选、绑定等。
5.2. 调度器性能优化
  • 持续的性能优化,提升调度器在大规模集群中的表现。

6. Kubernetes 1.14-1.19(2019-2020)

6.1. 调度框架逐步稳定
  • 调度框架功能逐步完善,用户可以更加灵活地自定义调度逻辑。
  • 增加了更多内置插件,提升了调度器的默认能力。
6.2. 调度器配置文件(Scheduler Configuration)
  • 引入调度器配置文件,允许用户通过配置文件定制调度器行为,而无需修改代码。

7. Kubernetes 1.20-1.23(2020-2021)

7.1. 调度框架的广泛采用
  • 调度框架被广泛采用,并逐渐成为定制调度逻辑的标准方式。
  • 更多的社区插件和企业插件被开发出来,满足不同场景的需求。
7.2. 性能和稳定性提升
  • 持续的性能和稳定性改进,使调度器能够在更大规模和更复杂的环境中运行。

8. Kubernetes 1.24+(2022-至今)

8.1. 提升调度器的智能化
  • 引入更多智能化的调度策略和算法,如机器学习驱动的调度。
  • 增加对异构资源(如 GPU、FPGA)的更好支持。
8.2. 多集群调度
  • 支持多集群环境中的调度需求,使得调度器能够跨多个 Kubernetes 集群进行资源调度。
8.3. 提升调度器的可观测性
  • 增加更多调度器的可观测性特性,使得管理员能够更好地了解调度决策和调度过程。

总结

Kubernetes Scheduler 的演进反映了 Kubernetes 社区对调度需求的不断理解和优化。随着 Kubernetes 的发展,调度器变得更加智能、灵活和高效,以应对现代应用程序的复杂需求和大规模集群的挑战。未来,调度器将继续演进,以支持更多新兴的计算资源和调度策略。

完。
希望对您有用!关注锅总,及时获得更多花里胡哨的运维实用操作!

一个秘密

在这里插入图片描述
锅总个人博客

https://gentlewok.blog.csdn.net/

锅总微信公众号
在这里插入图片描述

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

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

相关文章

Qwen2本地web Demo

Qwen2的web搭建(streamlit) 千问2前段时间发布了,个人觉得千问系列是我用过最好的中文开源大模型,所以这里基于streamlit进行一个千问2的web搭建,来进行模型的测试 一、硬件要求 该文档中使用的千问模型为7B-Instruct,需要5g以…

ROT5、ROT13、ROT18、ROT47全系列加解密小程序

ROT5、ROT13、ROT18、ROT47全系列加解密小程序 这几天在看CTF相关的课程,涉及到古典密码学和近代密码学还有现代密码学。自己编了一个关于ROT全系列的加、解密小程序。 ​ ROT5、ROT13、ROT18、ROT47 编码是一种简单的码元位置顺序替换暗码。此类编码具有可逆性&a…

【铂电阻测温】如何保证热电阻采集的可靠性

TPS02RAH的输出接口为I2C,支持主机动态更改模块I2C地址,实现了单I2C总线挂载多个TPS02RAH测温模块的功能。 TPS02RAH的输出接口为I2C,支持主机动态更改模块I2C地址,实现了单I2C总线挂载多个TPS02RAH测温模块的功能。 参考链接 【…

领夹麦克风什么样的好,麦克风品牌排行榜前十名,无线麦克风推荐

​在人人可做自媒体的时代,众多普通人加入自媒体。对拍视频的自媒体人,好内容是基础,好设备是保障。想提升视频音质需专业无线麦克风。现无线麦克风品牌多,如何少花钱买高性价比产品是问题。作为资深自媒体人,我用过的…

电子看板,实现生产现场数字化管理

如何提高生产效率、优化资源配置、保障产品质量,成为企业在激烈竞争中脱颖而出的关键。电子看板作为一种创新的生产管理工具,为实现生产现场数字化管理提供了有力支持。电子看板是生产现场的“智能窗口”,它能够实时、准确地展示各类关键信息…

《2024年新生代妈妈真实孕育状态洞察报告》

专注于行业分析与市场研究的专业机构易观分析,正式发布了其最新研究成果——《2024年新生代妈妈真实孕育状态洞察报告》。该报告深入探讨了新生代妈妈在孕育过程中的实际需求与挑战,通过对母婴行业的市场规模、消费行为、用户触媒习惯、用户关怀以及特定品类场景的细致分析,揭示…

日元跌破160大关,日本当局何时干预?

KlipC报道:6月26日,日元又跌了,美元兑日元跌破160的整关口,超过了4月日本官员在市场上干预的水平,创1986年来新低。美联储降息的可能性降低,市场预计日元有可能延续当前的弱势。 KlipC分析师David表示&…

Ubuntu 20.04安装显卡驱动、CUDA、Pytorch(2024.06最新)

文章目录 一、安装显卡驱动1.1 查看显卡型号1.2 根据显卡型号选择驱动1.3 获取下载链接1.4 查看下载的显卡驱动安装文件1.5 更新软件列表和安装必要软件、依赖1.6 卸载原有驱动1.7 禁用默认驱动1.8 安装lightdm显示管理器1.9 停止显示服务器1.10 在文本界面中,禁用X…

关于新零售的一些思考

本文作为2024上半年大量输入之后的核心思考之一。工作到一定阶段之后,思考的重要性越来越高,后续会把自己的个人思考记录在这个新系列《施展爱思考》。背景是上半年面临业务转型从电商到新零售,本文是相关大量输入之后的思考,对新…

浅析Resource Quota中limits计算机制

前言 在生产环境中,通常需要通过配置资源配额(Resource Quota)来限制一个命名空间(namespace)能使用的资源量。在资源紧张的情况下,常常需要调整工作负载(workload)的请求值&#xf…

生信实证系列Vol.15:如何用AlphaFold2,啪,一键预测100+蛋白质结构

"结构就是功能"——蛋白质的工作原理和作用取决于其3D形状。 2020年末,基于深度神经网络的AlphaFold2,一举破解了困扰生物学界长达五十年之久的“蛋白质折叠”难题,改变了科学研究的游戏规则,可以从蛋白质序列直接预测…

MySQL高级-索引-使用规则-前缀索引

文章目录 1、前缀索引2、前缀长度3、查询表数据4、查询表的记录总数5、计算并返回具有电子邮件地址(email)的用户的数量6、从tb_user表中计算并返回具有不同电子邮件地址的用户的数量7、计算唯一电子邮件地址(email)的比例相对于表…

VR加密方案常见问题有哪些?

在数字化时代,随着虚拟现实(VR)技术的迅速发展与普及,VR视频内容的安全传输成为关注焦点。为保护版权及敏感信息免遭非法复制或篡改,VR视频加密技术显得尤为重要。 首先,高效的加密算法对确保数据安全性至关…

动态流体工厂大屏

目录 一 设计原型 二 后台源码 一 设计原型 二 后台源码 namespace 动态流体工厂大屏 {public partial class Form1 : Form{public Form1(){InitializeComponent();}private void Form1_Load(object sender, EventArgs e){Task.Run(() >{while (true){this.Invoke(() >…

Linux之prometheus安装和使用简介(一)

一、prometheus简介 普罗米修斯Prometheus是一个开源系统监控和警报工具包,最初构建于SoundCloud。自2012年成立以来,许多公司和组织都采用了普罗米修斯,该项目拥有非常活跃的开发人员和用户社区。它现在是一个独立的开源项目,独立…

【深度学习】实践方法论

李宏毅深度学习笔记 优化问题 训练数据的损失不够低的时候,到底是模型偏差,还是优化的问题? 判断方法是通过比较不同的模型来判断模型现在到底够不够大 看到一个从来没有做过的问题,可以先跑一些比较小的、比较浅的网络&#x…

如何使用Hugging Face Transformers为情绪分析微调BERT?

情绪分析指用于判断文本中表达的情绪的自然语言处理(NLP)技术,它是客户反馈评估、社交媒体情绪跟踪和市场研究等现代应用背后的一项重要技术。情绪可以帮助企业及其他组织评估公众意见、提供改进的客户服务,并丰富产品或服务。 BERT的全称是来自Transfo…

编译VTK静态库

编译VTK静态库遇到问题 vtkCommonCore-9.3d.lib(vtkSMPToolsAPI.obj) : error LNK2019: unresolved external symbol "public: bool __cdecl vtk::detail::smp::vtkSMPToolsImpl<1>::IsParallelScope(void)" (?IsParallelScope?$vtkSMPToolsImpl$00smpdetai…

网信办算法备案详细解读——中国人工智能监管新规

中国出台新规旨在防范人工智能的相关风险&#xff0c;且规定了从事人工智能相关业务的实体的合规义务。 要点&#xff1a; • 中华人民共和国&#xff08;中国&#xff09; 通过推出并实施如下一系列法规&#xff0c;在人工智能监管方面领先于其他司法管辖 区&#xff1a…

Linux源码阅读笔记07-进程管理4大常用API函数

find_get_pid find_get_pid(...)函数功能&#xff1a;根据进程编号获取对应的进程描述符&#xff0c;具体Linux内核源码对应函数设计如下&#xff1a; 获取进程描述符&#xff0c;且描述符的count1&#xff0c;表示进程多一个用户 pid_task pid_task(...)函数功能&#xff1…