k8s Webhook 使用java springboot实现webhook 学习总结
k8s Webhook 使用java springboot实现webhook 学习总结
大纲
- 基础概念
- 准入控制器(Admission Controllers)
- ValidatingWebhookConfiguration 与 MutatingWebhookConfiguration
- 准入检查(AdmissionReview)
- 使用Springboot实现k8s-Webhook
- 证书创建
- 创建MutatingWebhookConfiguration 资源
- java代码编写
- 测试部署Pod
- 将Webhook部署在k8s集群内部
基础概念
Webhook就是一种HTTP回调,很多软件都支持webhook,例如 以前的文章中提到的graylog 也可以使用webhook进行通知。kubernetes也支持Webhook,例如istio就是通过 Mutating webhooks 来自动将Envoy这个 sidecar 容器注入到 Pod 中去的。
kubernetes利用webhook可以实现类似Java Web Filter的功能,拦截对资源的操作请求。 将操作增强或者拦截验证
例如
创建一个Pod,可以对这个操作添加额外的配置,比如添加标签,添加容器,添加挂载等,或者验证Pod操作是不是满足某些要求,不满足则不执行等
kubernetes实现Webhook主要是利用的 动态准入控制 实现
准入控制器
kubernetes 支持多种准入控制器例如:
- LimitRanger
- NamespaceExists
- NodeRestriction
- …略 详细见准入控制器
- MutatingAdmissionWebhook
- ValidatingAdmissionWebhook
准入控制过程分为两个阶段
- 第一阶段,运行变更准入控制器。
- 第二阶段,运行验证准入控制器。
注意:某些控制器既是变更准入控制器又是验证准入控制器。
利用 –enable-admission-plugins 可以添加准入控制器,多个控制器使用,号分开
--disable-admission-plugins 配置可以关闭控制器
MutatingAdmissionWebhook & ValidatingAdmissionWebhook 准入控制器
要实现kubernetes的webhook主要是 MutatingAdmissionWebhook 与 ValidatingAdmissionWebhook 这两个准入控制器
-
ValidatingAdmissionWebhook准入控制器 主要作用就是对操作做验证性质的准入
-
MutatingAdmissionWebhook准入控制器 主要作用就是对操作做修改性质的准入
例如:
想在操作资源之前进行修改(Mutating Webhook),比如增加Container或者修改部署的一些属性
想在操作资源之前进行校验(Validating Webhook),不满足条件的资源直接拒绝并给出相应信息
整体的执行流程如下图
本次测试的k8s 集群版本1.17默认是开启了MutatingAdmissionWebhook 与 ValidatingAdmissionWebhook 准入控制器,如果未开启需要添加这两个控制
在master节点的 /etc/kubernetes/manifests文件夹下修改 kube-apiserver.yaml后 api-server会自动重启
ValidatingWebhookConfiguration 与 MutatingWebhookConfiguration
前面提到的MutatingAdmissionWebhook & ValidatingAdmissionWebhook 准入控制器作用是开启准入的webhook调用。但如何调用,哪些资源允许调用则是由ValidatingWebhookConfiguration 与 MutatingWebhookConfiguration来配置
以MutatingWebhookConfiguration为例,可以配置如下条件
- 请求webhook服务的地址路径
- 匹配的k8s资源类型
- …略
以下是一个简单的MutatingWebhookConfiguration配置文件
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration #类型
metadata: name: my-test-webhook1 #创建MutatingWebhookConfiguration 的名称
webhooks:
- admissionReviewVersions: #指定可接受的 AdmissionReview 对象版本 这里支持v1beta1 v1- v1beta1- v1clientConfig:# CA根证书内容 需要base64编码caBundle: JBRUN3YR..# 只支持https请求# 配置k8s webhook准入器调用的 webhook服务地址(部署在k8s集群外部)url: "https://webhooktest.liuyijiang.com/mutate/v1" #webhook web服务访问的地址# 注意 url和service不能同时存在# webhook服务部署在k8s集群内部可以使用service的方式访问# service请求域名为 <servicename>.<namespace>.svcservice:namespace: my-namespacename: my-webhookpath: /mutate/v1 #指定请求地址port: 443 #端口默认是443可以不配置failurePolicy: FailmatchPolicy: Exact #精确匹配name: webhooktest.liuyijiang.com #名称随意但是必须是域名格式namespaceSelector:matchLabels:my-web-inject: enabled #必须匹配标签为my-web-inject=enabled的命名空间内的资源才会被拦截rules:- apiGroups:- ""apiVersions: #匹配的版本- v1operations: #拦截CREATE操作- CREATEresources: #拦截执行类型是pod- podsscope: '*' #所有命名空间sideEffects: None #配置是否有副作用,None表示调用 Webhook 没有副作用timeoutSeconds: 30 #请求超时时间
更多详细配置见Webhook 配置
注意:使用k8s的webhook功能需要提前配置ValidatingWebhookConfiguration 或 MutatingWebhookConfiguration
准入检查(AdmissionReview)
当配置好ValidatingWebhookConfiguration 或 MutatingWebhookConfiguration后,满足条件的kubernetes资源操作就会触发webhook动作。
k8s会对配置中的地址(url中配置的地址或者service配置的地址)发送POST请求。请求的Content-Type为application/json,内容则是一个AdmissionReview json字符串。
我们的程序需求对AdmissionReview json字符串中的内容做分析修改操作完成自己的业务
具体的AdmissionReview参数可以参考官方文档Webhook 请求与响应
一个整体的k8s webhook调用流程如下
使用springboot实现k8s-Webhook
Webhook只是一个k8s执行准入阶段后会调用的一个http地址而已,所以只要按照k8s-Webhook标准的输入和输出实现的一个web项目都可以作为一个Webhook
这里使用java语言来开发测试
web项目可以部署在k8s集群外部也可以部署在集群内部,但k8s访问Webhook必须是https的请求!
在配置动态准入的时候可以有如下两种方式
-
在k8s集群内部
以下配置使用service访问集群内部的webhook
clientConfig:
service:
name: istiod
namespace: istio-system
path: /inject
port: 443 -
在k8s集群外部
以下配置使用url地址访问集群外部的webhook
clientConfig:
url: “https://webhooktest.medcrab.com/mutate”
开发前准备:
- 1 确保k8s集群启用 MutatingAdmissionWebhook控制器,通常是已经启用的
- 2 确保启用了 admissionregistration.k8s.io/v1 API
本例子的k8s集群使用 1.17版本,默认已开启支持
此例子实现一个动态的修改Pod的标签的Webhook,并且webhook部署在集群外部,主要功能如下
当部署pod的时候自动的给pod添加一个新的标签,可以基于此例子扩展,例如动态的添加新的容器用于监控(类似istio的边车模式)
step1 证书创建
k8s访问Webhook必须是https的请求,所以我们需要先准备对应的证书让我们的springboot项目支持https访问
如果有权威机构(花钱买的)签署证书则可以直接使用此证书来部署程序,否则就需要自己制作自签名证书
先定义一个将使用的域名例如 webhooktest.liuyijiang.com 后续请求都使用这个域名访问,我们需要使用根证书对此域名签名
这里将使用cfssl工具来创建证书,关于证书的制作可以参考此文章 使用cfssl为程序添加https证书
准备根证书
首先使用cfssl 创建根证书,这个根证书后续会用在1 创建域名签名证书 2配置webhook的caBundle
ca-csr.json 内容如下
{"CN": "LYJCA", "key": {"algo": "rsa", "size": 2048 },"names": [{"C": "CN", "L": "Chengdu", "ST": "Sichuan", "O": "liuyjCA", "OU": "System" }]
}
使用命令 cfssl gencert -initca ca-csr.json | cfssljson -bare ca 创建CA根证书
得到ca.pem(根证书) ca-key.pem(根证书私钥)
用根证书给域名签发
使用生成的ca.pem ca-key.pem 对webhooktest.liuyijiang.com域名签名
ca-config.json 与 webhooktest.liuyijiang.com-csr.json 内容如下
ca-config.json
{"signing":{"default":{"expiry":"8760h" //指定了证书的有效期},"profiles":{//配置策略"mytest":{ //配置一个名称为mytest的策略"expiry":"8760h", //指定了证书的有效期"usages":["signing", //表示该证书可用于签名其它证书"key encipherment","server auth", // client端(客户端) 可以用该 CA 对 server 提供的证书进行验证"client auth" // server端(服务端) 可以用该 CA 对 client 提供的证书进行验证]}}}
}
webhooktest.liuyijiang.com-csr.json
{"CN":"liuyijiang.com","hosts":["webhooktest.liuyijiang.com"],"key":{"algo":"rsa","size":2048},"names":[{"C": "CN","L": "Chengdu","ST": "Sichuan","O": "liuyijiang.com","OU": "System"}]
}
使用命令 cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=mytest webhooktest.liuyijiang.com-csr.json | cfssljson -bare webhooktest.liuyijiang.com
得到webhooktest.liuyijiang.com.pem(证书) webhooktest.liuyijiang.com-key.pem(证书私钥)
springboot项目开启https
springboot目前是不支持.pem证书的,需要把刚才创建的.pem证书转换为p12
使用 openssl命令进行证书转换
命令格式
openssl pkcs12 -export -in "待转换的证书文件" -inkey "待转换的私钥文件" -out "指定生成的p12证书文件"
使用命令 openssl pkcs12 -export -in webhooktest.liuyijiang.com.pem -inkey webhooktest.liuyijiang.com-key.pem -out key.p12 注意输入自定义密码(例如123456)
得到key.p12 证书
将key.p12证书放入到项目的src/main/resources文件夹下,这样只需要修改项目的application.properties文件加入配置即可开启https
server.port=443
server.ssl.protocol=TLS
server.ssl.key-store=classpath:key.p12
server.ssl.key-store-password=123456
server.ssl.key-store-type=PKCS12
验证证书生效
启动springboot项目,修改host文件将 webhooktest.liuyijiang.com 域名映射到127.0.0.1
参考 使用cfssl为程序添加https证书 将刚才的CA根证书放到浏览器的受信根证书里重启浏览器后访问
证书验证成功
到此证书的配置完成
step2 创建MutatingWebhookConfiguration 资源
因为需要在准入阶段动态的修改 Pod配置,所以需要使用MutatingWebhookConfiguration
MutatingWebhookConfiguration配置文件webhook1.yaml内容如下
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata: name: my-test-webhook1 #创建MutatingWebhookConfiguration 的名称
webhooks:
- admissionReviewVersions: #指定可接受的 AdmissionReview 对象版本 这里支持v1beta1 v1- v1beta1- v1clientConfig:# CA根证书内容caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tL省略 # 只支持https请求url: "https://webhooktest.liuyijiang.com/mutate/v1" #webhook web服务访问的地址failurePolicy: FailmatchPolicy: Exact #精确匹配name: webhooktest.liuyijiang.com #名称随意但是必须是域名格式namespaceSelector:matchLabels:my-web-inject: enabled #必须匹配标签为my-web-inject=enabled的命名空间内的资源才会被拦截rules:- apiGroups:- ""apiVersions:- v1operations: #拦截CREATE操作- CREATEresources: #拦截执行类型是pod- podsscope: '*' #所有命名空间sideEffects: None #配置是否有副作用,None表示调用 Webhook 没有副作用timeoutSeconds: 30 #请求超时时间
注意:caBundle 内容是一个用 PEM 编码的 CA 证书,用于校验 Webhook 的服务器证书
这里就是使用开始创建的CA证书,可以把k8s-apiserver理解成一个浏览器,当访问webhooktest.liuyijiang.com时需要戴上一个根证书来确保webhook服务的证书正确
注意:如果webhook服务的证书是自签名证书则需要配置caBundle指定为CA根证书,如果webhook服务的证书是权威机构(花钱买的)签署证书则可以不用配置caBundle
使用cat ca.pem | base64 -w 0 将根证书base64编码
注意:webhooktest.liuyijiang.com是一个自建的一个域名,需要在k8s master节点上配置域名映射
192.168.0.204为我本机ip地址
域名能够ping通
curl --cacert ca.pem https://webhooktest.liuyijiang.com/echo 带证书访问正常
部署MutatingWebhookConfiguration资源
kubectl apply -f webhook1.yaml
kubectl get MutatingWebhookConfiguration
到此MutatingWebhookConfiguration的配置完成
step3 java代码编写
当K8S请求webhook时会发送 POST请求时,请求的Content-Type为application/json ,内容是一个AdmissionReview 对象的JSON序列化字符串
AdmissionReview的内容可以参考 https://kubernetes.io/zh-cn/docs/reference/access-authn-authz/extensible-admission-controllers/#webhook-request-and-response
可以根据AdmissionReview request的kind实现自己的业务逻辑
代码编写很简单需要注意以下关键点
- 1 controller中的mapping必须支持POST请求
- 2 注意JSONPatch对字段的操作,需要base64 JSONPatch的操作方式
- 3 响应也必须是一个Content-Type为application/json并且一个包含 AdmissionReview 对象的 JSON 序列化格式字符串
- 4 响应中必须要有response字段并且已被有效填充。uid与allowed字符段必须有值
这里贴出一个极简的代码
/*** 实现修改性质的准入 Webhook (Mutating Admission Webhook) */@RequestMapping("/mutate/v1")public String mutateV1(HttpServletRequest req) throws Exception {InputStream in = req.getInputStream();/*** 将输入流转成一个字符串 得到一个AdmissionReview(准入审查json字符串) */BufferedInputStream bis = new BufferedInputStream(in);byte[] b = new byte[1024];int len = 0;StringBuilder sb = new StringBuilder();while ((len = bis.read(b)) != -1) {sb.append(new String(b, 0, len));}System.out.println(sb); /*** 使用fastjson进行字符串转jsonobject* 转换为一个AdmissionReview jsonobject*/JSONObject admissionReview = JSON.parseObject(sb.toString());/*** * 给pod加一个标签 这是一个jsonpatch 操作* op 代表操作类型* path 代表操作的json路径* value 代表修改的值* 需要把字符串转换为base64编码*/String patchStr = "[{ \"op\": \"add\", \"path\": \"/metadata/labels\", \"value\": {\"new-label\":\"webhooktest\"} }]";Base64 base64= new Base64(); String patch = new String(base64.encode(patchStr.getBytes()));/*** uid,从发送到 Webhook 的 request.uid 中复制而来*/String uid = admissionReview.getJSONObject("request").getString("uid");/*** 创建返回值*/Map<String,Object> response = new HashMap<>();response.put("uid", uid); //创建一个UUIDresponse.put("allowed", true); //准入response.put("patchType", "JSONPatch"); //类型是JSONPatchresponse.put("patch", patch); //base64后的patchadmissionReview.put("response", response);String data = admissionReview.toJSONString();System.out.println(data);return data;}
也可以使用java k8s client库 io.fabric8,该库对k8s各种资源操作做了很好的封装
<dependency><groupId>io.fabric8</groupId><artifactId>kubernetes-client</artifactId><version>6.4.1</version></dependency>
以下代码使用 client库实现
step4 测试部署Pod
部署Pod之前需要准备一个两个部署文件
- 1 创建命名空间
- 2 创建Pod
注意:命名空间需要带有MutatingWebhookConfiguration 中 namespaceSelector匹配的标签
namespace.yaml配置文件如下
apiVersion: v1
kind: Namespace #类型 指定为Namespace
metadata:name: webhook-ns #namespace的名称 注意只能是英文小写和数字 labels: my-web-inject: enabled #注意: 命名空间需要带有namespaceSelector中匹配的标签
Pod部署文件指定命名空间是刚才创建的命名空间(webhook-ns),注意没有配置Pod的标签
pod.yaml配置文件如下
apiVersion: v1
kind: Pod
metadata: name: user-service-webhook-testnamespace: webhook-ns
spec: # 容器配置 containers: - image: registry.cn-hangzhou.aliyuncs.com/jimliu/user-service:v3imagePullPolicy: IfNotPresent #Alwaysname: user-serviceports: - containerPort: 5555name: httpprotocol: TCP
测试部署
kubectl apply -f namespace.yaml
kubectl apply -f pod.yaml
此时本机的eclipse中已经打印出k8s的请求日志
查看刚才部署的pod,发现已经动态的添加了标签了
kubectl -n webhook-ns get pods -o wide --show-labels
将Webhook部署在k8s集群内部
刚才的例子是将webhook部署在集群外部的方式,下面将测试把将Webhook部署在k8s集群内部,k8s访问内部Webhook使用的是service域名
step1 配置域名
k8s中service的域名默认格式是
<servicename>.<namespace>.svc.<clusterdomain>
使用my-service-webhook作为service的名称,此service后面将部署在my-in-webhook命名空间中!所以service的域名应该是
完整域名 my-service-webhook.my-in-webhook.svc.cluster.local
简写域名 my-service-webhook.my-in-webhook.svc
k8s在请求webhook是会使用my-service-webhook.my-in-webhook.svc这个域名
step2 给Webhook服务配置证书
我们继续使用上面已经存在的CA根证书 创建Webhook服务的证书
service-csr.json内容如下
{"CN":"liuyijiang.com","hosts":["my-service-webhook.my-in-webhook.svc"],"key":{"algo":"rsa","size":2048},"names":[{"C": "CN","L": "Chengdu","ST": "Sichuan","O": "liuyijiang.com","OU": "System"}]
}
注意hosts中的域名为my-service-webhook.my-in-webhook.svc
使用命令 cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=mytest service-csr.json | cfssljson -bare service 签名域名证书
得到service.pem(证书) service-key.pem(证书私钥)
使用命令 openssl pkcs12 -export -in service.pem -inkey service-key.pem -out key2.p12
得到key2.p12
修改配置application.properties
server.port=443
server.ssl.protocol=TLS
server.ssl.key-store=classpath:key2.p12
server.ssl.key-store-password=123456
server.ssl.key-store-type=PKCS12
到此证书配置完成
step3 创建镜像并推送到私库
将项目打包成jar文件制作镜像
docker build -t webhook .
docker tag webhook registry.cn-hangzhou.aliyuncs.com/jimliu/webhook:v1
docker push registry.cn-hangzhou.aliyuncs.com/jimliu/webhook:v1
到此webhook镜像创建完成
step4 部署webhook到k8s集群
部署配置文件如下deploy.yaml
apiVersion: v1
kind: Namespace #类型 指定为Namespace
metadata:name: my-in-webhook #namespace的名称 注意只能是英文小写和数字 --- apiVersion: apps/v1
kind: Deployment
metadata:name: webhook-pod-deploynamespace: my-in-webhook
spec:replicas: 1selector:matchLabels: app: webhook-pod template:metadata:labels:app: webhook-pod spec: imagePullSecrets:- name: myaliyunsecretcontainers:- name: webhook-run-containerimage: registry.cn-hangzhou.aliyuncs.com/jimliu/webhook:v1imagePullPolicy: IfNotPresent #Alwaysports: - containerPort: 443 protocol: TCP name: http ---apiVersion: v1
kind: Service
metadata:name: my-service-webhooknamespace: my-in-webhook
spec:ports:- protocol: TCPport: 443targetPort: 443name: httpselector:app: webhook-pod type: ClusterIP
部署webhook
kubectl apply -f deploy.yaml
pod service 成功部署运行
到此webhook相关Pod Service部署完成
step5 创建MutatingWebhookConfiguration 资源
与外部webhook不同,内部部署的webhook不使用url而是配置service 其他的都一致
webhook2.yaml内容如下
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata: name: my-test-webhook2 #创建MutatingWebhookConfiguration 的名称
webhooks:
- admissionReviewVersions: #指定可接受的 AdmissionReview 对象版本 这里支持v1beta1 v1- v1beta1- v1clientConfig:# CA根证书内容caBundle: LS0tLS1CRUdJTiBDRVJUS略..# 只支持https请求service:name: my-service-webhook # service的名称namespace: my-in-webhook #service所在的命名空间path: /mutate/v1 #指定请求地址port: 443 #端口默认是443可以不配置failurePolicy: FailmatchPolicy: Exact #精确匹配name: my-service-webhook.my-in-webhook.svc #名称随意但是必须是域名格式namespaceSelector:matchLabels:my-web-inject: enabled #必须匹配标签为my-web-inject=enabled的命名空间内的资源才会被拦截rules:- apiGroups:- ""apiVersions: #匹配的版本- v1operations: #拦截CREATE操作- CREATEresources: #拦截执行类型是pod- podsscope: '*' #所有命名空间sideEffects: None #配置是否有副作用,None表示调用 Webhook 没有副作用timeoutSeconds: 30 #请求超时时间
注意:caBundle 还是使用先前创建的CA根证书
部署MutatingWebhookConfiguration
到此MutatingWebhookConfiguration部署完成
step6 测试效果
kubectl apply -f namespace.yaml
kubectl apply -f pod.yaml
使用kubectl -n my-in-webhook logs -f webhook-pod-deploy-6bb498fbf6-4jkm9 查看日志
查看刚才部署的pod,发现已经动态的添加了标签了
kubectl -n webhook-ns get pods -o wide --show-labels
相关文章:

k8s Webhook 使用java springboot实现webhook 学习总结
k8s Webhook 使用java springboot实现webhook 学习总结 大纲 基础概念准入控制器(Admission Controllers)ValidatingWebhookConfiguration 与 MutatingWebhookConfiguration准入检查(AdmissionReview)使用Springboot实现k8s-Web…...

JS逆向之猿人学爬虫第20题-wasm
文章目录 题目地址sign参数分析python算法还原往期逆向文章推荐题目地址 https://match.yuanrenxue.cn/match/20第20题被置顶到了第1页,题目难度 写的是中等 算法很简单,就一个标准的md5算法,主要是盐值不确定, 而盐值就在wasm里面,可以说难点就在于wasm分析 sign参数分…...

【双指针优化DP】The 2022 Hangzhou Normal U Summer Trials H
Problem - H - Codeforces 题意: 思路: 首先很明显是DP 因为只有1e6个站点,因此可以以站点作为阶段 注意到K很小,因此可以尝试把这个当作第二维 设dp[i][j]为到达第i个站点,已经花了j元钱的最小步数 然后就想了一…...
[论文笔记] LLM数据集——金融数据集
一、chatglm_金融 ModelScope 魔搭社区 请将modelscope sdk升级到v1.7.2rc0,执行: pip3 install "modelscope1.7.2rc0" -f https://modelscope.oss-cn-beijing.aliyuncs.com/releases/repo.html # 方式1 git clone http://www.modelscope…...

在亚马逊平台,如何有效举报违规行为?
众所周知,在每个行业都有一些违规现象,甚至这些违规现象还会给自己带来利益方面的损失,一旦触犯到自己的利益的话,那自己是需要想办法解决的,想办法规避。 就拿开亚马逊店铺来说,比较容易遇到的就是产品侵…...

深度学习入门教学——神经网络
深度学习就是训练神经网络。 1、神经网络 举个最简单的例子,以下是一个使用线性回归来预测房屋价格的函数。这样一个用于预测房屋价格的函数被称作是一单个神经元。大一点的神经网络,就是将这些单个神经元叠加起来。例如:神经网络根据多个相…...
阿里Java开发手册~OOP 规约
1. 【强制】避免通过一个类的对象引用访问此类的静态变量或静态方法,无谓增加编译器解析成 本,直接用 类名 来访问即可。 2. 【强制】所有的覆写方法,必须加 Override 注解。 说明: getObject() 与 get 0 bject() 的问题。…...

【Mysql数据库面试01】内连接 左连接 右连接 全连接
【Mysql数据库】内连接 左连接 右连接 全连接 0.准备1.内连接1.1 SQL(不带where)1.2 SQL(带where)1.3总结 2.左连接2.1SQL(不带where)2.2SQL(带where)2.3总结 3.右连接3.1 SQL(不带where&#x…...

事务隔离:为什么你改了我还看不见
前提概要 你肯定不陌生,和数据库打交道的时候,我们总是会用到事务。最经典的例子就 是转账,你要给朋友小王转 100 块钱,而此时你的银行卡只有 100 块钱。 转账过程具体到程序里会有一系列的操作,比如查询余额、做加减法…...

吴恩达ChatGPT《LangChain Chat with Your Data》笔记
文章目录 1. Introduction2. Document Loading2.1 Retrieval Augmented Generation(RAG)2.2 Load PDFs2.3 Load YouTube2.4 Load URLs2.5 Load Notion 3. Document Splitting3.1 Splitter Flow3.2 Character Splitter3.3 Token Splitter3.4 Markdown Spl…...

https和http有什么区别
https和http有什么区别 简要 区别如下: https的端口是443.而http的端口是80,且二者连接方式不同;http传输时明文,而https是用ssl进行加密的,https的安全性更高;https是需要申请证书的,而h…...

振弦采集仪及在线监测系统完整链条的岩土工程隧道安全监测
振弦采集仪及在线监测系统完整链条的岩土工程隧道安全监测 近年来,随着城市化的不断推进和基础设施建设的不断发展,隧道建设也日益成为城市交通发展的必需品。然而,隧道建设中存在着一定的安全隐患,如地质灾害、地下水涌流等&…...

linux基础学习
1.day1 2.day2 1、VIM配置; 2、安装SSH,调用putty接入终端; 3、shell命令; *:匹配任意长度的字符 ?:匹配一个长度的字符 [...]:匹配其中指定的一个字符 [-]:匹配指定…...
android 前端常用布局文件升级总结(二)
问题一: android:name“android.support.v4.content.FileProvider” 报红 问题解决方案: 把xml布局文件里面: android.support.v4.content.FileProvider 更换成 androidx.core.content.FileProvider 问题二: android.support.design.wid…...

Linux复习——基础知识
作者简介:一名云计算网络运维人员、每天分享网络与运维的技术与干货。 座右铭:低头赶路,敬事如仪 个人主页:网络豆的主页 1. 有关早期linux系统中 sysvin的init的7个级别描述正确的是( )[选择1项] A. init 1 关机状态 B. init 2 字符界面多用户模式 …...

【数据结构】实验三:链表
实验三链表 一、实验目的与要求 1)熟悉链表的类型定义; 2)熟悉链表的基本操作; 3)灵活应用链表解决具体应用问题。 二、实验内容 1)请设计一个单链表的存储结构,并实现单链表中基本运算算…...
第4集丨webpack 江湖 —— loader的安装和使用
目录 一、loader简介1.1 使用 loader1.1.1 配置文件方式1.1.2 内联方式 1.2 loader 特性1.3 解析 loader1.4 命名规范 二、css loader的安装和使用2.1 安装2.2 配置2.3 测试 三、 less-loader 的安装和使用3.1 安装3.2 配置3.3 测试3.4 附件3.4.1 webpack.config.js3.4.2 index…...

【Lua学习笔记】Lua进阶——协程
文章目录 协程协程的定义和调度StatusRunning 协程 协程是一种并发操作,相比于线程,线程在执行时往往是并行的,并且线程在创建销毁执行时极其消耗资源,并且过长的执行时间会造成主进程阻塞。而协程可以以并发时轮值时间片来执行&…...

亚马逊云科技纽约峰会,充分释放数据价值和生成式AI的潜力
生成式AI将深刻改变每个公司的运营方式,标志着人工智能技术发展的新转折点。亚马逊云科技昨日在纽约峰会上宣布,推出七项生成式AI新功能,进一步降低了生成式AI的使用门槛,让无论是业务用户还是开发者都能从中受益。借助这些新功能…...

什么是 web3?
在百度搜索引擎输入 “Web3”、“大厂”。跳出来基本都是这样的标题. 以及如今的互联网行业 “哀鸿遍野”,不仅内卷,还裁员。然后掀起一阵风,猛吹 Web3 的好,数据回归用户……最后再 “威逼利诱” 一下,Web3 就是 20 年…...
ubuntu搭建nfs服务centos挂载访问
在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

汽车生产虚拟实训中的技能提升与生产优化
在制造业蓬勃发展的大背景下,虚拟教学实训宛如一颗璀璨的新星,正发挥着不可或缺且日益凸显的关键作用,源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例,汽车生产线上各类…...
质量体系的重要
质量体系是为确保产品、服务或过程质量满足规定要求,由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面: 🏛️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限,形成层级清晰的管理网络…...
数据链路层的主要功能是什么
数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...

ElasticSearch搜索引擎之倒排索引及其底层算法
文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

用docker来安装部署freeswitch记录
今天刚才测试一个callcenter的项目,所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...
稳定币的深度剖析与展望
一、引言 在当今数字化浪潮席卷全球的时代,加密货币作为一种新兴的金融现象,正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而,加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下,稳定…...

html-<abbr> 缩写或首字母缩略词
定义与作用 <abbr> 标签用于表示缩写或首字母缩略词,它可以帮助用户更好地理解缩写的含义,尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时,会显示一个提示框。 示例&#x…...