k8s Service 服务
文章目录
- 一、为什么需要 Service
- 二、Kubernetes 中的服务发现与负载均衡 -- Service
- 三、用例解读
- 1、Service 语法
- 2、创建和查看 Service
- 四、Headless Service
- 五、集群内访问 Service
- 六、向集群外暴露 Service
- 七、操作示例
- 1、获取集群状态信息
- 2、创建 Service、Deployment
- 3、创建客户端的测试 Pod
- 4、集群内访问 Service 的三种方式
- 4.1、直接通过 Service 的 clusterIP 访问
- 4.2、直接访问 Service 名
- 4.3、通过环境变量访问
- 5、集群外部访问服务
- 5.1、NodePort
- 5.1.1、创建 NodePort 类型的 Service(NodePort的端口范围是 30000-32767)
- 5.1.2、创建 Deployment 模拟后端一组应用 Pod
- 5.1.3、创建并查看
- 5.1.4、通过节点 IP:port 访问
- 5.1.5、通过nodename 也可以访问
- 5.2、LoadBalancer
- 5.2.1、安装METALLB
- 5.2.2、查看MetalLB的安装方式:Installation by manifest
- 5.2.3、创建 MetalLB 的命名空间
- 5.2.4、下载 MetalLB 的安装文件
- 5.2.5、查看 MetalLB 需要的镜像
- 5.2.6、修改 metallb.yaml 文件
- 5.2.7、worker节点提前下载speaker和controller镜像
- 5.2.8、安装 MetalLB
- 5.2.9、查看 Pod 验证安装情况
- 5.2.10、配置地址池
- 5.2.11、创建地址池
- 5.2.12、创建 LoadBalancer 类型的 SVC
- 5.2.13、通过 svc 的 EXTERNAL-IP 访问集群内部的服务
- 5.3、Ingress
- 5.4、HostNetwork
- 5.4.1、给 node 节点添加 role 标签
- 5.4.2、创建使用 hostnetwork 的 Deployment
- 5.4.3、通过节点 ip 访问
- 5.5、HostPort
- 5.5.1、给 node 节点添加 role 标签
- 5.5.2、创建使用 hostport 的deployment
- 5.5.3、通过标签节点 ip + port / pod ip 访问
- 5.6、ExternalName
- 5.6.1、创建 ExternalName 类型的 Service
- 5.6.2、启动临时 pod 测试 DNS 解析
- 5.6.3、域名解析
- 八、架构设计
- 1、Kubernetes 服务发现架构
- 1.1、组件
- 1.2、实际访问链路
一、为什么需要 Service
在 K8s 集群里面会通过 pod 去部署应用,与传统的应用部署不同,传统应用部署在给定的机器上面去部署,我们知道怎么去调用别的机器的 IP 地址;但是在 K8s 集群里面应用是通过 pod 去部署的, 而 pod 生命周期是短暂的。在 pod 的生命周期过程中,比如它创建或销毁,它的 IP 地址都会发生变化,这样就不能使用传统的部署方式,不能指定 IP 去访问指定的应用。
另外在 K8s 的应用部署里,之前虽然学习了 deployment 的应用部署模式,但还是需要创建一个 pod 组,这些 pod 组需要提供一个统一的访问入口,以及怎么去控制流量负载均衡到这个组里面。
比如说测试环境、预发环境和线上环境,其实在部署的过程中需要保持同样的一个部署模板以及访问方式。因为这样就可以用同一套应用的模板在不同的环境中直接发布。
二、Kubernetes 中的服务发现与负载均衡 – Service
最后应用服务需要暴露到外部去访问,需要提供给外部的用户去调用的。我们知道 pod 的网络跟机器不是同一个段的网络,那怎么让 pod 网络暴露到去给外部访问呢?这时就需要服务发现。

在 K8s 里面,服务发现与负载均衡就是 K8s Service。
上图就是在 K8s 里 Service 的架构,K8s Service 向上提供了外部网络以及 pod 网络的访问,即外部网络可以通过 service 去访问,pod 网络也可以通过 K8s Service 去访问。
向下,K8s 对接了另外一组 pod,可以通过 K8s Service 的方式去负载均衡到一组 pod 上面去,这样相当于解决了前面所说的复发性问题,或者提供了统一的访问入口去做服务发现,然后又可以给外部网络访问,解决不同的 pod 之间的访问,提供统一的访问地址。
三、用例解读
1、Service 语法
cat >> my-service.yaml << EOF
apiVersion: v1
kind: Service
metadata:name: my-servicelabels:app: my-service
spec:selector:app: MyAppports:- protocol: TCPport: 80targetPort: 9376
EOF
定义了用于 K8s Service 服务发现的一个协议以及端口。声明了一个名叫 my-service 的一个 K8s Service,它有一个 app:my-service 的 label,它选择了 app:MyApp 这样一个 label 的 pod 作为它的后端。
最后是定义的服务发现的协议以及端口,我们定义的是 TCP 协议,端口是 80,目的端口是 9376,效果是访问到这个 service 80 端口会被路由到后端的 targetPort,就是只要访问到这个 service 80 端口的都会负载均衡到后端 app:MyApp 这种 label 的 pod 的 9376 端口。
2、创建和查看 Service
kubectl apply -f my-service.yamlkubectl describe svc my-service

service 创建好之后,可以看到它的名字是 my-service。Namespace、Label、Selector 这些都跟我们之前声明的一样,这里声明完之后会生成一个 IP 地址,这个 IP 地址就是 service 的 IP 地址,它在集群里面可以被其它 pod 所访问,相当于通过这个 IP 地址提供了统一的一个 pod 的访问入口,以及服务发现。
这里还有一个 Endpoints 的属性,就是我们通过 Endpoints 可以看到:通过前面所声明的 selector 去选择了哪些 pod?以及这些 pod 都是什么样一个状态?比如说通过 selector,我们看到它选择了这些 pod 的一个 IP,以及这些 pod 所声明的 targetPort 的一个端口。

在 service 创建之后,它会在集群里面创建一个虚拟的 IP 地址以及端口,在集群里,所有的 pod 和 node 都可以通过这样一个 IP 地址和端口去访问到这个 service。这个 service 会把它选择的 pod 及其 IP 地址都挂载到后端,这样通过 service 的 IP 地址访问时,就可以负载均衡到后端这些 pod 上面去。
当 pod 的生命周期有变化时,比如说其中一个 pod 销毁,service 就会自动从后端摘除这个 pod。这样实现了:就算 pod 的生命周期有变化,它访问的端点是不会发生变化的。
四、Headless Service
service 创建的时候可以指定 clusterIP:None,告诉 K8s 说我不需要 clusterIP(就是刚才所说的集群里面的一个虚拟 IP),然后 K8s 就不会分配给这个 service 一个虚拟 IP 地址,它没有虚拟 IP 地址怎么做到负载均衡以及统一的访问入口呢?
它是这样来操作的:pod 可以直接通过 service_name 用 DNS 的方式解析到所有后端 pod 的 IP 地址,通过 DNS 的 A 记录的方式会解析到所有后端的 Pod 的地址,由客户端选择一个后端的 IP 地址,这个 A 记录会随着 pod 的生命周期变化,返回的 A 记录列表也发生变化,这样就要求客户端应用要从 A 记录把所有 DNS 返回到 A 记录的列表里面 IP 地址中,客户端自己去选择一个合适的地址去访问 pod。
apiVersion: v1
kind: Service
metadata:name: my-servicelabels:app: my-service
spec:clusterIP: Noneselector:app: MyAppports:- protocol: TCPport: 80targetPort: 9376
可以从看到跟刚才我们声明的模板的区别,就是在spec下加了一个 clusterIP:None,即表明不需要虚拟 IP。

Headless Service 实际效果就是集群的 pod 访问 my-service 时,会直接解析到所有的 service 对应 pod 的 IP 地址,返回给 pod,然后 pod 里面自己去选择一个 IP 地址去直接访问。
五、集群内访问 Service
在集群里面,其他 pod 要怎么访问到我们所创建的这个 service 呢?
有三种方式:
- 首先我们可以通过 service 的虚拟 IP 去访问,比如说刚创建的 my-service 这个服务,通过 kubectl get svc 或者 kubectl discribe service 都可以看到它的虚拟 IP 地址是 10.96.47.23,端口是 80,然后就可以通过这个虚拟 IP 及端口在 pod 里面直接访问到这个 service 的地址;
- 第二种方式直接访问服务名,依靠 DNS 解析,就是同一个 namespace 里 pod 可以直接通过 service 的名字去访问到刚才所声明的这个 service。不同的 namespace 里面,我们可以通过 service 名字加“.”,然后加 service 所在的哪个 namespace 去访问这个 service,例如我们直接用 curl 去访问,就是 my-service:80 就可以访问到这个 service;
- 第三种是通过环境变量访问,在同一个 namespace 里的 pod 启动时,K8s 会把 service 的一些 IP 地址、端口,以及一些简单的配置,通过环境变量的方式放到 K8s 的 pod 里面。在 K8s pod 的容器启动之后,通过读取系统的环境变量比读取到 namespace 里面其他 service 配置的一个地址,或者是它的端口号等等。
比如在集群的某一个 pod 里面,可以直接通过 curl $ 取到一个环境变量的值,比如取到 MY_SERVICE_SERVICE_HOST 就是它的一个 IP 地址,MY_SERVICE 就是刚才我们声明的 my-service,SERVICE_PORT 就是它的端口号,这样也可以请求到集群里面的 MY_SERVICE 这个 service。
kubectl get pods -l app=MyAppkubectl exec -it my-deployment-6866788946-8v9m6 /bin/bashecho $MY_SERVICE_SERVICE_HOSTecho $MY_SERVICE_SERVICE_PORT

六、向集群外暴露 Service
前面介绍的都是在集群里面 node 或者 pod 去访问 service,service 怎么去向外暴露呢?怎么把应用实际暴露给公网去访问呢?
NodePort:这种方法会在集群的所有节点上开放一个端口(称为 NodePort),外部可以通过任意节点的 IP 地址加上这个端口号来访问服务。NodePort 的端口范围默认是 30000-32767。例如,如果你有一个名为 my-service 的服务,Kubernetes 可能会随机分配一个端口,比如 30001,那么你可以通过 :30001 来访问服务 。
LoadBalancer:在支持外部负载均衡器的云服务提供商(如 AWS、Azure、GCP 等)上,你可以创建一个 LoadBalancer 类型的服务。这将自动创建一个外部负载均衡器,并将外部流量转发到服务。LoadBalancer 类型的服务会在云提供商的负载均衡器上配置一个公共 IP 地址,你可以通过这个 IP 地址访问服务 。
ExternalName:这种方式通过 CNAME 记录将服务映射到一个外部域名。这意味着当请求发送到 Kubernetes 集群时,DNS 服务会返回一个 CNAME 记录,指向你指定的外部域名。这种方法不涉及流量的转发,而是在 DNS 层面上进行重定向 。
External IP:为服务分配一个或多个外部可访问的 IP 地址。这些 IP 地址通常由云服务提供商管理,可以是静态或动态分配。通过 Service 的 externalIPs 字段指定外部 IP 地址,外部流量可以通过指定的 IP 地址访问 Service。
Ingress:Ingress 是 Kubernetes 的一种 API 对象,它管理外部访问到集群内服务的 HTTP 流量。通过定义 Ingress 规则,你可以控制如何将外部请求路由到集群内的服务。Ingress 通常与 Ingress Controller 一起使用,后者负责实现 Ingress 规则并将流量转发到正确的服务 。
HostPort:在 Pod 级别使用,将 Pod 内的端口映射到宿主机的特定端口。这种方式不是通过 Service 资源实现的,而是在 Pod 定义中使用 hostPort 字段。
HostNetwork:在 Pod 级别使用,允许 Pod 直接使用宿主机的网络命名空间。这意味着 Pod 会绕过 Kubernetes 的网络代理,直接在宿主机上监听网络请求。这种方式不是通过 Service 资源实现的,而是在 Pod 定义中设置 hostNetwork: true。
七、操作示例
1、获取集群状态信息
kubectl get cs

2、创建 Service、Deployment
cat >> service.yaml << EOF
apiVersion: v1
kind: Service
metadata:name: nginx-testlabels:run: nginx
spec:selector:run: nginxports:- protocol: TCPport: 80targetPort: 80
EOF
cat >> server.yaml << EOF
apiVersion: apps/v1
kind: Deployment
metadata:name: nginx-testlabels:run: nginx
spec:replicas: 2selector:matchLabels:run: nginxtemplate:metadata:labels:run: nginxspec:containers:- name: nginximage: nginx:1.16.0imagePullPolicy: IfNotPresent
EOF
kubectl apply -f service.yaml -f server.yamlkubectl get pods -o wide -l run=nginxkubectl describe svc nginx-test

3、创建客户端的测试 Pod
现在去创建一个客户端的 pod 实际去感受一下如何去访问这个 K8s Service
cat >> client-test.yaml << EOF
apiVersion: v1
kind: Pod
metadata:name: test-client
spec:containers:- name: client-testimage: busybox:1.31.0command:- sleep- "3600"
EOF

4、集群内访问 Service 的三种方式
4.1、直接通过 Service 的 clusterIP 访问
kubectl exec -it test-client /bin/shwget -qO- 10.96.252.19

4.2、直接访问 Service 名
wget -qO- nginx-test

不同命名空间时也可以通过 .namespace 来访问 service

4.3、通过环境变量访问
通过执行 env 命令看一下它实际注入的环境变量的情况。看一下 nginx-test 的 service 的各种配置已经注册进来了。
env

wget -qO- $NGINX_TEST_SERVICE_HOST

5、集群外部访问服务
5.1、NodePort
NodePort 类型的 Service 提供了一种将集群内部的服务暴露给外部客户端访问的方式。通过创建一个类型为 NodePort 的 Service,Kubernetes 控制器会在每个运行中的节点上打开一个固定的端口(默认范围是30000-32767,但可以根据需要进行配置)。外部流量可以通过这个节点端口访问到集群内的服务。

5.1.1、创建 NodePort 类型的 Service(NodePort的端口范围是 30000-32767)
cat >> nodeport-svc.yaml << EOF
apiVersion: v1
kind: Service
metadata:name: nodeport-service
spec:type: NodePortports:- port: 8080targetPort: 80nodePort: 30120selector:app: nginx
EOF
5.1.2、创建 Deployment 模拟后端一组应用 Pod
cat >> nodeport-deploy.yaml << EOF
apiVersion: apps/v1
kind: Deployment
metadata:name: nodeport-deploy
spec:replicas: 3selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:containers:- name: nginximage: nginx:1.16.0ports:- containerPort: 80
EOF
5.1.3、创建并查看
kubectl apply -f nodeport-deploy.yaml -f nodeport-svc.yamlkubectl get pods -l app=nginxkubectl get svckubectl describe svc nodeport-service

5.1.4、通过节点 IP:port 访问
curl 192.168.112.10:30120

5.1.5、通过nodename 也可以访问

5.2、LoadBalancer
当创建一个 LoadBalancer 类型的服务时,Kubernetes 会尝试通过云提供商或第三方负载均衡解决方案来创建一个负载均衡器。这个负载均衡器会分配一个静态的外部IP地址(或 DNS 名称),并会将外部流量路由到集群内的服务。

5.2.1、安装METALLB
使用LoadBalancer的方式进行服务发布,需要借助第三方的工具(METALLB)。
每个svc都有一个私有地址,只能在集群内部访问,如果我们把svc的类型设置为LoadBalancer,则svc会获取到一个外部IP,这个外部IP来自地址池,示例使用METALLB配置地址池。
METALLB官网

5.2.2、查看MetalLB的安装方式:Installation by manifest

5.2.3、创建 MetalLB 的命名空间
kubectl create ns metallb-system
5.2.4、下载 MetalLB 的安装文件
wget https://raw.githubusercontent.com/metallb/metallb/v0.11.0/manifests/metallb.yamlwget https://raw.githubusercontent.com/metallb/metallb/v0.11.0/manifests/namespace.yaml
5.2.5、查看 MetalLB 需要的镜像
grep image metallb.yaml

5.2.6、修改 metallb.yaml 文件
image同级下添加如下字段
imagePullPolicy: IfNotPresent

5.2.7、worker节点提前下载speaker和controller镜像
所有节点都执行拉取操作
docker pull quay.io/metallb/speaker:v0.11.0docker pull quay.io/metallb/controller:v0.11.0
5.2.8、安装 MetalLB
kubectl apply -f namespace.yaml -f metallb.yaml
5.2.9、查看 Pod 验证安装情况
kubectl get pods -n metallb-system

5.2.10、配置地址池

cat >> IPAddressPool.yaml << EOF
apiVersion: v1
kind: ConfigMap
metadata:namespace: metallb-systemname: config
data:config: |address-pools:- name: defaultprotocol: layer2addresses:- 192.168.112.100-192.168.112.200
EOF
5.2.11、创建地址池
kubectl apply -f IPAddressPool.yaml

5.2.12、创建 LoadBalancer 类型的 SVC
cat << EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:name: podtestlabels:app: podtest
spec:containers:- name: nginximage: nginx:1.16.0ports:- containerPort: 80
EOF
kubectl expose pod podtest --name=loadbalancer-svc --port=80 --target-port=80 --type=LoadBalancer --selector=app=podtest

查看svc,EXTERNAL-IP地址是从地址池里分配的(默认为首个可分配的ip地址)
5.2.13、通过 svc 的 EXTERNAL-IP 访问集群内部的服务
浏览器访问
192.168.112.100

curl 192.168.112.100

5.3、Ingress
Ingress 是 Kubernetes 中另一种将集群内部的服务暴露给外部的方式。不同于 Service 类型(如 NodePort 和 LoadBalancer),Ingress 提供了一个更高级别的抽象,允许管理员定义更加复杂的路由规则,以便于管理和扩展HTTP和HTTPS服务。

TODO
下一篇单独讲讲吧
5.4、HostNetwork
hostNetwork 是 Kubernetes 中的一个特性选项,但它并不是直接用于将集群内部服务暴露给外部访问的方式,而是指在创建 Pod 时是否使用宿主机的网络栈来进行网络通信。当在 Pod 的规格中设置了 hostNetwork: true 时,Pod 将直接使用宿主机的网络接口而不是 Kubernetes 的服务网络。
5.4.1、给 node 节点添加 role 标签
kubectl label nodes k8s-node1 role=node1kubectl get nodes -L role

5.4.2、创建使用 hostnetwork 的 Deployment
apiVersion: apps/v1
kind: Deployment
metadata:labels:app: nginxname: nginx-deployment
spec:replicas: 1selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:nodeSelector: role: node1hostNetwork: truecontainers:- image: nginx:1.16.0imagePullPolicy: IfNotPresentname: nginxports:- containerPort: 8080
5.4.3、通过节点 ip 访问

在和containers 同级的 hostNetwork: true,表示pod使用宿主机网络,配合 nodeSelector,把pod实例化在固定节点,如上,给node1节点加上标签role: node1 , 通过nodeSelector,nginx就会实例化在node1节点,这样就可以通过node1节点的ip就可以访问这个nginx了。
5.5、HostPort
在 Kubernetes 中,hostPort 是一种配置 Pod 的方式,使得 Pod 内部的应用可以通过特定的端口监听宿主机的网络接口。当 Pod 的容器配置了 hostPort,它将能够接收来自宿主机对应端口的流量。这种方式可以实现外部服务访问集群内部服务的需求,但需要注意的是,使用 hostPort 需要注意端口冲突及安全性问题。
5.5.1、给 node 节点添加 role 标签
kubectl label k8s-node2 role=node2kubectl get nodes -L role

5.5.2、创建使用 hostport 的deployment
apiVersion: apps/v1
kind: Deployment
metadata:labels:app: nginxname: hostport-deploy
spec:replicas: 1selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec: nodeSelector:role: node2containers:- image: nginx:1.16.0imagePullPolicy: IfNotPresentname: nginxports:- containerPort: 8080hostPort: 80
5.5.3、通过标签节点 ip + port / pod ip 访问

和hostNetwork相比多了映射能力,可以把容器端口映射为node节点不同端口,hostPort,当然也需要nodeSelector来固定节点,不然每次创建,节点不同,ip也会改变
5.6、ExternalName
ExternalName 类型的 Service 是 Kubernetes 中用于提供从集群内部访问外部 DNS 名称的一种方式。它的主要目的是简化集群内部应用访问外部服务的过程。当你创建一个类型为 ExternalName 的 Service 时,Kubernetes 会为这个 Service 创建一个 DNS 条目,该条目将解析为指定的外部 DNS 名称。
与 NodePort 或 LoadBalancer 类型的 Service 不同,ExternalName 类型的 Service 不会暴露任何集群内部的服务到外部网络,而是相反,它让集群内部的服务可以访问外部的服务。

5.6.1、创建 ExternalName 类型的 Service
cat << EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:name: service-externalnamelabels:type: externalname
spec:type: ExternalNameexternalName: www.baidu.com
EOF
kubectl get svc -l type=externalname

5.6.2、启动临时 pod 测试 DNS 解析
可以看到集群内部是可以访问外部服务www.baidu.com
kubectl run -it --rm --image=alpine:latest dns-test -- sh

5.6.3、域名解析
- 查看 kube-dns 的 ip 地址
kubectl get svc kube-dns -n kube-system -o custom-columns='ClusterIP:.spec.clusterIP'
- 安装 dig 命令
yum provides digyum install -y bind-utils-9.11.4-26.P2.el7_9.16.x86_64
- 从集群内部解析
ExternalName类型的Service
dig @172.16.0.10 service-externalname.default.svc.cluster.local

八、架构设计
1、Kubernetes 服务发现架构

如上图所示,K8s 服务发现以及 K8s Service 是这样整体的一个架构。
K8s 分为 master 节点和 worker 节点:
- master 里面主要是 K8s 管控的内容;
- worker 节点里面是实际跑用户应用的一个地方。
在 K8s master 节点里面有 APIServer,就是统一管理 K8s 所有对象的地方,所有的组件都会注册到 APIServer 上面去监听这个对象的变化,比如说我们刚才的组件 pod 生命周期发生变化这些事件。
1.1、组件
这里面最关键的有三个组件:
-
一个是 Cloud Controller Manager,负责去配置 LoadBalancer 的一个负载均衡器给外部去访问;
-
另外一个就是 Coredns,通过 Coredns 去观测 APIServer 里面的 service 后端 pod 的一个变化,去配置 service 的 DNS 解析,实现可以通过 service 的名字直接访问到 service 的虚拟 IP,或者是 Headless 类型的 Service 中的 IP 列表的解析;
-
在每个 node 里面会有 kube-proxy 这个组件,它通过监听 service 以及 pod 变化,然后实际去配置集群里面的 node pod 或者是虚拟 IP 地址的一个访问。
1.2、实际访问链路
比如说从集群内部的一个 Client Pod3 去访问 Service:
Client Pod3 首先通过 Coredns 这里去解析出 ServiceIP,Coredns 会返回给它 ServiceName 所对应的 service IP 是什么,这个 Client Pod3 就会拿这个 Service IP 去做请求,它的请求到宿主机的网络之后,就会被 kube-proxy 所配置的 iptables 或者 IPVS 去做一层拦截处理,之后去负载均衡到每一个实际的后端 pod 上面去,这样就实现了一个负载均衡以及服务发现。
对于外部的流量,比如说刚才通过公网访问的一个请求。它是通过外部的一个负载均衡器 Cloud Controller Manager 去监听 service 的变化之后,去配置的一个负载均衡器,然后转发到节点上的一个 NodePort 上面去,NodePort 也会经过 kube-proxy 配置的一个 iptables,把 NodePort 的流量转换成 ClusterIP,紧接着转换成后端的一个 pod 的 IP 地址,去做负载均衡以及服务发现。
相关文章:
k8s Service 服务
文章目录 一、为什么需要 Service二、Kubernetes 中的服务发现与负载均衡 -- Service三、用例解读1、Service 语法2、创建和查看 Service 四、Headless Service五、集群内访问 Service六、向集群外暴露 Service七、操作示例1、获取集群状态信息2、创建 Service、Deployment3、创…...
安全建设当中的冷门知识
今天说点有趣的话题,也是因为在安全建设过程中,安全员也不太可能都按照最理想的状态去工作,有资源的问题,有管理惰性问题,当然也有管理者本身决策的问题。 安全行业起步较晚,16年才施行网络安全法ÿ…...
python画图|极坐标下的3D surface
前述学习过程中,我们已经掌握了3D surface的基本绘制技巧,详见链接: python画图|3D surface基础教程-CSDN博客 基础教程中的3D surface绘制位于笛卡尔坐标系,但有时候会用到极坐标绘图。虽然我们已经学过简单的极坐标绘图技巧&a…...
html+css+js网页设计 旅游 大理旅游7个页面
htmlcssjs网页设计 旅游 大理旅游7个页面 网页作品代码简单,可使用任意HTML辑软件(如:Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修改编辑等操作)。 获取源码 1&#…...
Day 29~42 JavaWeb
Java Web 1、基本概念 1.1、前言 web开发: web,网页的意思,www.baidu.com静态web html,css 提供给所有人看的数据始终不会发生变化动态web 淘宝,几乎是所有的网站 提供给所有人看的数据始终会发生变…...
小程序开发设计-第一个小程序:创建小程序项目④
上一篇文章导航: 小程序开发设计-第一个小程序:安装开发者工具③-CSDN博客https://blog.csdn.net/qq_60872637/article/details/142219152?spm1001.2014.3001.5501 须知:注:不同版本选项有所不同,并无大碍。 一、创…...
C++设计模式——Mediator中介者模式
一,中介者模式的定义 中介者模式是一种行为型设计模式。它通过一个中介者对象将多个对象之间的交互关系进行封装,使得对象之间的交互需要通过中介者对象来完成。该设计模式的结构很容易理解,以中介者为中心。 中介者模式的设计思想侧重于在…...
微服务之间远程调用实现思路
项目使用的Spring Cloud Alibaba框架,微服务之间远程调用使用OpenFeign,具体实现步骤如下: (1)在api工程定义OpenFeign接口,使用FeignClient注解进行定义。 (2)服务提供方定义Open…...
获取STM32 MCU的唯一ID
STM32每个系列都会有唯一的一个芯片序列号(96位bit) STM32F10X 的起始地址是 0x1FFFF7E8 STM32F20X 的起始地址是 0x1FFF7A10 STM32F30X 的起始地址是 0x1FFFF7AC STM32F40X 的起始地址是 0x1FFF7A10 STM32L0XX 的起始地址是 0x1FF80050 STM32L1XX 的起…...
Debian项目实战——环境搭建篇
Debian系统安装 准备工作 1、系统镜像:根据自己的需要选择合适的版本格式:x86 / arm 架构 | 最好下载离线安装版本 | 清华镜像源 2、制作工具:balenaEtcher 3、系统媒介:16G以上U盘最佳 烧录镜像 打开balenaEtcher进行烧录&am…...
CenterNet官方代码—目标检测模型推理部分解析与项目启动
CenterNet模型推理部分解析 CenterNet官方代码环境部署 CenterNet作为2019年CVPR推出的论文,论文中给出了官方代码所在的github仓库地址。https://github.com/xingyizhou/CenterNet。 整个代码的代码量并不是特别大,但整个项目的难点在于使用了老版本的…...
测试开发基础——测试用例的设计
三、测试用例的设计 1. 什么是测试用例 测试用例(Test Case)是为了实施测试而向被测试的系统提供的一组集合,这组集合包含:测试环境、操作步骤、测试数据、预期结果等要素。 设计测试用例原则一:测试用例中一个必需部分是对预期输出或结果进…...
C++第五十一弹---IO流实战:高效文件读写与格式化输出
✨个人主页: 熬夜学编程的小林 💗系列专栏: 【C语言详解】 【数据结构详解】【C详解】 目录 1. C语言的输入与输出 2. 流是什么 3. CIO流 3.1 C标准IO流 3.2 C文件IO流 3.2.1 以写方式打开文件 3.2.1 以读方式打开文件 4 stringstre…...
C++中使用分治法求最大值
在C++中使用分治法(Divide and Conquer)来求一个数组中的最大值是一个经典的问题。分治法是一种通过将原问题分解为若干个小规模相似子问题,递归地求解这些子问题,然后将子问题的解合并成原问题的解的方法。 以下是使用分治法求数组中最大值的步骤: 分解(Divide):将数…...
数据集 CULane 车道线检测 >> DataBall
数据集 CULane 车道线检测 自动驾驶 无人驾驶目标检测 CULane是用于行车道检测学术研究的大规模具有挑战性的数据集。它由安装在六辆由北京不同驾驶员驾驶的不同车辆上的摄像机收集。收集了超过55小时的视频,并提取了133,235帧。数据示例如上所示。我们将数据集分为…...
Android CustomDialog圆角背景不生效的问题
一行解决: window?.setBackgroundDrawableResource(android.R.color.transparent) 原文件: /*** Created by Xinghai.Zhao* 自定义选择弹框*/ SuppressLint("InflateParams", "MissingInflatedId") class CustomDialog(context: Context?) : AlertDia…...
C++速通LeetCode简单第9题-二叉树的最大深度
深度优先算法递归: /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right…...
com.microsoft.sqlserver:sqljdbc4:jar:4.0 was not found产生原因及解决步骤
文章目录 问题sqlserver 包找不到 报错原因分析主要原因 解决方案步骤 1:检查 pom.xml 中的依赖声明步骤 2:配置 Microsoft 的 Maven 仓库步骤 3:强制更新 Maven 依赖步骤 4:清理本地仓库缓存步骤 5:手动下载并安装 sq…...
【算法】 滑动窗口—最长无重复子串
“无重复字符的最长子串”,难度为Medium,看下题目: 输入一个字符串 s,请计算 s 中不包含重复字符的最长子串长度。 比如,输入 s "aabab",算法返回2,因为无重复的最长子串是 "ab…...
SpringBoot2:web开发常用功能实现及原理解析-上传与下载
文章目录 一、上传文件1、前端上传文件给Java接口2、Java接口上传文件给Java接口 二、下载文件1、前端调用Java接口下载文件2、Java接口下载网络文件到本地3、前端调用Java接口下载网络文件 一、上传文件 1、前端上传文件给Java接口 Controller接口 此接口支持上传单个文件和…...
地震勘探——干扰波识别、井中地震时距曲线特点
目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波:可以用来解决所提出的地质任务的波;干扰波:所有妨碍辨认、追踪有效波的其他波。 地震勘探中,有效波和干扰波是相对的。例如,在反射波…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...
Python爬虫实战:研究feedparser库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...
稳定币的深度剖析与展望
一、引言 在当今数字化浪潮席卷全球的时代,加密货币作为一种新兴的金融现象,正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而,加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下,稳定…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
怎么让Comfyui导出的图像不包含工作流信息,
为了数据安全,让Comfyui导出的图像不包含工作流信息,导出的图像就不会拖到comfyui中加载出来工作流。 ComfyUI的目录下node.py 直接移除 pnginfo(推荐) 在 save_images 方法中,删除或注释掉所有与 metadata …...
通过 Ansible 在 Windows 2022 上安装 IIS Web 服务器
拓扑结构 这是一个用于通过 Ansible 部署 IIS Web 服务器的实验室拓扑。 前提条件: 在被管理的节点上安装WinRm 准备一张自签名的证书 开放防火墙入站tcp 5985 5986端口 准备自签名证书 PS C:\Users\azureuser> $cert New-SelfSignedCertificate -DnsName &…...
WPF八大法则:告别模态窗口卡顿
⚙️ 核心问题:阻塞式模态窗口的缺陷 原始代码中ShowDialog()会阻塞UI线程,导致后续逻辑无法执行: var result modalWindow.ShowDialog(); // 线程阻塞 ProcessResult(result); // 必须等待窗口关闭根本问题:…...
springboot 日志类切面,接口成功记录日志,失败不记录
springboot 日志类切面,接口成功记录日志,失败不记录 自定义一个注解方法 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/***…...
HybridVLA——让单一LLM同时具备扩散和自回归动作预测能力:训练时既扩散也回归,但推理时则扩散
前言 如上一篇文章《dexcap升级版之DexWild》中的前言部分所说,在叠衣服的过程中,我会带着团队对比各种模型、方法、策略,毕竟针对各个场景始终寻找更优的解决方案,是我个人和我司「七月在线」的职责之一 且个人认为,…...
