k8s java程序实现kubernetes Controller Operator 使用CRD 学习总结
k8s java程序实现kubernetes Controller & Operator 使用CRD 学习总结
大纲
- 原理
- Controller 与 Operator
- 自定义资源定义 CRD ( CustomResourceDefinition)
- kubernetes-client
- 使用java fabric8io/kubernetes-client操作k8s 原生资源
- 使用java abric8io/kubernetes-clientt操作CRD watch状态变更
- 权限处理
- 实例:用java开发一个数据库表监控Operator
- 数据库表监控CRD 创建
- springboot k8s Operator 程序开发
- 部署springboot k8s Operator到k8s集群
- 创建自定义资源 程序实现监控
原文地址 https://blog.csdn.net/liuyij3430448/article/details/129534732
原理
k8s中 “Pod Service Deployment”等都是一种资源,k8s的作用就是管理这些资源。(当资源创建,更新,删除后会有对应的操作)。
单纯的资源是没有任何意义的,需要配合对应的Controller[控制器] 来管理资源
例如
Pod 的扩容 就是使用ReplicationController等实现的,单纯的Pod只是一个存储在Etcd中的数据
当k8s 内置的资源无法满足我们的需求时,可以使用k8s提供的CustomResourceDefinition + 自定义controller实现自己的资源与资源控制
有了自定义的资源(CRD),但是没有相应的Controller对其进行操作,那这些资源也就只能简单的存储到k8s集群中了(etcd)。
因此还需要开发相应的Controller来对相应的CRD进行监听、处理业务逻辑
Controller & Operator
Controller就是一遵循k8s相关规范,然后连接到k8s master API 并监听CRD事件的进程(CRD的事件一般就是指:Add, Update, Delete)
Operator是一个更加复杂的Controller,还可以实现一些运维操作
Operator 官方资料 https://kubernetes.io/zh-cn/docs/concepts/extend-kubernetes/operator/
Operator 就是一种 Controller
Kubernetes 的 Operator 模式概念允许你在不修改 Kubernetes 自身代码的情况下,
通过为一个或多个自定义资源关联控制器来扩展集群的能力。
简单讲 Operator = 资源(可以是k8s内置资源或者自定义的CRD) + controller + 一些运维操作
例如本文中最后的实例
会创建一个数据库表监控CRD资源,在创建一个自己的controller,监控表的创建,保持指定数量行,删除表。 这一系列操作就是一个 Operator
CRD ( CustomResourceDefinition)
要使用自定义资源,就需要先在k8s集群中定义这个资源,定义资源就需要使用CustomResourceDefinition
注意:要使用CustomResourceDefinition, Kubernetes 服务器版本必须不低于版本 1.16.
创建CRD
官方文档 https://kubernetes.io/zh-cn/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/
以一个自定义的MyCrdTest 资源为例 CustomResourceDefinition.yaml文件中需要定 资源的名称,资源的组,资源的版本 以及spec等内容
# 定义自定义的 MyCrdTest 资源
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:# 名字必需与下面的 spec 字段匹配,并且格式为 '<名称的复数形式>.<组名>'name: mycrdtests.liuyjiang.mycrdtest.com
spec: # 组名称,用于 REST API: /apis/<组>/<版本>group: liuyjiang.mycrdtest.comnames:# 名称的复数形式,用于 URL:/apis/<组>/<版本>/<名称的复数形式>plural: mycrdtests# 名称的单数形式,作为命令行使用时和显示时的别名singular: mycrdtest# kind 通常是单数形式的驼峰命名(CamelCased)形式。你的资源清单会使用这一形式。kind: MyCrdTest# shortNames 允许你在命令行使用较短的字符串来匹配资源shortNames:- mct# 可以是 Namespaced 或 Cluster scope: Namespaced versions:- name: v1# 每个版本都可以通过服务标志启用/禁用。served: true# 必须将一个且只有一个版本标记为存储版本。storage: trueschema:openAPIV3Schema:type: objectproperties: #自定义CRD中的specspec:type: objectproperties:# 自定义的资源spec 中的属性 mymsgmymsg: type: string# 自定义的资源spec 中的属性 myarray myarray: type: arrayitems:type: string # 自定义的资源spec 中的属性 mynumber mynumber: type: integer#自定义CRD中的status status:type: object properties: mystatus: type: stringmyip: type: string
使用命令kubectl apply -f crd-simple.yaml 创建CRD 相关文件见 《/yaml/crd-simple.yaml》
这样自定义资源的定义就有了,接下来就可以创建自定义资源MyCrdTest
创建CRD定义的资源
上一步中创建了自定义资源定义CustomResourceDefinition 这样就可以基于定义的内容创建自定义资源MyCrdTest
my-crd-test.yaml 文件内容如下
# 这个就是对应crd-simple.yaml 中定义的
# api使用 crd中定义的组名称(group)+ 版本号(versions name)
apiVersion: "liuyjiang.mycrdtest.com/v1"
# kind使用 crd中定义的kind名称
kind: MyCrdTest
metadata:name: test-001
# 对应 crd-simple.yaml schema中的spec 配置
spec:mymsg: "hello world"mynumber: 3myarray: - aaabbbccc
# 对应 crd-simple.yaml schema中的status 配置
status:mystatus: "running"myip: "192.168.0.211"
使用kubectl apply -f my-crd-test.yaml 创建自定义资源MyCrdTest
查看CRD定义的资源
使用kubectl get 【资源】查看创建的资源
可以自定义 kubectl get 显示字段
自定义kubectl get 显示字段各式如下
kubectl get [资源类型] [资源名称] -o custom-columns=【显示的的字段】:【.资源配置】
例如yaml中配置
metadata:name: test-001
spec:mymsg: "hello world"
status:mystatus: "running"myip: "192.168.0.211"
使用以下命令查看内容 注意.号
kubectl get mct -o custom-columns=NAME:.metadata.name,MSG:.spec.mymsg,IP:.status.myip,STATUS:.status.mystatus
也可以使用模板文件
kubectl get mct -o custom-columns-file=tpl.txt模板文件tpl.txt内容为
NAME MSG IP STATUS
metadata.name spec.mymsg status.myip status.mystatus
这样一个自定义的资源就创建完成了,注意此时资源只存在Etcd中并没有对应的控制器来管理资源
kubernetes-client
k8s 提供了大量的 client端库来操作集群,官方资料: https://kubernetes.io/zh-cn/docs/reference/using-api/client-libraries/
这里使用fabric8io/kubernetes-client来操作k8s集群,quarkus中就是使用fabric8io/kubernetes-client这个库
fabric8io/kubernetes-client 官方地址 https://github.com/fabric8io/kubernetes-client
关于quarkus可以参考
《quarkus 搭建与基础开发环境配置总结》
《quarkus 生产环境与k8s集成总结》
使用fabric8io/kubernetes-client操作k8s 原生资源
使用fabric8io/kubernetes-client 需要在项目中添加依赖
<dependency><groupId>io.fabric8</groupId><artifactId>kubernetes-client</artifactId><version>6.4.1</version>
</dependency>
在maven pom.xml中加入依赖,就可以使用kubernetes-client 注意:可能还需要引入 jackson相关的依赖
以下方式是在集群外(程序未部署到k8s集群中)创建KubernetesClient
这样就可以拿到KubernetesClient,然后对Pod Service Deployment进行操作private String caCertData = "LS0tLS1C***=";
private String clientCertData = "LS0tLS****LQo=";
private String clientKeyData = "LS0tLS****=";
private String host = "https://192.168.0.160:6443";Config config = new ConfigBuilder().withMasterUrl(host).withCaCertData(caCertData).withClientCertData(clientCertData).withClientKeyData(clientKeyData).withDefaultNamespace().build();
//集群外创建client 需要指定 host 证书 私钥等
KubernetesClient client = new KubernetesClientBuilder().withConfig(config).build();
以上代码中的caCertData clientCertData clientKeyData host
可以使用k8s集群master节点 /root/.kube/config中的配置
//以下方式是在集群内(程序部署在k8s集群中)创建KubernetesClient
KubernetesClient client = new KubernetesClientBuilder().build();
不需要配置 host 证书 私钥等
然后就可以使用client
client.pods()..
client.services()..
来操作k8s集群中的资源了
使用abric8io/kubernetes-clientt操作CRD watch状态变更
此时我们只需要在自己的java springboot项目中,使用kubernetes-client 去监听自定义的资源的状态并对状态做对应的响应操作即可
对应的就是watch操作
后续实例中会详解讲解 watch操作 监控资源状态变更
权限处理
把java项目部署到k8s集群中,是一个很好的选择。但是对于我们自定义的资源默认的ServiceAccount中是没有对应的定义的,所以需要创建ServiceAccount,并让ServiceAccount与ClusterRole 绑定。这样java程序能够在集群内部访问k8s api接口
参考资料《快速上手k8s权限管理 立即掌握User Role RoleBinding kubeconfig 实战教程》
相关的权限配置如下
# 创建ServiceAccountapiVersion: v1kind: ServiceAccountmetadata:name: crdtest-serviceaccountnamespace: crd-tm-testlabels:myk8s.crd-test.com: crd-tm-test---# 需要操作自定义的 CRD TableMonitor 需要配置对TableMonitor资源的操作权限apiVersion: rbac.authorization.k8s.io/v1beta1kind: ClusterRolemetadata:name: crdtest-clusterrolerules:- apiGroups:- "myk8s.crd-test.com"resources: - tablemonitorsverbs:- list- watch---# 让ServiceAccount 与 ClusterRole绑定
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:name: crdtest-cluster-role-binding
roleRef:apiGroup: rbac.authorization.k8s.iokind: ClusterRolename: crdtest-clusterrole
subjects:- kind: ServiceAccountname: crdtest-serviceaccountnamespace: crd-tm-test
实例:用java开发一个数据库表监控Operator
本例子为了简洁并利于理解,使用数据库中的表作为一个需要管理的资源。
类似Pod管理的是容器,我们创建一个TableMonitor资源来管理表
架构设计入下图
数据库表监控Operator的业务逻辑是
- 1 管理k8s集群中定义的TableMonitor资源
- 2 如果发现新建了TableMonitor资源就新建表 (类似Pod新建一个容器)
- 3 如果发现删除了TableMonitor资源就删除表
- 4 循环的监控TableMonitor资源定义的表行数,保证行数在指定范围内 (类似Deployment replicas)
Step1 数据库表监控CRD 创建
创建一个TableMonitor资源的定义 CRD yaml文件 crd-table-monitor.yaml 内容如下 (见my-docker-demo-k8s-operator/yaml/crd-table-monitor.yaml)
# 定义自定义的TableMonitor 资源
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:# 名字必需与下面的 spec 字段匹配,并且格式为 '<名称的复数形式>.<组名>'name: tablemonitors.liuyijiang.crd-tm.comspec: # 组名称,用于 REST API: /apis/<组>/<版本>group: liuyijiang.crd-tm.comnames:# 名称的复数形式,用于 URL:/apis/<组>/<版本>/<名称的复数形式>plural: tablemonitors# 名称的单数形式,作为命令行使用时和显示时的别名singular: tablemonitor# kind 通常是单数形式的驼峰命名(CamelCased)形式。你的资源清单会使用这一形式。kind: TableMonitor# shortNames 允许你在命令行使用较短的字符串来匹配资源shortNames:- tmscope: Namespaced versions:- name: v1# 每个版本都可以通过服务标志启用/禁用。served: true# 必须将一个且只有一个版本标记为存储版本。storage: trueschema:openAPIV3Schema:type: objectproperties: spec:type: objectproperties:# 自定义的资源spec 中的属性 dbUserName 需要连接的数据库的账户名dbUserName: type: string# 自定义的资源spec 中的属性 dbUserPassword 需要连接的数据库的密码dbUserPassword: type: string# 自定义的资源spec 中的属性 dbUrl 需要连接的数据库的urldbUrl: type: string# 自定义的资源spec 中的属性 tableName 需要操作的表名称tableName: type: string # 自定义的资源spec 中的属性 tableColumns 注意类型是 array 表中的字段tableColumns: type: arrayitems:type: string # 自定义的资源spec 中的属性 dataNum 表中保存的数据行数 dataNum: type: integerstatus:type: object properties: # 恢复次数 每调整一次表行数就加1recoverNum: type: integer# 运行数据库ip hostIp: type: string# 运行状态 runingStatus: type: string
kubectl apply -f crd-table-monitor.yaml 创建CRD
Step2 springboot k8s Operator 程序开发
程序就是一个简单的springboot 其中fabric8/kubernetes-client版本号6.4.1 项目主要结构如下
自定义资源相关类
TableMonitorSpec.java TableMonitorStatus.java 都是一个实现了KubernetesResource接口的POJO类
对应crd-table-monitor.yaml中配置的spec 和 status 相关字段
TableMonitorSpec.java
TableMonitorStatus.java
TableMonitor.java 则是对应的TableMonitor资源 注意组和版本号
TableMonitorList.java 是一个继承了DefaultKubernetesResourceList的类,用于保存多个TableMonitor
数据库操作类
TableService.java的作用就是一个数据库操作的类,用于创建表,删表,加数据,删数据等
使用spring提供的jdbctemplate来操作数据库,例如以下是一个建表操作
数据库操作的类很简单 就不多赘述
监听自定义资源类
TableMonitorListener.java 是本Operator 程序的核心类
代码如下:
package com.k8s.operator.listener;import java.util.List;
import java.util.concurrent.ConcurrentHashMap;import javax.annotation.PostConstruct;import org.springframework.stereotype.Component;import com.k8s.operator.crd.TableMonitor;
import com.k8s.operator.crd.TableMonitorList;
import com.k8s.operator.crd.TableMonitorStatus;
import com.k8s.operator.database.DataTable;
import com.k8s.operator.database.TableService;import io.fabric8.kubernetes.client.KubernetesClient;
import io.fabric8.kubernetes.client.KubernetesClientBuilder;
import io.fabric8.kubernetes.client.Watch;
import io.fabric8.kubernetes.client.Watcher;
import io.fabric8.kubernetes.client.WatcherException;
import io.fabric8.kubernetes.client.dsl.MixedOperation;
import io.fabric8.kubernetes.client.dsl.NonNamespaceOperation;
import io.fabric8.kubernetes.client.dsl.Resource;/*** 核心就是这个TableMonitorListener* * TableMonitorListener watch 自定义的TableMonitor资源 处理 1 新建 2 删除 3 数据是否满足指定* * @author liuyijiang**/
@Component
public class TableMonitorListener {/*** TableMonitor 控制器*/private MixedOperation<TableMonitor, TableMonitorList, Resource<TableMonitor>> tableMonitor;/*** 数据库操作类*/private TableService tableService = new TableService();/*** 保存所有的k8s集中部署的TableMonitor*/private ConcurrentHashMap<String, TableMonitor> CRDS = new ConcurrentHashMap<>();/*** 初始化*/@PostConstructpublic void initListerner() {System.out.println("start TableMonitorListener");/*** 初始化客户端*/init();/*** 监听表的状态变化*/watchTable();/*** 监听资源的变化*/watchCRD();}/*** 初始化KubernetesClient 客户端*/private void init() {System.out.println("init KubernetesClientBuilder !!!!!!!!!!!!!!!!");KubernetesClient client = new KubernetesClientBuilder().build();/*** 获取自定义资源的客户端*/NonNamespaceOperation<TableMonitor, TableMonitorList, Resource<TableMonitor>> tableMonitorNonNamespace = client.resources(TableMonitor.class, TableMonitorList.class);//使用default 命名空间tableMonitorNonNamespace = ((MixedOperation<TableMonitor, TableMonitorList, Resource<TableMonitor>>) tableMonitorNonNamespace).inNamespace("default");tableMonitor = (MixedOperation<TableMonitor, TableMonitorList, Resource<TableMonitor>> ) tableMonitorNonNamespace;}/*** 监控表 保证表中的数据始终保持在 dataNum配置的值*/private void watchTable() {new Thread(() -> {System.out.println("start watchTable ");while (true) {for (String id : CRDS.keySet()) {TableMonitor tm = CRDS.get(id);/*** 检查是否存在表*/System.out.println("check if table is not EXISTS");tableService.createTable(tm);/*** 查询出TableMonitor 表中存在的数据*/int num = tableService.getTableDataCount(tm);if (num != tm.getSpec().getDataNum()) {// 小于定义的值if (num < tm.getSpec().getDataNum()) {System.out.println("### data too little !!!!!!!!!!!!!!!!");int flag = tm.getSpec().getDataNum() - num; // 获得少了的量for (int i = 0; i < flag; i++) {tableService.insertTableData(tm); // 创建少的数据}} else { // 大于定义的值System.out.println("### data too more !!!!!!!!!!!!!!!!");int flag = num - tm.getSpec().getDataNum(); // 获得多了的量List<DataTable> list = tableService.listTableData(tm);for (int i = 0; i < flag; i++) {tableService.deleteTableData(tm, list.get(i)); // 删除多的数据}}//更新资源状态 添加一次恢复次数tm.getStatus().setRecoverNum(tm.getStatus().getRecoverNum() + 1);tableMonitor.resource(tm).createOrReplace();}}// 10秒钟监控一次try {Thread.sleep(10000);} catch (InterruptedException e) {e.printStackTrace();}}}).start();}public void watchCRD() {/*** 监控资源*/Watch watch = tableMonitor.watch(new Watcher<TableMonitor>() {@Overridepublic void eventReceived(Action action, TableMonitor resource) {// 新增if (action.equals(Action.ADDED)) { // 新增资源System.out.println("===============create kind=================" + resource);// 建表tableService.createTable(resource);CRDS.put(resource.getMetadata().getName(), resource); // 资源放入到map中//添加资源状态resource.setStatus(new TableMonitorStatus());resource.getStatus().setRuningStatus("running");resource.getStatus().setRecoverNum(0);String ip = resource.getSpec().getDbUrl().substring(13,26);resource.getStatus().setHostIp(ip);//更新资源状态tableMonitor.resource(resource).createOrReplace();} else if (action.equals(Action.DELETED)) { // 删除资源System.out.println("===============delete kind=================" + resource);tableService.dropTable(resource);CRDS.remove(resource.getMetadata().getName());}}@Overridepublic void onClose(WatcherException cause) {System.out.println(cause);}});}}
以上便是 java实现Operator 的基本代码
Step3 部署springboot k8s Operator到k8s集群
主要事项
- 1 需要创建对应的ServiceAccount 让程序可以访问自定义的TableMonitor资源
- 2 由于镜像仓库是阿里云私库,需要创建对应的Secret便于拉取镜像
关于k8s权限 角色 可以参考《快速上手k8s权限管理 立即掌握User Role RoleBinding kubeconfig 实战教程》
注意:所有相关配置文件保存在 /my-docker-demo-k8s-operator/yaml/operrator相关 Docker相关
创建镜像
Dockerfile内容如下
FROM ascdc/jdk8
VOLUME ["/data/service/logs","/data/service/tmp"]
WORKDIR "/data/service"
EXPOSE 5533
COPY my-docker-demo-k8s-operator.jar my-docker-demo-k8s-operator.jar
ENTRYPOINT ["nohup","java","-jar","my-docker-demo-k8s-operator.jar","&"]
Dockerfile参考 《Dockerfile文件总结》
docker build -t tm-controller .
docker tag tm-controller registry.cn-hangzhou.aliyuncs.com/jimliu/tm-controller
docker push registry.cn-hangzhou.aliyuncs.com/jimliu/tm-controller
此时镜像创建完毕
创建k8s部署文件
springboot k8s Operator部署文件deploy.yml如下 (也可以不部署在k8s中 注意kubernetes-clinet的创建方式)
# 创建命名空间
apiVersion: v1
kind: Namespace
metadata:name: crd-tm-testlabels:liuyijiang.crd-tm.com: crd-tm-test---# 创建阿里云私库秘钥
apiVersion: v1
kind: Secret
metadata:name: myaliyunsecret-crdtmtestnamespace: crd-tm-test labels:liuyijiang.crd-tm.com: crd-tm-test
data:.dockerconfigjson: eyJhdXRocyI6eyJyZWdpc3RyeS5.....省略换成自己的
type: kubernetes.io/dockerconfigjson---# 创建ServiceAccount 用于 程序中访问自定义资源
apiVersion: v1
kind: ServiceAccount
metadata:name: crdtest-serviceaccountnamespace: crd-tm-testlabels:liuyijiang.crd-tm.com: crd-tm-test
imagePullSecrets:- name: myaliyunsecret-crdtmtest---# 需要操作自定义的 CRD TableMonitor 需要配置对TableMonitor资源的操作权限
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:name: crdtest-clusterrolelabels:liuyijiang.crd-tm.com: crd-tm-test
rules:- apiGroups:- "liuyijiang.crd-tm.com" #apiGroups crd-table-monitor.yaml中定义的 groupresources: - tablemonitors #只操作TableMonitor资源 注意为crd-table-monitor.yaml中配置的复数名称verbs: #可以操作的类型- list- watch- get- create- delete - update - edit - exec---# 让ServiceAccount 与 ClusterRole绑定
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:name: crdtest-cluster-role-bindinglabels:liuyijiang.crd-tm.com: crd-tm-test
roleRef:apiGroup: rbac.authorization.k8s.iokind: ClusterRolename: crdtest-clusterrole
subjects:- kind: ServiceAccountname: crdtest-serviceaccount namespace: crd-tm-test ---# 创建项目容器pod
apiVersion: v1
kind: Pod
metadata: name: tm-controller-podnamespace: crd-tm-test labels: liuyijiang.crd-tm.com: crd-tm-testspec: # 注意指定serviceAccountserviceAccountName: crdtest-serviceaccountrestartPolicy: Alwayscontainers: - image: registry.cn-hangzhou.aliyuncs.com/jimliu/tm-controller:latestname: tm-controller-runtime
执行 kubectl apply -f deploy.yml 部署operator
执行 kubectl logs -f tm-controller-pod -n crd-tm-test 查看日志 注意-n 命名空间
到此 springboot k8s Operator部署完成
创建自定义资源 程序实现监控
测试创建TableMonitor资源
现在创建一个资源来测试 springboot k8s Operator
资源创建文件 tm1.yaml 内容如下
# api使用 crd中定义的组名称
apiVersion: "liuyijiang.crd-tm.com/v1"
# kind使用 crd中定义的kind名称
kind: TableMonitor
metadata:name: test-001
spec:dbUserName: "root"dbUserPassword: "123456"dbUrl: "jdbc:mysql://192.168.0.206:3306/t0003"tableName: "tb_my_test"dataNum: 3tableColumns: - aaabbbccc
首先可以看到t0003数据库中目前还没有tb_my_test 这张表
kubectl apply -f tm1.yaml 创建资源
kubectl apply -f tm1.yaml
kubectl get tm -o custom-columns-file=tpl.txt
springboot k8s Operator 日志出现建表操作
测试表数据始终保持为 dataNum
删除表中的一条数据
10秒后 表数据恢复到dataNum指定的值3
同时恢复次数增加1次
测试删除TableMonitor资源
执行 kubectl delete -f tm1.yaml 删除TableMonitor资源
原文地址 https://blog.csdn.net/liuyij3430448/article/details/129534732
相关文章:

k8s java程序实现kubernetes Controller Operator 使用CRD 学习总结
k8s java程序实现kubernetes Controller & Operator 使用CRD 学习总结 大纲 原理Controller 与 Operator自定义资源定义 CRD ( CustomResourceDefinition)kubernetes-client使用java fabric8io/kubernetes-client操作k8s 原生资源使用java abric8io/kubernetes-clientt操…...

Unity笔记:修改代码执行的默认打开方式
使用 External Tools 偏好设置可设置用于编写脚本、处理图像和进行源代码控制的外部应用程序。 External Script Editor:选择 Unity 应使用哪个应用程序来打开脚本文件。Unity 会自动将正确的参数传递给内置支持的脚本编辑器。Unity 内置支持 Visual Studio Commun…...

Linux IPC:匿名管道 与 命名管道
目录一、管道的理解二、匿名管道三、命名管道四、管道的通信流程五、管道的特性进程间通信方式有多种,本文介绍的是管道,管道分为匿名管道和命名管道。 一、管道的理解 生活中的管道用来传输资源,例如水、石油之类的资源。而进程间通信的管道…...

阿里研发工程师JAVA暑期实习一面
文章目录先说一下我自己的情况面试过程总结先说一下我自己的情况 我就读于湖南大学,软件工程专业,现在大三下 很巧的是,我在大二的时候就在相同的时间面过相同的部门和相同的岗位,所以我没有做笔试就直接让我去面试了。我当时还纳…...

第十四届蓝桥杯三月真题刷题训练——第 11 天
目录 第 1 题:卡片 题目描述 运行限制 第 2 题:路径_dpgcd 运行限制 第 3 题:字符统计 问题描述 输入格式 输出格式 样例输入 样例输出 评测用例规模与约定 运行限制 第 4 题:费用报销 第 1 题:卡片 题…...

机器学习入门——线性回归
线性回归什么是线性回归?回归分析:线性回归:回归问题求解单因子线性回归简单实例评估模型表现可视化模型展示多因子线性回归什么是线性回归? 回归分析: 根据数据,确定两种或两种以上变量间相互依赖的定量…...
Microsoft Word 远程代码执行漏洞(CVE-2023-21716)
本文转载于: https://mp.weixin.qq.com/s?__bizMzI5NTUzNzY3Ng&mid2247485476&idx1&sneee5c7fd1c4855be6441b8933b10051e&chksmec535547db24dc516d013d3d76097e985aaad7f10f82f15b4e355a97af75fd333acdab6232af&mpshare1&scene23&srci…...
Android kotlin 系列讲解(数据篇)SharedPreferences存储及测试
文章目录 一、什么是SharedPreferences1、将数据存储到SharedPreferences中2、从SharedPreferences中读取数据二、登录使用SharedPreferences一、什么是SharedPreferences SharedPreferences是使用键值对的方式来存储数据的。也就是说,当保存一条数据的时候,需要给这条数据提…...

一文了解Web Worker
一、概述 众所周知,JavaScript最初设计是运行在浏览器中的,为了防止多个线程同时操作DOM带来的渲染冲突问题,所以JavaScript执行器被设计成单线程。但是随着前端技术的发展,JavaScript要处理的工作也越来越复杂,当我们…...

接口文档包含哪些内容?怎么才能写好接口文档?十年测试老司机来告诉你
目录 接口文档结构 参数说明 示例 错误码说明 语言基调通俗易懂 及时更新与维护 总结 那么我们该如何写好一份优秀的接口文档呢? 接口文档结构 首先我们要知道文档结构是什么样子的。接口文档应该有清晰明确的结构,以便开发人员能快速定位自己需…...

java面试八股文之------Java并发夺命23问
java面试八股文之------Java并发夺命23问👨🎓1.java中线程的真正实现方式👨🎓2.java中线程的真正状态👨🎓3.如何正确停止线程👨🎓4.java中sleep和wait的区别👨…...

CANoe中使用CAPL刷写流程详解(Trace图解)(CAN总线)
🍅 我是蚂蚁小兵,专注于车载诊断领域,尤其擅长于对CANoe工具的使用🍅 寻找组织 ,答疑解惑,摸鱼聊天,博客源码,点击加入👉【相亲相爱一家人】🍅 玩转CANoe&…...

【MySQL】002 -- 日志系统:一条SQL更新语句是如何执行的
此文章为《MySQL 实战 45 讲》的学习笔记,其课程链接可参见:MySQL实战45讲_MySQL_数据库-极客时间 目录 一、日志系统 1、重做日志:redo log(引擎层) 2、归档日记:binlog(Server层) …...
C++---背包模型---数字组合(每日一道算法2023.3.14)
注意事项: 本题是"动态规划—01背包"的扩展题,优化思路不多赘述,dp思路会稍有不同,下面详细讲解。 题目: 给定 N个正整数 A1,A2,…,AN,从中选出若干个数,使它们的和为 M,…...

并查集(不相交集)详解
目录 一.并查集 1.什么是并查集 2.并查集的基本操作 3.并查集的应用 4.力扣上的题目 二.三大操作 1.初始化 2.查找 3.合并 三.省份数量 1.题目描述 2.问题分析 3.代码实现 四.冗余连接 1.题目描述 2.问题分析 3.代码实现 一.并查集 1.什么是并查集 并查集&…...

10个最频繁用于解释机器学习模型的 Python 库
文章目录什么是XAI?可解释性实践的步骤技术交流1、SHAP2、LIME3、Eli54、Shapash5、Anchors6、BreakDown7、Interpret-Text8、aix360 (AI Explainability 360)9、OmniXAI10、XAI (eXplainable AI)XAI的目标是为模型的行为和决定提供有意义的解释,本文整理…...

final关键字:我偏不让你继承
哈喽,小伙伴们大家好,我是兔哥呀,今天就让我们继续这个JavaSE成神之路! 这一节啊,咱们要学习的内容是Java所有final关键字。 之前呢,我们学习了继承,这大大提高了代码的灵活性和复用性。但是总…...

8大主流编程语言的适用领域,你可能选错了语言
很多人学编程经常是脑子一热然后就去网上一搜资源就开始学习了,但学到了后面发现目前所学的东西并不是自己最喜欢的,好像自己更喜欢另一个技术,感觉自己学错了,于是乎又去学习别的东西。 结果竹篮打水一场空,前面所付…...

关于Python库的问题
关于Python库的问题 问题1: ModuleNotFoundError: No module named ‘requests’ Python库 Pycharm使用Requests库时报错: No module named requests’解决方法 未安装requests库,使用"pip install requests"命令安装 依然提示P…...
好记性不如烂笔头(2)
概述:用来记录一些小技巧。 1.查看MyBatis执行的sql 类:org.apache.ibatis.mapping.MappedStatement方法:getBoundSql(Object parameterObject)在IDEA的Evaluate Expression查看sql:boundSql.getSql() 2.maven仓库地址为https&…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器
一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

MongoDB学习和应用(高效的非关系型数据库)
一丶 MongoDB简介 对于社交类软件的功能,我们需要对它的功能特点进行分析: 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具: mysql:关系型数据库&am…...

PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

Golang——6、指针和结构体
指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
Kubernetes 网络模型深度解析:Pod IP 与 Service 的负载均衡机制,Service到底是什么?
Pod IP 的本质与特性 Pod IP 的定位 纯端点地址:Pod IP 是分配给 Pod 网络命名空间的真实 IP 地址(如 10.244.1.2)无特殊名称:在 Kubernetes 中,它通常被称为 “Pod IP” 或 “容器 IP”生命周期:与 Pod …...

WPF八大法则:告别模态窗口卡顿
⚙️ 核心问题:阻塞式模态窗口的缺陷 原始代码中ShowDialog()会阻塞UI线程,导致后续逻辑无法执行: var result modalWindow.ShowDialog(); // 线程阻塞 ProcessResult(result); // 必须等待窗口关闭根本问题:…...
MFE(微前端) Module Federation:Webpack.config.js文件中每个属性的含义解释
以Module Federation 插件详为例,Webpack.config.js它可能的配置和含义如下: 前言 Module Federation 的Webpack.config.js核心配置包括: name filename(定义应用标识) remotes(引用远程模块࿰…...
comfyui 工作流中 图生视频 如何增加视频的长度到5秒
comfyUI 工作流怎么可以生成更长的视频。除了硬件显存要求之外还有别的方法吗? 在ComfyUI中实现图生视频并延长到5秒,需要结合多个扩展和技巧。以下是完整解决方案: 核心工作流配置(24fps下5秒120帧) #mermaid-svg-yP…...