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

K8S Service 原理、案例

一、理论介绍

1.1、3W 法则

1、是什么?

  • Service 是一种为一组功能相同的 pod 提供单一不变的接入点的资源。当 Service 存在时,它的IP地址和端口不会改变。客户端通过IP地址和端口号与 Service 建立连接,这些连接会被路由到提供该 Service 的任意一个pod上。通过这种方式,客户端不需要知道每个单独的pod的地址,这样这些pod就可以在集群中随时被创建或移除。

2、为什么需要?

  • Pod 的 IP 地址经常变化。
  • Pod 的 IP 在集群外无法访问。
  • Pod 实例之间的负载均衡。

3、局限性

  • Service 是一种四层代理。
  • 所谓四层,是针对 OSI 七层网络模型来说的。四层对应的是TCP/UDP协议,也就常说的IP+端口。
  • 因此,所谓四层代理就是基于IP+端口的负载均衡;七层就是基于URL等应用层信息的负载均衡。

1.2、基础信息

kubectl explain svc
# svc 是 service 的缩写

  • apiVersion:当前资源使用的 api 版本,与 VERSION 一致。
  • kind:资源类型,跟 KIND 保持一致。
  • metadata:元数据。定义资源名称、标签、注解等。
  • spec:规范、规约。
  • status:最近观察到的 Service 状态。由系统填充。只读。

1.3、ServiceSpec 规约

kubectl explain svc.spec
allocateLoadBalancerNodePorts    <boolean>
clusterIP    <string>
clusterIPs    <[]string>
externalIPs    <[]string>
externalName    <string>
externalTrafficPolicy    <string>
healthCheckNodePort    <integer>
internalTrafficPolicy    <string>
ipFamilies    <[]string>
ipFamilyPolicy    <string>
loadBalancerClass    <string>
loadBalancerIP    <string>
loadBalancerSourceRanges    <[]string>
ports    <[]ServicePort>端口
publishNotReadyAddresses    <boolean>
selector    <map[string]string>标签选择器
sessionAffinity    <string>
sessionAffinityConfig    <SessionAffinityConfig>
trafficDistribution    <string>
type    <string>类型

1.4、Service 类型

kubectl explain svc.spec.type

type 类型有四种:

  • ClusterIP:虚拟集群IP。通过集群的内部 IP 暴露服务,选择该值时服务只能够在集群内部访问。默认类型。
  • NodePort:节点端口。通过每个节点上的 IP 和静态端口(NodePort)暴露服务。 NodePort 服务会路由到自动创建的 ClusterIP 服务。 通过请求 <节点 IP>:<节点端口>,你可以从集群的外部访问一个 NodePort 服务。
  • ExternalName:外部命名空间。通过返回 CNAME 和对应值,可以将服务映射到 externalName 字段的内容(例如,foo.bar.example.com)。 无需创建任何类型代理。
  • LoadBalancer:负载均衡。使用云提供商的负载均衡器向外部暴露服务。 外部负载均衡器可以将流量路由到自动创建的 NodePort 服务和 ClusterIP 服务上。Kubernetes 不直接提供负载均衡组件; 你必须提供一个,或者将你的 Kubernetes 集群与某个云平台集成。

其中 ClusterIP 为默认方式,只能集群内部访问。NodePort、LoadBalancer 则是向外暴露服务的同时将流量路由到 ClusterIP服务。ExternalName 则是CNAME方式进行服务映射。

1.5、Service 端口

kubectl explain svc.spec.ports
appProtocol    <string>
name    <string>
nodePort    <integer>

service 在节点映射的端口。

type 类型是 NodePort 或 LoadBalancer 时才指定。

通常是系统分配,也可以自己指定,范围在 30000-32767

port    <integer> -required-Service 将公开的端口。
protocol    <string>协议。协议类型有 SCTP, TCP, UDP。默认 TCP
targetPort    <IntOrString>pod 端口

二、镜像准备

2.1、镜像准备

docker pull mirrorgooglecontainers/serve_hostname:latest
docker pull alpine:latest
docker pull curlimages/curl

 2.2、镜像导出

docker save -o serve_hostname.tar.gz mirrorgooglecontainers/serve_hostname:latest
docker save -o alpine.tar.gz alpine:latest
docker save -o curl.tar.gz curlimages/curl

 2.3、镜像导入工作节点 containerd

# k8s31node1 执行
[root@k8s31node1 ~]# ctr -n=k8s.io images import serve_hostname.tar.gz
[root@k8s31node1 ~]# ctr -n=k8s.io images ls|grep serve_hostname
[root@k8s31node1 ~]# ctr -n=k8s.io images import alpine.tar.gz
[root@k8s31node1 ~]# ctr -n=k8s.io images ls|grep alpine
[root@k8s31node1 ~]# ctr -n=k8s.io images import curl.tar.gz
[root@k8s31node1 ~]# ctr -n=k8s.io images ls|grep curl# k8s31node2 执行
[root@k8s31node2 ~]# ctr -n=k8s.io images import serve_hostname.tar.gz
[root@k8s31node2 ~]# ctr -n=k8s.io images ls|grep serve_hostname
[root@k8s31node2 ~]# ctr -n=k8s.io images import alpine.tar.gz
[root@k8s31node2 ~]# ctr -n=k8s.io images ls|grep alpine
[root@k8s31node2 ~]# ctr -n=k8s.io images import curl.tar.gz
[root@k8s31node2 ~]# ctr -n=k8s.io images ls|grep curl

2.4、环境准备

 假设有如下三个节点的 K8S 集群:

k8s31master 是控制节点

k8s31node1、k8s31node2 是工作节点

容器运行时是 containerd

三、实践

3.1、创建 ClusterIP 类型 Service

假设有这么一个部署:

apiVersion: apps/v1
kind: Deployment
metadata:name: hostnames
spec:selector:matchLabels:app: hostnamesreplicas: 3template:metadata:labels:app: hostnamesspec:containers:- name: hostnamesimage: mirrorgooglecontainers/serve_hostnameimagePullPolicy: IfNotPresentports:- containerPort: 9376protocol: TCP

mirrorgooglecontainers/serve_hostname 这个应用的作用,就是每次访问 9376 端口时,返回它自己的 hostname。

3.1.1、在不同的节点上访问 podIP:port

返回了各个 pod 自己的 hostname。

可以看到,在集群内的不同节点上, Pod IP 都能访问。

3.1.2、在不同的容器内访问 podIP:port

假设现在新起一个 pod:

apiVersion: v1
kind: Pod
metadata:name: curl-tools
spec:containers:- name: curl-toolsimage: curlimages/curl:latestimagePullPolicy: IfNotPresentcommand: ["/bin/sh", "-c", "while true; do echo 'Hello from curl-tools'; sleep 30; done"]
  • curlimages/curl 是一个 curl 调试工具。
  • command:容器启动后执行的命令,这里使用一个无限循环,每隔 30 秒输出一次 Hello from curl-tools。
  • 像 Alpine 镜像,或者基于 Alpine 制作的工具镜像,容器内没有运行服务,需要启动后运行一个无限循环,防止容器被 K8S 杀掉。

 进入容器访问 hostnames 服务:

kubectl exec -it curl-tools -- curl 10.244.165.57:9376

可以看到,在集群内的容器之间,Pod IP 都能访问。

3.1.3、在集群外访问 podIP:port

我们再起一台虚拟机 docker1,IP 地址跟 K8S 集群在一个网段。

访问 hostnames 服务:

可以看到,即使 docker1 的 IP 地址跟 K8S 集群在一个网段,但 docker1 没有用类似 kubeadm join 加入过集群,Pod IP 是不能访问的。

3.1.4、误删一个 pod 

kubectl delete pod hostnames-d9d7674f5-2djvf

 可以看到,K8S 又帮我们重新拉起了一个新 pod:hostnames-d9d7674f5-n7mtn,以维持我们 Deployment 控制器希望的副本数 replicas: 3。但是这个新 pod 的 IP,跟原来旧 pod 的 IP 是不一样的。

倘若我们是调用这些 pod 服务的客户端,在 pod 扩缩容期间,维护这些 pod IP 的代价是非常大的。所以我们需要一个稳定的接入层,它的 IP 地址、端口不变,让它来代理后端的一组 pod,而我们程序只需要跟这个接入层打交道就可以。这个接入层,就是 Service。

 3.1.5、新建一个 ClusterIP 类型 Service

apiVersion: v1
kind: Service
metadata:name: hostnames-svc
spec:type: ClusterIPselector:app: hostnamesports:- port: 80protocol: TCPtargetPort: 9376
  • spec.selector:Service 通过标签选择器来查找 app=hostnames 标签的 Pod。
  • port: 80  表示该服务的可用端口。
  • targetPort: 9376 表示服务将连接转发的 Pod 端口。
  • port 跟 targetPort 配合起来表示 这个 Service 的 80 端口,代理的是 Pod 的 9376 端口。
  •  查看 service
kubectl get svc

  •  访问 service

连续三次不断地访问 Service 的 CLUSTER-IP 和 端口 80:

  • 依次返回了三个 Pod 的 hostname。
  • 请求 Service IP:port 跟直接访问 Pod IP:port 的结果一样,这说明 Service 可以把请求代理到它所关联的后端 Pod。
  • 这也印证了 Service 提供的是 Round Robin (轮询) 方式的负载均衡。

  • 查看 endpoints

 K8S 创建 Service 的时候,如果 Service 带有 selector 选择器,则 K8S 会创建一个与 Service 同名的 Endpoints 对象。selector 选中的 Pod 的 IP 和 端口,都会记录在 Endpoints 中。当一个新的 Pod 被创建并且它的标签匹配了某个 Service 的选择器时,该 Pod 的 IP 和端口会被添加到对应的 Endpoints 对象中;同样地,当 Pod 被删除时,它也会从 Endpoints 中移除。Endpoints 通常由 Service 引用, 以定义可以将流量发送到哪些 Pod。

kubectl get ep hostnames-svc
# ep endpoints 缩写
kubectl get ep hostnames-svc -oyaml

 需要注意的是,只有处于 Running 状态,且 readinessProbe 检查通过的 Pod,才会出现在 Service 的 Endpoints 列表里。并且,当某一个 Pod 出现问题时,Kubernetes 会自动把它从 Service 里摘除掉。

 3.1.6、集群外访问 Service ClusterIP:port

 在集群外的虚拟机 192.168.40.111 访问 10.103.168.44:80

可以看到,访问不到 Service。如果希望集群外的机器能访问,需要创建 NodePort 类型的 Service 或 LoadBalancer 类型的 Service。

 3.1.7、通过 FQDN 访问服务

在 Kubernetes (K8S) 环境中,FQDN(Fully Qualified Domain Name,完全限定域名)是指集群内部服务的完整域名,它包含了服务名、命名空间以及可选的服务后缀,用于唯一标识集群中的一个服务。

当你在 Kubernetes 中创建一个服务时,Kubernetes 会为该服务分配一个 FQDN。这个 FQDN 的格式通常是:

<service-name>.<namespace>.svc.cluster.local
  • service-name 是你给服务起的名字。
  • namespace 是服务所在的命名空间,默认是 default,除非你在创建服务时指定了不同的命名空间。
  • svc 是固定的,代表这是一个服务。
  • cluster.local 是集群的默认域,大多数情况下是这个值,但如果你的集群配置了不同的域名,则会有所不同。

例如,我们上面 hostnames-svc 服务,它的完整域名是:

hostnames-svc.default.svc.cluster.local

我们在集群的其他 pod 中,就可以使用这个域名访问服务:

可以省略命名空间和 svc.cluster.local,因为已经帮我们解析了。

在节点上不能解析这个域名,Kubernetes 的 DNS 服务通常只服务于集群中的 Pod,而节点本身并不自动配置为使用它:

使用 FQDN 可以让 Kubernetes 集群中的其他服务通过 DNS 解析来找到并访问你的服务,而不需要知道服务的具体 IP 地址。这有助于实现服务发现和服务间的通信,并且提高了服务部署的灵活性和可移植性。在 Kubernetes 中,CoreDNS 通常被用来提供这种 DNS 服务发现的功能。

 3.1.8、Service 原理

我们以 3.1.2 小节 curl-tools 容器(假设运行在 node2 上)访问 Service Cluster_IP : port 为例,来讲解 Service 的工作原理。

首先介绍一下几个组件:

  • kube - proxy:是 Kubernetes 集群中每个节点上运行的一个组件。它负责在节点上维护网络规则,实现了 Service 的代理和负载均衡功能,确保客户端可以通过 Service 的 IP 和端口访问到对应的后端 Pod。kube-proxy 会监视 API Server 中 Service 和 Endpoints 对象的变化。当有新的 Service 或 Endpoints 对象创建、更新或删除时,kube-proxy 会收到通知,并相应地更新节点上的网络规则(iptables)。kube-proxy 有 iptables 模式跟 ipvs 模式。

  • Service:是 Kubernetes 提供的一种抽象层,它定义了一组 Pod 的逻辑集合以及访问这些 Pod 的策略。Service 为 Pod 提供了一个稳定的 IP 地址(ClusterIP)和端口号,使得客户端可以通过这个稳定的地址来访问后端的 Pod,而不需要关心具体 Pod 的 IP 地址和生命周期。
  • Endpoints:是 Kubernetes 中的一个资源对象,它记录了 Service 对应的所有后端 Pod 的 IP 地址和端口信息。每当 Pod 的数量或状态发生变化时,Endpoints 对象会自动更新。

curl-tools 容器内访问 Service IP : port 流程:

  1. node2 上的 kube-proxy 监视 API Server 中 Service 和 Endpoints 对象的变化,更新节点上的网络规则(iptables)。
  2. 客户端 curl-tools 请求 Service IP : port,请求包目的地 Destination 初始设置为服务的IP和端口(10.103.168.44:80)。发送到网络之前,node2 的内核会根据配置在该节点上的 iptables 规则处理数据包。内核会检查数据包是否匹配任何这些 iptables 规则。其中有个规则规定如果有任何数据包的目的地IP等于10.103.168.44、目的地端口等于80,那么数据包的目的地IP和端口应该被替换为随机选中的 hostnames pod的IP和端口。
  3. 本例中的数据包满足规则,故而它的IP:端口被改变了。假设 pod hostnames-d9d7674f5-tjwzp 被轮询算法随机选中了,所以数据包的目的地IP变更为 10.244.165.56,端口改为9376(Service中定义的目标端口)。就好像是客户端 curl-tools 直接发送数据包给 hostnames-d9d7674f5-tjwzp 而不是通过 Service。

3.1.9、iptables Or IPVS

kube-proxy 通过 iptables 处理 Service 的过程,其实需要在宿主机上设置相当多的 iptables 规则。而且,kube-proxy 还需要在控制循环里不断地刷新这些规则来确保它们始终是正确的。

当宿主机上有大量 Pod 的时候,成百上千条 iptables 规则不断地被刷新,很明显会影响到整体性能。

IPVS 模式的工作原理,其实跟 iptables 模式类似。区别只在于当我们创建了前面的 Service 之后,kube-proxy 首先会在宿主机上创建一个虚拟网卡(叫作:kube-ipvs0),并为它分配 Service VIP 作为 IP 地址,如下所示:

 

而接下来,kube-proxy 就会通过 Linux 的 IPVS 模块,为这个 IP 地址设置三个 IPVS 虚拟主机,并设置这三个虚拟主机之间使用轮询模式 (rr) 来作为负载均衡策略。我们可以通过 ipvsadm 查看到这个设置,如下所示:

ipvsadm -ln
-l:这是 ipvsadm 命令的一个选项,代表 “list”,即列出当前 IPVS 规则。使用该选项可以查看已经配置的虚拟服务器(Virtual Server)及其对应的真实服务器(Real Server)信息。
-n:同样是 ipvsadm 命令的选项,代表 “numeric”,表示以数字形式显示地址和端口,而不是将 IP 地址解析为域名、端口号解析为服务名。使用这个选项可以避免 DNS 解析和服务名查找的过程,更直观地显示规则信息。

可以看到,这三个 IPVS 虚拟主机的 IP 地址和端口,对应的正是三个被代理的 Pod。rr 表示轮询 round robin。

这时候,任何发往 10.103.168.44:80 的请求,就都会被 IPVS 模块转发到某一个后端 Pod 上了。 而相比于 iptables,IPVS 在内核中的实现其实也是基于 Netfilter 的 NAT 模式,所以在转发这一层上,理论上 IPVS 并没有显著的性能提升。但是,IPVS 并不需要在宿主机上为每个 Pod 设置 iptables 规则,而是把对这些“规则”的处理放到了内核态,从而极大地降低了维护这些规则的代价。

不过需要注意的是,IPVS 模块只负责上述的负载均衡和代理功能。而一个完整的 Service 流程正常工作所需要的包过滤、SNAT 等操作,还是要靠 iptables 来实现。

 3.1.10、Endpoints 与 readinessProbe 就绪探针

  • 编写服务 svc-hellok8s.yaml
apiVersion: v1
kind: Service
metadata:name: hellok8s-svc
spec:type: ClusterIPselector:app: hellok8sports:- port: 80protocol: TCPtargetPort: 8080
  •  执行并监控
kubectl apply -f svc-hellok8s.yaml
# -w 表示持续监控,注意这个时候不要关闭终端
kubectl get ep hellok8s-svc -w

  • 编写部署  deploy-hellok8s.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: hellok8s
spec:replicas: 3selector:matchLabels:app: hellok8sversion: "1.0"template:metadata:labels:app: hellok8sversion: "1.0"spec:containers:- name: hellok8simage: hellok8s:1.0imagePullPolicy: IfNotPresentports:- containerPort: 8080readinessProbe:httpGet:path: /port: 8080initialDelaySeconds: 15periodSeconds: 10

initialDelaySeconds: 表示容器启动后延迟多少秒,开始就绪探测。这里特意设置成 15 秒,为了观察就绪探针没有完成时, Endpoints 的列表里,会不会有 pod 的 IP。

  •  在另一个终端运行部署
kubectl apply -f deploy-hellok8s.yaml

    可以看到,在 pod 还没就绪前,endpoints 列表里面是不会有 pod IP 的。

    • 删除部署
    kubectl delete -f deploy-hellok8s.yaml

    可以看到 pod 被删除,endpoints 列表也会移除 pod IP。

     3.1.11、原理图

    3.2、创建 NodePort 类型 Service

    假设我们现在有如下 三个 pod:

    kubectl get pod -l app=hostnames -owide

     IP 分别是 10.244.9.57、10.244.9.59、10.244.165.3

    3.2.1、编写服务

    apiVersion: v1
    kind: Service
    metadata:name: hostnames-nodeport
    spec:type: NodePortselector:app: hostnamesports:- port: 80protocol: TCPtargetPort: 9376nodePort: 32000
    • spec.type:NodePort 通过每个节点上的 IP 和静态端口(NodePort)暴露服务。
    • spec.ports.nodePort:指定节点上暴露的端口 32000。

     3.2.2、访问服务

    在浏览器中、或者任何能访问到集群三个节点的机器上,访问 节点IP:32000

    curl 192.168.40.10:32000
    curl 192.168.40.20:32000
    curl 192.168.40.30:32000

    3.2.3、原理

    每一个节点的防火墙规则里面,都有一条 节点IP:32000 的转发规则。转发到三个 pod上。

    创建 NodePort 类型的 Service 会默认帮我们创建 Cluster_IP

    它的数据转发方式,跟 3.1 节讲的是一样的,走 kube-ipvs0 虚拟网桥。

    如果节点上有安装 docker,NodePort 不会走节点IP端口,会默认走 docker0 网桥,然后数据再通过 docker0 转发给 pod。

    3.3、创建 ExternalName 类型 Service

    3.3.1、场景分析

    Service,是无法代理到不同名称空间下的 Pod 的。

    假设我们默认名称空间下,有三个这样的 Pod:

    kubectl get pod -l app=hostnames -A --show-labels

    在名称空间 external-demo 下,有这样一个 Service:

    apiVersion: v1
    kind: Service
    metadata:name: external-svc-anamespace: external-demo
    spec:type: ClusterIPselector:app: hostnamesports:- port: 80protocol: TCPtargetPort: 9376

     Service 在 external-demo 名称空间下,它的标签选择器选择了上面的三个 Pod。

     查看 Service 详情:

    kubectl describe svc external-svc-a -n=external-demo

    可以看到它并没有代理到任何 Pod。

     此时,不管是在节点上直接访问 Service ClusterIP 10.100.211.127:80

    还是在 external-demo 名称空间下的 Pod:

    apiVersion: v1
    kind: Pod
    metadata:name: curl-toolsnamespace: external-demo
    spec:containers:- name: curl-toolsimage: curlimages/curl:latestimagePullPolicy: IfNotPresentcommand: ["/bin/sh", "-c", "while true; do echo 'Hello from curl-tools'; sleep 30; done"]
    kubectl exec -it -n=external-demo curl-tools -- /bin/sh

    都访问不到任何 Pod。

    那么,external-demo 名称空间下的 Pod 要如何通过 Service 访问 default 名称空间下的 Pod 呢?

    3.3.2、ExternalName 类型 Service

    在 external-demo 名称空间下新建一个 Service:

    apiVersion: v1
    kind: Service
    metadata:name: external-svc-bnamespace: external-demo
    spec:type: ExternalNameexternalName: hostnames-svc.default.svc.cluster.localselector:app: hostnamesports:- port: 80protocol: TCP
    • type: ExternalName。
    • externalName:指定 default 名称空间下的完全限定服务名。

    相当于给 hostnames-svc 服务创建了一个软连接。

    • targetPort:在这种情况下可以忽略。
    kubectl get svc -n=external-demo

    此时,在 external-demo 名称空间下的 curl-tools 就可以直接访问这个服务,请求会被代理到 default 名称空间下的 Pod:

    四、参考资料

    官网:虚拟 IP 和服务代理

    Kubernetes教程(五)---Service 的几种访问方式

    相关文章:

    K8S Service 原理、案例

    一、理论介绍 1.1、3W 法则 1、是什么&#xff1f; Service 是一种为一组功能相同的 pod 提供单一不变的接入点的资源。当 Service 存在时&#xff0c;它的IP地址和端口不会改变。客户端通过IP地址和端口号与 Service 建立连接&#xff0c;这些连接会被路由到提供该 Service 的…...

    Base64编码原理:二进制数据与文本的转换技术

    &#x1f504; Base64编码原理&#xff1a;二进制数据与文本的转换技术 开发者的数据编码困境 作为开发者&#xff0c;你是否曾遇到这些与Base64相关的挑战&#xff1a; &#x1f4ca; 需要在JSON中传输二进制数据&#xff0c;但不确定如何正确编码&#x1f5bc;️ 想要在HT…...

    系统设计(1)—前端—CDN—Nginx—服务集群

    简介&#xff1a; 本指南旨涵盖前端、CDN、Nginx 负载均衡、服务集群、Redis 缓存、消息队列、数据库设计、熔断限流降级以及系统优化等模块的核心要点。我们将介绍各模块常见的设计方案与优化策略&#xff0c;并结合电商秒杀、SaaS CRM 系统、支付系统等高并发场景讨论实践技巧…...

    Easysearch 基础运维扫盲指南:从 HTTP 到 HTTPS、认证与安全访问全解析

    Easysearch 基础运维扫盲指南&#xff1a;从 HTTP 到 HTTPS、认证与安全访问全解析 众所周知&#xff0c;原生 Elasticsearch 默认开启的是 HTTP 明文接口&#xff0c;并且不开启任何身份认证或传输加密。若想启用 TLS/SSL 加密及账号密码验证&#xff0c;通常需要配置繁琐的安…...

    在Android中如何使用Protobuf上传协议

    在 Android 中使用 Protobuf&#xff08;Protocol Buffers&#xff09;主要分为以下几个步骤&#xff1a; ✅ 1. 添加 Protobuf 插件和依赖 在项目的 build.gradle&#xff08;Project 级&#xff09;文件中添加 Google 的 Maven 仓库&#xff08;通常默认已有&#xff09;&am…...

    【数据可视化艺术·应用篇】三维管线分析如何重构城市“生命线“管理?

    在智慧城市、能源管理、工业4.0等领域的快速发展中&#xff0c;地下管线、工业管道、电力通信网络等“城市血管”的复杂性呈指数级增长。传统二维管理模式已难以应对跨层级、多维度、动态变化的管线管理需求。三维管线分析技术应运而生&#xff0c;成为破解这一难题的核心工具。…...

    2025年的营销趋势-矩阵IP

    从 2025 年的营销生态来看&#xff0c;创始人 IP 与智能矩阵的结合确实呈现出颠覆性趋势&#xff0c;这一现象背后隐藏着三个值得深度解析的商业逻辑&#xff1a; 一、创始人 IP 的本质是 "信任货币" 的数字化迁徙 当新能源汽车市场陷入参数混战&#xff0c;雷军将个…...

    对接金蝶获取接口授权代码

    接口服务信息 using RestSharp; using System.Configuration; using System.Threading.Tasks; public class KingdeeAccessTokenService { private readonly RestClient _client; private readonly KingdeeApiConfig _config; public KingdeeAccessTokenService() …...

    探秘 3D 展厅之卓越优势,解锁沉浸式体验新境界

    &#xff08;一&#xff09;打破时空枷锁&#xff0c;全球触达​ 3D 展厅的首要优势便是打破了时空限制。在传统展厅中&#xff0c;观众需要亲临现场&#xff0c;且必须在展厅开放的特定时间内参观。而 3D 展厅依托互联网&#xff0c;让观众无论身处世界哪个角落&#xff0c;只…...

    prometheus通过Endpoints自定义grafana的dashboard模块

    1、prometheus自定义的dashboard模块 文件路径/etc/prometheus/config_out/prometheus-env.yaml - job_name: serviceMonitor/monitoring/pfil/0honor_labels: falsekubernetes_sd_configs:- role: endpointsnamespaces:names:- monitoringrelabel_configs:- source_labels:- …...

    java排序算法-计数排序

    计数排序的思路 计数排序的基本思路&#xff1a; 确定取值范围&#xff1a; 遍历整个待排序的数组&#xff0c;确定数组中元素的取值范围&#xff0c;找到最小值和最大值。创建计数数组&#xff1a; 创建一个计数数组&#xff0c;其长度为取值范围的大小&#xff0c;用于统计…...

    力扣-hot100(滑动窗口最大值)

    239. 滑动窗口最大值 困难 给你一个整数数组 nums&#xff0c;有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回 滑动窗口中的最大值 。 示例 1&#xff1a; 输入&#xff1a;nums […...

    每日c/c++题 备战蓝桥杯(P1049 [NOIP 2001 普及组] 装箱问题)

    洛谷P1049 装箱问题题解&#xff1a;动态规划在背包问题中的经典应用 题目描述 P1049 装箱问题是一道典型的0-1背包问题变种。题目要求在给定箱子容量V和n个物品体积的情况下&#xff0c;选择若干物品装入箱子&#xff0c;使得箱子的剩余空间最小。最终输出这个最小剩余空间的…...

    【尚硅谷Redis6】自用学习笔记

    Redis介绍 Redis是单线程 多路IO复用技术&#xff08;类似黄牛买票&#xff09; 默认有16个库&#xff0c;用select进行切换 默认端口号为6379 Memcached&#xff1a;多线程 锁&#xff08;数据类型单一&#xff0c;不支持持久化&#xff09; 五大常用数据类型 Redis key …...

    产品更新丨谷云科技ETLCloud V3.9.2版本发布

    谷云科技 ETLCloud 集成平台迎来了每月一次的功能迭代&#xff0c;本月发布版本号为 3.9.2 版本&#xff0c;为用户带来了新的功能、优化改进以及问题修复&#xff0c;以下是详细介绍&#xff1a; 新增组件 本次更新新增了众多实用组件&#xff0c;涵盖了京东和 Shopify 相关…...

    Promise并发控制与HTTP请求优化

    Promise并发方法对比 #mermaid-svg-tnmGzOkgNUCrbvfI {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-tnmGzOkgNUCrbvfI .error-icon{fill:#552222;}#mermaid-svg-tnmGzOkgNUCrbvfI .error-text{fill:#552222;stroke…...

    G1垃圾回收器中YoungGC和MixedGC的区别

    在 G1 垃圾回收器中&#xff0c;Mixed GC 和 Young GC 的区别主要体现在以下几个方面&#xff1a; 作用范围 Young GC&#xff1a;仅针对年轻代中的Region进行回收&#xff0c;包括 Eden 区和 Survivor 区的 Region。Mixed GC&#xff1a;会回收所有年轻代的 Region 以及部分…...

    Web4.0身份革命:去中心化身份系统的全栈实现路径

    去中心化身份&#xff08;DID&#xff09;技术栈正在重构数字世界的信任根基&#xff0c;本文从密码学协议、存储网络、验证框架三个维度&#xff0c;解析符合W3C标准的身份系统构建方案。通过Hyperledger Aries架构实践&#xff0c;揭示如何实现跨链身份互通、数据主权控制、零…...

    iOS/Flutter混合开发之PlatformView配置与使用

    环境&#xff1a;Xcode 16.3、Flutter 3.29.2、Dart 3.7.2。 使用背景&#xff1a;需要在flutter界面中嵌入一个iOS原生控件。 步骤&#xff1a; 1. iOS侧实现&#xff1a; 1.1&#xff1a;PlatformView实现 class FLNativeView: NSObject, FlutterPlatformView {private v…...

    Libconfig 修改配置文件里的某个节点

    THCommandStatus ( { Status "1"; index 5; }, { Status "2"; index 8; }, { Status "3"; index 7; }, { Status "4"; index 0; } ); 比如这是配置文件的内容&#xff…...

    【金仓数据库征文】_AI 赋能数据库运维:金仓KES的智能化未来

    AI 赋能数据库运维&#xff1a;金仓KES的智能化未来 &#x1f31f;嗨&#xff0c;我是LucianaiB&#xff01; &#x1f30d; 总有人间一两风&#xff0c;填我十万八千梦。 &#x1f680; 路漫漫其修远兮&#xff0c;吾将上下而求索。 在当今数字经济飞速发展的时代&#xff0…...

    【MySQL】3分钟解决MySQL深度分页问题

    什么是深度分页问题&#xff1f;该如何解决呢?这篇文章展开讲讲 什么是深度分页&#xff1f; 当查询结果集非常大时&#xff0c;需要获取靠后页码的数据&#xff0c;比如第1000页、10000页。 如&#xff1a; SELECT * FROM table LIMIT 10000, 10; -- 获取第10001-10010条…...

    GitHub 趋势日报 (2025年04月24日)

    本日报由 TrendForge 系统生成 https://trendforge.devlive.org/ &#x1f4c8; 今日整体趋势 Top 10 排名项目名称项目描述今日获星总星数语言1kortix-ai/sunaSuna - Open Source Generalist AI Agent⭐ 1105⭐ 3639TypeScript2cloudcommunity/Free-CertificationsA curated …...

    一种双模式机器人辅助股骨干骨折钢板植入方法

    股骨干骨折是一种常见的高能损伤&#xff0c;微创内固定是首选治疗方法。然而&#xff0c;钢板植入过程中存在不可见、不准确和不稳定等问题。山东大学研究团队提出了一种双模式机器人辅助钢板植入方法&#xff0c;通过神经网络模型规划钢板植入轨迹&#xff0c;然后利用机械臂…...

    全球碳化硅晶片市场深度解析:技术迭代、产业重构与未来赛道争夺战(2025-2031)

    一、行业全景&#xff1a;从“材料突破”到“能源革命”的核心引擎 碳化硅&#xff08;SiC&#xff09;作为第三代半导体材料的代表&#xff0c;凭借其宽禁带&#xff08;3.26eV&#xff09;、高临界击穿场强&#xff08;3MV/cm&#xff09;、高热导率&#xff08;4.9W/cmK&…...

    IDEA搭建环境的五种方式

    一、普通的java项目 File--New--Project 选择Java&#xff0c;jdk选择1.8版本&#xff0c;然后点next 输入项目名和路径名&#xff0c;点击Finish 创建包结构&#xff0c;编写Class类 编写主方法&#xff0c;输出Hello标志完成 二、普通的javaWeb项目 Java Enterprise-- 勾选…...

    隐形革命:环境智能如何重构“人-机-境“共生新秩序

    引言 在万物互联的时代&#xff0c;环境智能&#xff08;Ambient Intelligence, AmI&#xff09;正以“隐形革命者”的姿态重塑人类生活场景。通过分布式传感器、边缘计算与自适应算法的深度融合&#xff0c;AmI构建出能感知、学习并响应人类行为的智慧环境。 本文基于多领域研…...

    Mysql唯一性约束

    唯一性约束&#xff08;Unique Constraint&#xff09;是数据库设计中用于保证表中某一列或多列组合的值具有唯一性的一种规则。它可以防止在指定列中插入重复的数据&#xff0c;有助于维护数据的完整性和准确性。下面从几个方面为你详细解释 作用 确保数据准确性&#xff1a…...

    QuecPython+GNSS:实现快速定位

    概述 QuecPython 结合 GNSS&#xff08;全球导航卫星系统&#xff09;模块为物联网设备提供开箱即用的定位能力解决方案。该方案支持 GPS/北斗/GLONASS/Galileo 多系统联合定位&#xff0c;为物联网开发者提供从硬件接入到云端服务的全栈式定位解决方案。 优势特点 多体系定…...

    【从零开始:自制一个Java消息队列(MQ)】

    &#x1f680; 从零开始&#xff1a;自制一个Java消息队列&#xff08;MQ&#xff09; 在现代分布式系统中&#xff0c;消息队列&#xff08;Message Queue&#xff0c;MQ&#xff09;已经成为一个至关重要的组件。它帮助系统在异步处理、负载均衡、解耦等方面提供了强大的支持…...

    WHAT - 已阅读书单

    指数基金投资指南✅ 我们终将变富 纳瓦尔宝典 围城✅ 许三观卖血记✅ 骆驼祥子✅ 活着 白鹿原✅ 百年孤独 君主论 阿Q正传✅ 蛤蟆先生去看心理医生✅ 思考&#xff0c;快与慢 三体✅ 人类简史&#xff1a;从动物到上帝✅ 明朝那些事✅ 三国演义✅ 中国历代政治得失✅ 资治…...

    代码随想录算法训练营第60期第十七天打卡

    今天我们继续进入二叉树的下一个章节&#xff0c;今天的内容我在写今天的博客前大致看了一下部分题目难度不算大&#xff0c;那我们就进入今天的题目。 第一题对应力扣编号为654的题目最大二叉树 这道题目的坑相当多&#xff0c;我第一次题目没有看明白就是我不知道到底是如何…...

    C 语言数组详解

    一、数组的基本概念 在 C 语言中&#xff0c;数组是一种相同数据类型元素的集合&#xff0c;这些元素在内存中连续存储。通过数组&#xff0c;我们可以用一个统一的名字来管理一组相关的数据&#xff0c;并且通过下标&#xff08;索引&#xff09;快速访问其中的每一个元素。例…...

    ADVB协议同步

    关于视频传输&#xff0c;有多种控制时序。协议标准允许设计者选择有限的几个速率的接口来满足 系统设计目标。例如&#xff0c;一些系统使用总线时序发送信息通过line-by-line;在这个案例中&#xff0c; 容器的sof作为vsync同步的点。horizontal line blanding将插入idles,ADV…...

    基于LAB颜色空间的增强型颜色迁移算法

    本文算法使用Grok完成所有内容&#xff0c;包含算法改进和代码编写&#xff0c;可大大提升代码编写速度&#xff0c;算法改进速度&#xff0c;提供相关idea&#xff0c;提升效率&#xff1b; 概述 本文档描述了一种基于LAB颜色空间的颜色迁移算法&#xff0c;用于将缩略图D的…...

    复合材料高置信度 DIC 测量与高级实验技术研讨会邀请函

    邀请函 2025年5月8日 上海 中国复合材料学会官网会议通知 您可以点击上方蓝字跳转官网查看官网信息 主办单位&#xff1a; 中国复合材料学会 协办单位&#xff1a; 研索仪器科技&#xff08;上海&#xff09;有限公司 数字图像相关技术&#xff08;Digital Image Correla…...

    解决docker部署MySQL的max_allowed_packet 限制问题

    报错 Error querying database. Cause: com.mysql.cj.jdbc.exceptions.PacketTooBigException: Packet for query is too large (2,471 > 2,048). You can change this value on the server by setting the max_allowed_packet variable. ### The error may exist in file …...

    【XR手柄交互】Unity 中使用 InputActions 实现手柄控制详解(基于 OpenXR + Unity新输入系统(Input Actions))

    摘要&#xff1a; 本文主要介绍如何使用 Input Actions&#xff08;Unity 新输入系统&#xff09; OpenXR 来实现 VR手柄控制&#xff08;监听ABXY按钮、摇杆、抓握等操作&#xff09;。 &#x1f3ae; Unity 中使用 InputActions 实现手柄控制详解&#xff08;基于 OpenXR 新…...

    C++:继承机制详解

    目录 一.继承的概念及定义 一&#xff09;.继承的概念 二&#xff09;.继承定义 1.定义格式 2.继承类型 3.继承类模板 二.基类和派生类间的转换 三.继承中的作用域 四.派生类的默认成员函数 一&#xff09;.4个常见默认成员函数 二&#xff09;.不可被继承的类 五…...

    自然语言处理+知识图谱:智能导诊的“大脑”是如何工作的?

    智能导诊系统定义与作用 智能导诊系统是一种基于人工智能技术的医疗辅助工具&#xff0c;旨在提高医疗服务效率、改善患者就医体验、降低医院运营成本&#xff0c;通过自然语言处理技术&#xff0c;智能导诊系统能够自动回答患者的常见问题&#xff0c;帮助患者快速了解自己的…...

    论文阅读笔记——ZeroGrasp: Zero-Shot Shape Reconstruction Enabled Robotic Grasping

    ZeroGrasp 论文 多视角重建计算大、配置复杂&#xff0c;本文将稀疏体素重建&#xff08;快且效果好&#xff09;引入机器人抓取且只考虑单目重建&#xff0c;通过利用基于物理的接触约束与碰撞检测&#xff08;这对精确抓取至关重要&#xff09;&#xff0c;提升三维重建质量将…...

    Qt 调试信息重定向到本地文件

    1、在Qt软件开发过程中&#xff0c;我们经常使用qDebug()输出一些调试信息在QtCreator终端上。 但若将软件编译、生成、打包为一个完整的可运行的程序并安装在系统中后&#xff0c;系统中没有QtCreator和编译环境&#xff0c;那应用程序出现问题&#xff0c;如何输出信息排查…...

    Android Studio开发中Application和Activity生命周期详解

    文章目录 Application生命周期Application生命周期概述Application关键回调方法onCreate()onConfigurationChanged()onLowMemory()onTrimMemory()onTerminate() Application生命周期管理最佳实践 Activity生命周期Activity生命周期概述Activity生命周期回调方法onCreate()onSta…...

    vite+vue2+elementui构建之 package.json

    webpack版本太低&#xff0c;构建依赖太多&#xff0c;头大。 各种查阅资料&#xff0c;弄了一份直通构建vite构建elementUi核心文件&#xff0c; 构建基于开源若依vue2vue3版本改造&#xff0c;感谢开源&#xff0c;感谢若依。 vitevue2elementui构建之 vite.config.js-CSD…...

    安全编排自动化与响应(SOAR):从事件响应到智能编排的技术实践

    安全编排自动化与响应&#xff08;SOAR&#xff09;&#xff1a;从事件响应到智能编排的技术实践 在网络安全威胁复杂度指数级增长的今天&#xff0c;人工处理安全事件的效率已难以应对高频攻击&#xff08;如日均万级的恶意IP扫描&#xff09;。安全编排自动化与响应&#xf…...

    《Keras 3 :使用 TFServing 提供 TensorFlow 模型》

    《Keras 3 :使用 TFServing 提供 TensorFlow 模型》 作者:Dimitre Oliveira 创建日期:2023/01/02 最后修改时间:2023/01/02 描述:如何使用 TensorFlow Serving 为 TensorFlow 模型提供服务。 (i) 此示例使用 Keras 3 在 Colab 中查看 GitHub 源 介绍 构建机器学习模…...

    深入理解C++ 中的list容器

    目录 一、引言 二、list的基本介绍 2.1 底层结构 2.2 特性 三、list的使用 3.1 构造函数 3.2 迭代器的使用 3.3 容量相关操作 3.4 元素访问相关操作 3.5 修改器操作 3.6 迭代器失效问题 四、list的模拟实现 4.1 节点定义 4.2 迭代器实现 4.3 list类实现 五、lis…...

    附赠二张图,阐述我对大模型的生态发展、技术架构认识。

    文章精炼&#xff0c;用两张图说明大模型发展业态方向&#xff0c;以及大模型主体技术架构。&#xff08;目前还需要进一步验证我的Thought && ideas&#xff0c;等待机会吧.........&#xff09; 图一&#xff1a;探究大模型三个层次应用方向&#xff0c;浅层次入门简…...

    Java实现加密(七)国密SM2算法的签名和验签(附商用密码检测相关国家标准/国密标准下载)

    目录 一、国密标准中&#xff0c;关于SM2签名验签的定义二、SM2签名和验签的实现原理1. 前置知识2. 签名生成过程3. 验签过程4. 数学正确性证明5. 安全性与注意事项 三、带userId、不带userId的区别1. 核心区别2.算法区别(1) 哈希计算过程(2) 签名验签流程 四、Java代码实现1. …...

    贪心算法~~

    目录 一、理论基础 二、题目练习 &#xff08;1&#xff09;455. 分发饼干 &#xff08;2&#xff09;53. 最大子数组和 - 力扣 &#xff08;3&#xff09;122. 买卖股票的最佳时机 II - 力扣&#xff08;LeetCode&#xff09; &#xff08;4&#xff09;860. 柠檬水找零…...