K8S - Service简介和 1个简单NodePort例子

大纲图

在这里插入图片描述



流量方向

在这里插入图片描述

如上图, 当用户or 别的service 从k8s 集群外部访问 集群内的services 流量方向有两种

一种是垂直方向, 通过域名 -> Load Balancer -> gateway -> services , 在k8s 一般是通过ingress 来实现, 而ingress 不是本文的范围内
另一种是横向流量, 因为每个service 基本都在不同的pods, 甚至是不同的nodes, 它们如何互相沟通, 这就是k8s service 的负责范围.




Service 的基本定义

严格来说,Kubernetes中的Service仅仅包括ClusterIP、NodePort和LoadBalancer这三种类型。

ClusterIP:

是默认的Service类型,为 Pod集合分配一个仅集群内部可达的虚拟IP地址。只能从集群内访问。
通常用来定义内部微服务。

NodePort:

除了分配 ClusterIP 外,还会在每一个 Node 上享有一个高端口号暴露服务。
可以通过 : 从集群外访问服务。但不经常使用,局限性较大。

LoadBalancer:

使用云平台本身的负载均衡功能,会在平台上创建一个负载均衡器。
外部流量进入负载均衡器,会转发到集群中能处理请求的节点。
这种类型的Service需要云平台原生支持。

所以总体来说,ClusterIP用于内部服务发现和通信,NodePort和LoadBalancer可以在某种程度上从外部访问服务,但不如Ingress功能全面。




NodePort 基本介绍

NodePort类型的Service是Kubernetes中最常见的一种服务类型。让我来详细介绍一下NodePort Service:
NodePort Service会在每个NodeNode上随机分配一个端口(默认范围30000-32767),通过这个端口就可以从集群外访问Service。

与ClusterIP不同,NodePort Service不仅分配一个内部ClusterIP,还会将服务暴露到每个Node的同一端口上。
客户端可以通过任何一个Node的IP和端口进行访问,例如:NodeIP:NodePort。

NodePort使得外部应用能够找到服务,但不提供负载均衡。流量直接到达Node上服务的首个Pod。
这种类型适用于测试和非生产环境,在生产环境一般不推荐直接使用。
它可以作为集群负载测试的简单方式,也可用于开发和调试服务。

和LoadBalancer相比,NodePort不需要外部负载均衡器支持,在任何云环境下都可以使用。

所以总结来说,NodePort Service通过在集群中的每个节点上映射一个端口,来暴露服务至外部,实现了较为简单的外部访问能力。

即使NodePort 更常用与测试环境, 但是学习nodePort 对k8s 可以加深对k8s 内部网络访问规则的理解




NodePort 的个例子




构造1个接口用于return hostname信息

/actuator/info

@Configuration
@Slf4j
public class MainConfigs {
    @Bean("hostname")
    public String hostname() {
        return getHostName();
    }

    private String getHostName() {
        log.info("MainConfigs: getHostName ...");
        String hostName = "unknown";
        try {
            hostName = java.net.InetAddress.getLocalHost().getHostName();
        } catch (Exception e) {
            log.error("Error in getting hostname...", e);
        }
        return hostName;
    }
}
@Component
@Slf4j
public class AppVersionInfo implements InfoContributor {

    @Value("${pom.version}") // https://stackoverflow.com/questions/3697449/retrieve-version-from-maven-pom-xml-in-code
    private String appVersion;

    @Autowired
    private String hostname;

    @Override
    public void contribute(Info.Builder builder) {
        log.info("AppVersionInfo: contribute ...");
        builder.withDetail("app", "Sales API")
                .withDetail("version", appVersion)
                .withDetail("hostname",hostname)
                .withDetail("description", "This is a simple Spring Boot application to demonstrate the use of BigQuery in GCP.");
    }
}




编写yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels: # label of this deployment
    app: bq-api-service # custom defined
    author: Jason
  name: bq-api-service-deploy-sample
  namespace: default
spec:
  replicas: 3           # desired replica count, Please note that the replica Pods in a Deployment are typically distributed across multiple nodes.
  revisionHistoryLimit: 10
  selector: # label of the Pod that the Deployment is managing,, it's mandatory, without it , we will get this error 
            # error: error validating data: ValidationError(Deployment.spec.selector): missing required field "matchLabels" in io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector ..
    matchLabels:
      app: bq-api-service
  strategy: # Strategy of upodate
    type: RollingUpdate # RollingUpdate or Recreate
    rollingUpdate:
      maxSurge: 25% # The maximum number of Pods that can be created over the desired number of Pods during the update
      maxUnavailable: 25% # The maximum number of Pods that can be unavailable during the update
  template: # Pod template
    metadata:
      labels:
        app: bq-api-service # label of the Pod that the Deployment is managing. must match the selector, otherwise, will get the error Invalid value: map[string]string{"app":"bq-api-xxx"}: `selector` does not match template `labels`
    spec:
      containers:
      - image: europe-west2-docker.pkg.dev/jason-hsbc/my-docker-repo/bq-api-service:1.1.4 # image of the container
        imagePullPolicy: IfNotPresent
        name: bq-api-service-container
      restartPolicy: Always # Restart policy for all containers within the Pod
      terminationGracePeriodSeconds: 10 # The period of time in seconds given to the Pod to terminate gracefully
       
---
apiVersion: v1 #  api version can be v1 or apps/v1
kind: Service 
metadata:
  name: bq-api-service-1 # name of the service
  labels:
    app: bq-api-service # label of the service
spec:
  selector: # Label of the Pod that the Service is selecting 
    app: bq-api-service
  ports:
  - port: 32111 # port of the service
    targetPort: 8080 # port of the Pod
    name: 8080-port # name of the port
  type: NodePort # type of the service, NodePort, ClusterIP, LoadBalancer

在这个yaml 中
我们构建了1个deployment, 包括3个pod 副本

还有1个nodePort service, 定义了service pod 是 32111 (随便定义, 一般跟target port一样), target port 是 8080 (必须跟docker file 暴露的端口一至)




执行yaml

正常用kubectl 命令执行

root@k8s-master:~/k8s-s/services# kubectl apply -f bq-api-service-sample.yaml 
deployment.apps/bq-api-service-deploy-sample created
service/bq-api-service-1 created




查看resource

先看 nodes

NAME         STATUS   ROLES                  AGE   VERSION   INTERNAL-IP    EXTERNAL-IP   OS-IMAGE                         KERNEL-VERSION          CONTAINER-RUNTIME   LABELS
k8s-master   Ready    control-plane,master   43d   v1.23.6   192.168.0.3    <none>        Debian GNU/Linux 11 (bullseye)   5.10.0-28-cloud-amd64   docker://25.0.3     beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-master,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node-role.kubernetes.io/master=,node.kubernetes.io/exclude-from-external-load-balancers=
k8s-node0    Ready    <none>                 43d   v1.23.6   192.168.0.6    <none>        Debian GNU/Linux 11 (bullseye)   5.10.0-28-cloud-amd64   docker://25.0.3     beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node0,kubernetes.io/os=linux
k8s-node1    Ready    <none>                 43d   v1.23.6   192.168.0.44   <none>        Debian GNU/Linux 11 (bullseye)   5.10.0-28-cloud-amd64   docker://25.0.3     beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node1,kubernetes.io/os=linux
k8s-node3    Ready    <none>                 23d   v1.23.6   192.168.0.45   <none>        Debian GNU/Linux 11 (bullseye)   5.10.0-28-cloud-amd64   docker://25.0.3     beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node3,kubernetes.io/os=linux

可以查看各个node的ip 我们有1个master 和3 台nodes

再看pods

root@k8s-master:~/k8s-s/services# kubectl get pods -o wide --show-labels
NAME                                           READY   STATUS    RESTARTS   AGE     IP             NODE        NOMINATED NODE   READINESS GATES   LABELS
bq-api-service-deploy-sample-f448cf6ff-c8zlp   1/1     Running   0          6m47s   10.244.2.104   k8s-node0   <none>           <none>            app=bq-api-service,pod-template-hash=f448cf6ff
bq-api-service-deploy-sample-f448cf6ff-tkxck   1/1     Running   0          6m47s   10.244.1.45    k8s-node1   <none>           <none>            app=bq-api-service,pod-template-hash=f448cf6ff
bq-api-service-deploy-sample-f448cf6ff-vvkt9   1/1     Running   0          6m47s   10.244.3.54    k8s-node3   <none>           <none>            app=bq-api-service,pod-template-hash=f448cf6ff
root@k8s-master:~/k8s-s/services# 

可以见3个pods 被create, 分布在3个不同的nodes node0, node1 和 node3

再看service

root@k8s-master:~/k8s-s/services# kubectl get svc -o wide --show-labels
NAME               TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)           AGE     SELECTOR             LABELS
bq-api-service-1   NodePort    10.105.158.88   <none>        32111:31372/TCP   7m58s   app=bq-api-service   app=bq-api-service
kubernetes         ClusterIP   10.96.0.1       <none>        443/TCP           21h     <none>               component=apiserver,provider=kubernetes

可见1个名字是 bq-api-service-1的NodePort service 被创建, 在PORT(S) 属性里 的值是 32111:31372

其中这个32111是service 本身的port, 而31372 是1个随机生成的port, 可以让k8s外部通过 node ip:31372 去访问这个service

而kubectl get svc 这个命令是不能显示target port 信息
要查看taget port则要查看yaml 信息

root@k8s-master:~/k8s-s/services# kubectl get svc bq-api-service-1 -o yaml
apiVersion: v1
kind: Service
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"labels":{"app":"bq-api-service"},"name":"bq-api-service-1","namespace":"default"},"spec":{"ports":[{"name":"8080-port","port":32111,"targetPort":8080}],"selector":{"app":"bq-api-service"},"type":"NodePort"}}
  creationTimestamp: "2024-04-07T14:44:56Z"
  labels:
    app: bq-api-service
  name: bq-api-service-1
  namespace: default
  resourceVersion: "2301903"
  uid: 6dc89e70-6d6f-4965-a613-246c085ca1ef
spec:
  clusterIP: 10.105.158.88
  clusterIPs:
  - 10.105.158.88
  externalTrafficPolicy: Cluster
  internalTrafficPolicy: Cluster
  ipFamilies:
  - IPv4
  ipFamilyPolicy: SingleStack
  ports:
  - name: 8080-port
    nodePort: 31372
    port: 32111
    protocol: TCP
    targetPort: 8080
  selector:
    app: bq-api-service
  sessionAffinity: None
  type: NodePort
status:
  loadBalancer: {}

再看endpoint

root@k8s-master:~/k8s-s/services# kubectl get endpoints -o wide --show-labels
NAME               ENDPOINTS                                             AGE   LABELS
bq-api-service-1   10.244.1.45:8080,10.244.2.104:8080,10.244.3.54:8080   17m   app=bq-api-service
kubernetes         192.168.0.3:6443                                      21h   endpointslice.kubernetes.io/skip-mirror=true

重点来了, 一个与service 同名的endpoint 被创建出来, 其实service 与 endpoint 是1 1 对应的, 可以把endpoint 看作service 的属性

endpoints 有3个
10.244.1.45:8080,10.244.2.104:8080,10.244.3.54:8080

其实他们正是 是3个nodes的内部ip + target port




测试

正常我们要通过随机生成的端口nodePort: 31372 来访问

我们先登陆一台k8s 集群外的server

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1460 qdisc mq state UP group default qlen 1000
    link/ether 42:01:c0:a8:00:23 brd ff:ff:ff:ff:ff:ff
    altname enp0s4
    inet 192.168.0.35/32 brd 192.168.0.35 scope global dynamic ens4
       valid_lft 53636sec preferred_lft 53636sec
    inet6 fe80::4001:c0ff:fea8:23/64 scope link 
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP>
...

用curl 命令来测试

gateman@tf-vpc0-subnet0-main-server:~$ curl 192.168.0.6:31372/actuator/info
{"app":"Sales API","version":"1.1.4","hostname":"bq-api-service-deploy-sample-f448cf6ff-tkxck","description":"This is a simple Spring Boot application to demonstrate the use of BigQuery in GCP."}
gateman@tf-vpc0-subnet0-main-server:~$ curl 192.168.0.6:31372/actuator/info
{"app":"Sales API","version":"1.1.4","hostname":"bq-api-service-deploy-sample-f448cf6ff-c8zlp","description":"This is a simple Spring Boot application to demonstrate the use of BigQuery in GCP."}
gateman@tf-vpc0-subnet0-main-server:~$ curl 192.168.0.6:31372/actuator/info
{"app":"Sales API","version":"1.1.4","hostname":"bq-api-service-deploy-sample-f448cf6ff-tkxck","description":"This is a simple Spring Boot application to demonstrate the use of BigQuery in GCP."}
gateman@tf-vpc0-subnet0-main-server:~$ curl 192.168.0.6:31372/actuator/info
{"app":"Sales API","version":"1.1.4","hostname":"bq-api-service-deploy-sample-f448cf6ff-c8zlp","description":"This is a simple Spring Boot application to demonstrate the use of BigQuery in GCP."}
gateman@tf-vpc0-subnet0-main-server:~$ curl 192.168.0.6:31372/actuator/info
{"app":"Sales API","version":"1.1.4","hostname":"bq-api-service-deploy-sample-f448cf6ff-c8zlp","description":"This is a simple Spring Boot application to demonstrate the use of BigQuery in GCP."}
gateman@tf-vpc0-subnet0-main-server:~$ curl 192.168.0.6:31372/actuator/info
{"app":"Sales API","version":"1.1.4","hostname":"bq-api-service-deploy-sample-f448cf6ff-vvkt9","description":"This is a simple Spring Boot application to demonstrate the use of BigQuery in GCP."}
gateman@tf-vpc0-subnet0-main-server:~$ 

在多次执行的情况下, 虽然我们curl 指定是 node0 的ip , 但是实际上, 返回的hostname 是随机的, 包含其他node 的结果, 所以nodeport service 是包含Loadbalance 的功能的

NodePort, service port, target port的作用

从service 的yaml 可以看出, 当这个service 被创建后, 3个ports 出现了

分别是
nodePort: 31372
port: 32111
targetPort: 8080

其中nodePort 31372 是用于被集群外访问的端口, targetPort 是Pod 的端口 , 置于port 32111 是什么来的
其实我之前的文章已经介绍过, 这里的32111 port 是service 本身的port
https://editor.csdn.net/md/?articleId=131278799
也就是讲 service 有两个端口, 1个是被外部访问的, 另1个是service自己内部端口

其实如果我们在集群内任何台主机, 是可以同过service 的ip 和 service 的port去访问的


root@k8s-master:~/k8s-s/services# kubectl get svc bq-api-service-1
NAME               TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)           AGE
bq-api-service-1   NodePort   10.105.158.88   <none>        32111:31372/TCP   47m
root@k8s-master:~/k8s-s/services# curl 10.105.158.88:32111/actuator/info
{"app":"Sales API","version":"1.1.4","hostname":"bq-api-service-deploy-sample-f448cf6ff-tkxck","description":"This is a simple Spring Boot application to demonstrate the use of BigQuery in GCP."}

如何我们进入某个pod的容器
甚至可以用service name 和 service port 去访问

root@k8s-master:~# kubectl get pods
NAME                                           READY   STATUS    RESTARTS   AGE
bq-api-service-deploy-sample-f448cf6ff-c8zlp   1/1     Running   0          56m
bq-api-service-deploy-sample-f448cf6ff-tkxck   1/1     Running   0          56m
bq-api-service-deploy-sample-f448cf6ff-vvkt9   1/1     Running   0          56m
root@k8s-master:~# kubectl exec -it bq-api-service-deploy-sample-f448cf6ff-c8zlp -- /bin/bash
root@bq-api-service-deploy-sample-f448cf6ff-c8zlp:/app# curl http://bq-api-service-1:32111/actuator/info
{"app":"Sales API","version":"1.1.4","hostname":"bq-api-service-deploy-sample-f448cf6ff-tkxck","description":"This is a simple Spring Boot application to demonstrate the use of BigQuery in GCP."}

所以看出service port 32111 是被pod 容器内部用的




nodePort 图例

还是重新画张图加深理解

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

免费https详细教程

简单叙述一下https的定义和实现https的一些基本作用&#xff0c;然后会给到申请SSL证书的方式以及安装部署流程&#xff0c;最终实现网站的https访问。 随着互联网的快速发展&#xff0c;网络安全问题日益凸显。在互联网上传输敏感信息、进行在线交易和共享个人数据时&#xf…

nginx配置实例-负载均衡

目录 一、目的&#xff1a;实现效果 二、准备工作 三、实验部署 3.1修改第二台Tomcat服务器的监听端口为8081 3.2修改完成后&#xff0c;重新启动tomcat8081这台服务器。 3.3在浏览器测试 3.4在两台tomcat里面webapps目录中&#xff0c;创建名称是edu的文件夹&#xff0c…

Vue的学习之旅-part3

Vue的学习之旅-part1 vue的自带指令v-model的修饰符 一般用于input输入框中v-model.numberv-model.trimv-slot 作用域插槽具名插槽插槽-组件数据传递注意点1&#xff1a;注意点2&#xff1a; v-on: 绑定触发事件v-on监听事件的修饰符冒泡&#xff1a; 通过.stop阻止阻止默认行为…

软考118-上午题-【软件工程】-能力成熟度模型

一、考试题型 选择题&#xff08;13题&#xff09; 二、能力成熟度模型CMM 能力成熟度模型CMM的研究目的是&#xff1a;提供一种评价软件承接方能力的方法&#xff0c;同时它可帮助软件组织改进其软件过程。 CMM 将软件过程改进分为以下5个成熟度级别&#xff1a; 1、初始级…

探索实践昏暗光线低光照场景下目标检测,基于YOLOv7【tiny/l/x】模型开发构建昏暗光线低光照场景下的目标检测识别系统

昏暗光线低光照条件下的目标检测问题&#xff0c;是机器视觉领域一个长期存在且持续受到关注的挑战。这个问题的背景主要源自现代社会对机器视觉技术的广泛需求&#xff0c;特别是在光线条件不佳的环境下&#xff0c;如夜间监控、自动驾驶、安防系统等场景。在昏暗光线或低光照…

849. Dijkstra求最短路 I

tips&#xff1a; 采用0x3f3f3f3f作为一个极大值&#xff1a; 1061109567 //是一个很大的数&#xff0c;可以用来代表∞&#xff1b; 在memset里0x3f表示为0x3f3f3f3f memset(a, 0x3f, sizeof a); //0x是十六进制的意思&#xff1b; memset()是对char操作&#xff0c;即一个…

海外媒体宣发套餐推广8个要点解析为标题-华媒舍

在当前全球化的时代背景下&#xff0c;海外市场的开拓对于企业的发展至关重要。而海外媒体宣传是一种有效的推广方式&#xff0c;可以帮助企业在全球范围内打开市场。本文将对8个海外媒体宣发套餐的推广要点进行解析&#xff0c;帮助企业了解如何在海外市场进行宣传推广。 1. 媒…

js,uniapp,vue,小写数字转化为大写

应用场景&#xff1a; 把1、2、3&#xff0c;转为一、二、三 方法&#xff1a; retBigSrt(num) {const changeNum [零, 一, 二, 三, 四, 五, 六, 七, 八, 九]const unit [, 十, 百]num parseInt(num)const getWan (temp) > {const strArr temp.toString().split().re…

论文阅读《Semantic Prompt for Few-Shot Image Recognition》

论文地址&#xff1a;https://arxiv.org/pdf/2303.14123.pdf 论文代码&#xff1a;https://github.com/WentaoChen0813/SemanticPrompt 目录 1、存在的问题2、算法简介3、算法细节3.1、预训练阶段3.2、微调阶段3.3、空间交互机制3.4、通道交互机制 4、实验4.1、对比实验4.2、组…

软件杯 深度学习交通车辆流量分析 - 目标检测与跟踪 - python opencv

文章目录 0 前言1 课题背景2 实现效果3 DeepSORT车辆跟踪3.1 Deep SORT多目标跟踪算法3.2 算法流程 4 YOLOV5算法4.1 网络架构图4.2 输入端4.3 基准网络4.4 Neck网络4.5 Head输出层 5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; *…

QT C++(QT对象树与内存泄漏管理,QT中文乱码问题)

文章目录 1. QT对象树与内存泄漏2. QT中文乱码 1. QT对象树与内存泄漏 #include "widget.h" #include "ui_widget.h" #include <QLabel>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);//通过代码构…

SpringCloud Alibaba Sentinel 实现熔断功能

一、前言 接下来是开展一系列的 SpringCloud 的学习之旅&#xff0c;从传统的模块之间调用&#xff0c;一步步的升级为 SpringCloud 模块之间的调用&#xff0c;此篇文章为第十六篇&#xff0c;即使用 Sentinel 实现熔断功能。 二、 Ribbon 系列 首先我们新建两个服务的提供者…

90天玩转Python—05—基础知识篇:Python基础知识扫盲,使用方法与注意事项

90天玩转Python系列文章目录 90天玩转Python—01—基础知识篇:C站最全Python标准库总结 90天玩转Python--02--基础知识篇:初识Python与PyCharm 90天玩转Python—03—基础知识篇:Python和PyCharm(语言特点、学习方法、工具安装) 90天玩转Python—04—基础知识篇:Pytho…

神经网络中的超参数调整

背景 在深度神经网络学习和优化中&#xff0c;超参数调整一项必备技能&#xff0c;通过观察在训练过程中的监测指标如损失loss和准确率来判断当前模型处于什么样的训练状态&#xff0c;及时调整超参数以更科学地训练模型能够提高资源利用率。在本研究中使用了以下超参数&#x…

cocos creator 安卓包 输入法遮挡问题

问题描述 Cocos Creator开发版本&#xff1a; v2.4.x 如上效果图。该需求是&#xff0c;进入游戏后&#xff0c;随机角色名&#xff0c;可以自己编辑。在未修改前 手机输入法遮挡了游戏的编辑框&#xff0c;导致无法直观展示&#xff0c;编辑的文字。尝试各种修改清单文件wind…

2024春算法训练4——函数与递归题解

一、前言 感觉这次的题目都很好&#xff0c;但是E题....&#xff08;我太菜了想不到&#xff09;&#xff0c;别人的题解都上百行了&#xff0c;晕&#xff1b; 二、题解 A-[NOIP2010]数字统计_2024春算法训练4——函数与递归 (nowcoder.com) 这种题目有两种做法&#xff1a;…

Golang单元测试和压力测试

一.单元测试 1.1 go test工具 go语言中的测试依赖go test命令。编写测试代码和编写普通的Go代码过程类似&#xff0c;并不需要学习新的语法&#xff0c;规则和工具。 go test命令是一个按照一定约定和组织的测试代码的驱动程序。在包目录内&#xff0c;所有以_test.go为后缀名的…

自定义gitlog格式

git log命令非常强大而好用&#xff0c;在复杂系统的版本管理中扮演着重要的角色&#xff0c;但默认的git log命令显示出的东西实在太丑&#xff0c;不好好打扮一下根本没法见人&#xff0c;打扮好了用alias命令拍个照片&#xff0c;就正式出道了&#xff01; 在使用git查看lo…

物联网可视化平台

随着数字化转型的深入&#xff0c;物联网技术正在成为企业实现智能化、高效化运营的重要工具。物联网可视化平台&#xff0c;作为连接物理世界与数字世界的桥梁&#xff0c;为企业提供了直观、实时的数据展示和监控能力&#xff0c;从而在数字化转型中扮演着关键角色。 一、物…

链路代价信息、链路状态信息(链路状态通告LSA)

链路代价信息"link cost information" 通常指的是**在网络中&#xff0c;数据包从一个节点传输到另一个节点所需承担的“成本”或者“开销”&#xff0c;这个概念常用于路由算法和网络设计中**。以下是一些关键要点&#xff1a; 1. **路径开销**&#xff1a;路径开…