题图摄于北京奥利匹克中心

【编者推荐】本文选自马哥教育 CEO 马永亮老师撰写的《Kubernetes进阶实战(第2版)》,第十三章 13.3.3-13.3.5 节。马老师曾经到我司给云原生开发人员讲授 Kubernetes 的课程,讲解内容细致入微、条理清晰,受到学员一致好评。文末赠书活动,欢迎参加。

《Kubernetes进阶实战(第2版)》新增与重写多种知识点,基于 Kubernetes v1.19 与 v1.20 讲解新特性,值得推荐给大家。感兴趣的读者可参加文末赠书活动,或直接购买。

Contour 是 Kubernetes Ingress 控制器的另一款开源实现,它以高性能的 Envoy 代理程序作为数据平面,支持开箱即用的动态配置和多种高级路由机制,支持 TCP 代理,并且提供了自定义资源(CRD)HTTPProxy 扩展了 Ingress API,它以更丰富的功能集部分地解决了Ingress 原始设计中的缺点,是Ingress控制器的较为出色实现之一。

本文主要就 HTTPProxy 基础、HTTPProxy 高级路由、HTTPProxy 服务韧性三个方面展开介绍 HTTPProxy。

提示:本文中的操作需要读者部署完成了可用的Kubernetes集群,且部署了Contour 作为 Ingress Controller。

(一)   HTTPProxy 基础

HTTPProxy 资源几乎兼容 Ingress 资源的所有功能,只不过它使用独有的资源规范,具体的格式及简要说明如下所示。

apiVersion: projectcontour.io/v1   # API群组及版本
kind: HTTPProxy       # CRD资源的名称
metadata:name <string>namespace <string>      # 名称空间级别的资源
spec:virtualhost <VirtualHost>  # 定义FQDN格式的虚拟主机,类似于Ingress中的hostfqdn <string>       # 虚拟主机FQDN格式的名称tls <TLS>         # 启用HTTPS,且默认以301将HTTP请求重定向至HTTPSsecretName <string>     # 存储证书和私钥信息的Secret资源名称minimumProtocolVersion <string>   # 支持的SSL/TLS协议的最低版本passthrough <boolean>     # 是否启用透传模式,启用时控制器不卸载HTTPS会话clientValidation <DownstreamValidation>   # 验证客户端证书,可选配置caSecret <string>     # 用于验证客户端证书的CA证书routes <[]Route>      # 定义路由规则conditions <[]Condition>    # 流量匹配条件,支持PATH前缀和标头匹配两种检测机制prefix <String>       # PATH路径前缀匹配,类似于Ingress中的path字段permitInsecure <Boolean>   # 是否禁止默认的将HTTP重定向到HTTPS的功能services <[]Service>     # 后端服务,会对应转换为Envoy的Cluster定义name <String>        # 服务名称port <Integer>       # 服务端口protocol <String>     # 到达后端服务的协议,可用值为tls、h2或者h2cvalidation <UpstreamValidation>   # 是否校验服务端证书caSecret <String>  subjectName <string>   # 要求证书中使用的Subject值

需要特别说明的是,在同一个 conditions 字段中使用多个 prefix 前缀时,前缀间将存在串联关系,例如对于第一个前缀 /api 和第二个前缀 /docs 来说,该条件实际匹配的是 /api/docs 路由前缀。但通常在一个条件中只应该使用单个 prefix。

我们以 demoapp 应用为例来说明如何通过 HTTPProxy 将应用发布到 Kubernetes 集群外部。为了隔离其它环境,我们下面先创建一个测试使用的名称空间,以 dev 为例,而后在该名称空间下分别创建 deployments/demoapp 和 service/demoapp 资源。

~$ kubectl create namespace dev
~$ kubectl create deployments demoapp –image=”ikubernetes/demoapp:v1.0“ -n dev
~$ kubectl create service clusterip demoapp –tcp=80 -n dev

下面配置清单中定义的 HTTPProxy 资源将 demoapp 以 HTTP 和 HTTPS 协议同时予以发布,客户端可通过其中任何一种协议发起访问请求。当然,我们也可以将 “permitInsecure: true” 中的值修改为“false”,从而将 HTTP 请求一律重定向至 HTTPS。

apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:name: httpproxy-demonamespace: dev
spec:virtualhost:fqdn: www.ilinux.iotls:secretName: tls-ingress-www-ilinuxminimumProtocolVersion: "tlsv1.1"   # 支持的TLS协议最小版本routes:- conditions:- prefix: /   # PATH路径前缀匹配services:- name: demoappport: 80
permitInsecure: true   # 禁止将HTTP重定向至HTTPS

随后,将上面的定义的 httpproxy/httpproxy-demo 创建于 Kubernetes 上,即可展开访问测试。

~$ kubectl apply -f httpproxy-demo.yaml
httpproxy.projectcontour.io/httpproxy-demo created

资源创建完成后,我们可通过 HTTPProxy 资源描述信息中的 Status 字段来了解其生效结果,有效的配置通常以 valid 进行标识,否则就需要排除问题后重新创建。

~$ kubectl describe httpproxy -n dev
……
Status:Current Status:  validDescription:     valid HTTPProxyLoad Balancer:

随后,即可采用类似于此前的方式,分别对通过 HTTP 和 HTTPS 协议发布的 demoapp 服务进行访问,如下面的命令及结果所示。

~$ curl http://www.ilinux.io
iKubernetes demoapp v1.0 !! ……: demoapp-6c5d545684-v6djh, ServerIP: 10.244.1.7!
~$ curl -k https://www.ilinux.io:30530
iKubernetes demoapp v1.0 !! ……: demoapp-6c5d545684-v6djh, ServerIP: 10.244.1.7!

为了避免与后面几节中的测试产生冲突,测试完成后,建议使用如下方式删除该HTTPProxy资源。

~$ kubectl delete httpproxy/httpproxy-demo -n dev

(二)   HTTPProxy高级路由

除了能实现类似于 Ingress 资源的流量分发等基础功能,HTTPProxy 还封装了 Envoy 相当一部分高级路由功能的API,例如基于标头的路由、流量镜像和流量分割等多种高级路由功能,能帮助用户实现诸如金丝雀部署、蓝绿部署和A/B测试等功能。相关的规范均定义在 HTTPProxy 的 .spec.routes 字段中,其简要格式及功能说明如下所示。

spec:routes <[]Route>      # 定义路由规则conditions <[]Condition>prefix <String>header <HeaderCondition>     # 请求报文标头匹配name <String>          # 标头名称present <Boolean>     # true表示存在该标头即满足条件,值false没有意义contains <String>     # 标头值必须包含的子串notcontains <String>    # 标头值不能包含的子串exact <String>        # 标头值的精确匹配notexact <String>    # 标头值精确反向匹配,即不能与指定的值相同services <[]Service>     # 后端服务,转换为Envoy的集群name <String>port <Integer>protocol <String>  weight <Int64>       # 服务权重,用于流量分割mirror <Boolean>     # 流量镜像requestHeadersPolicy <HeadersPolicy>   # 到上游服务器请求报文的标头策略set <[]HeaderValue>     # 添加标头或设置指定标头的值name <String>value <String>remove <[]String>     # 移除指定的标头responseHeadersPolicy <HeadersPolicy>   # 到下游客户端响应报文的标头策略loadBalancerPolicy <LoadBalancerPolicy>   # 指定要使用的负载均衡策略strategy <String>      # 具体使用的策略,支持Random、RoundRobin、Cookie# 和WeightedLeastRequest,默认为RoundRobinrequestHeadersPolicy <HeadersPolicy>     # 路由级别的请求报文标头策略reHeadersPolicy <HeadersPolicy>         # 路由级别的响应报文标头策略pathRewritePolicy <PathRewritePolicy>    # URL重写replacePrefix <[]ReplacePrefix>prefix <String>         # PATH路由前缀replacement <String>   # 要替换为的目标路径

需要特别说明的是,在同一个 conditions 字段中以不同的列表项分别定义的多个头部条件彼此间存在“逻辑与”关系,这意味着请求报文需要同时满足头部条件的定义才能匹配到设置的规则。

高级路由功能的应用场景通常会依赖同一应用程序两个或以上数量的版本,为了避免其他依赖,这里选择在 dev 名称空间下准备好的 demoapp-v1.1 和 demoapp-v1.2 两个版本的应用,它们都使用 Deployment 控制器编排,且分别有各自的 Service 对象。

~$ kubectl create deployment demoappv11 --image="ikubernetes/demoapp:v1.1" -n dev
deployment.apps/demoappv11 created
~$ kubectl create deployment demoappv12 --image="ikubernetes/demoapp:v1.2" -n dev
deployment.apps/demoappv12 created
~$ kubectl create service clusterip demoappv11 --tcp=80 -n dev
service/demoappv11 created
~$ kubectl create service clusterip demoappv12 --tcp=80 -n dev
service/demoappv12 created

为了便于读者朋友们理解,下面将分别说明几种主流高级路由功能的配置方法。

1. 基于标头的路由

基于标头的流量匹配机制是指检测请求报文的特定头部是否存在,或者其值是否满足表述的条件,而后仅路由测试结果为 True 的请求报文,不能满足测试条件的报文将被忽略,它们可能会由后续的其他路由规则匹配后进行路由,或者由默认路由指定的后端予以服务。在 conditions 字段中的同一个列表项中同时指定的header 和 prefix 之间是“与”关系,即报文必须同时满足两个条件,而不同列表项表达的筛选条件间为“与”关系,报文也需要同时满足其全部条件。

下面的配置清单示例(httpproxy-headers-routing.yaml)在dev名称空间中定义了一个名为 httpproxy-headers-routing 的 HTTPProxy 资源,它在规则一中定义了两个过滤条件,满足条件的请求将被路由至 demoappv11 服务上,其他请求的路由目标则是 demoapp 服务。

apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:name: httpproxy-headers-routingnamespace: dev
spec:virtualhost:fqdn: www.ilinux.ioroutes:- conditions:     # 规则一,内部各条件间为与关系,且至多使用一个prefix- header:      # 过滤条件一,未指定prefix则表示适用于所有PATHname: X-Canary   # 指定要检测的头部名称present: true    # 报文头部存在即满足条件,无论其值是什么- header:       # 过滤条件二与条件一为“与”关系name: User-Agent  # 指定要检测的头部名称contains: curl   # 指定的头部的值包含字符串"curl"方满足条件services:- name: demoappv11port: 80- services:       # 规则二,虚拟主机上未被前一路由规则匹配到的请求都将由该后端处理- name: demoappport: 80

将httpproxy/httpproxy-headers-routing资源应用到集群之上即可展开测试。

~$ kubectl apply -f httpproxy-headers-routing.yaml
httpproxy.projectcontour.io/httpproxy-headers-routing created

随后,由Envoy使用NodePort在集群外部向Kubernetes集群任一节点发起测试请求,只有同时满足规则一中的两个条件的请求报文才会被路由到demoappv11后端,例如明确指定了自定义标头X-Canary的curl命令发起的测试请求及结果,如下所示。

~$ curl -H "X-Canary: true" http://www.ilinux.io
iKubernetes demoapp v1.1 !! ……demoappv11-59cddc6bff-9bfkg, ServerIP: 10.244.1.12!

仅满足规则一中的一个条件或者不能满足规则一中的任何条件的请求报文,将被路由到 demoapp 后端,如下面的 3 个测试命令及结果所示。

# 下面的命令仅满足规则一中的条件二
~$ curl http://www.ilinux.io
iKubernetes demoapp v1.0 !! …… demoapp-6c5d545684-v6djh, ServerIP: 10.244.1.7!
# 下面的curl命令模拟自身为chrome浏览器,仅能满足规则一中的条件一
~$ curl -A "chrome" -H "X-Canary: On" http://www.ilinux.io
iKubernetes demoapp v1.0 !!…… demoapp-6c5d545684-v6djh, ServerIP: 10.244.1.7!
# 下面的命令无法满足规则一中的任何条件
~$ wget -q -O - http://www.ilinux.io
iKubernetes demoapp v1.0 !! …… demoapp-6c5d545684-v6djh, ServerIP: 10.244.1.7!
基于标头路由有许多应用场景,例如用户分类路由或浏览器分类路由等,甚至是基于某些特定的标头模拟金丝雀发布等。

2. 流量切分

HTTPProxy 支持在单个路由规则中同时指定多个后端服务,默认情况下,所有流量将以等量切分的方式平均分发到多个后端之上,每个后端内部再按照代理服务器配置的调度算法进行二级负载均衡。同时,HTTPProxy 也允许用户为每个后端服务使用 weight 字段指定一个特定流量百分比,从而将流量以指定的比例在不同的后端服务间进行分发,如图 13-11 所示。

图13-11 流量分割示意图

基于流量分割的流量切分是完成灰度发布的常用手段。上线应用的新版本时,无论是出于产品稳定性还是用户接受程度等因素的考虑,直接以新代旧都充满风险。因此,灰度发布是应用程序在生产环境安全上线的一种重要手段,而对于Envoy来说,灰度发布仅是其流量治理功能的一种典型应用,结合分割策略便能实现常见的金丝雀部署、蓝绿部署和A/B测试等应用场景。

事实上,基于标头的流量分割算是“基于请求内容”灰度部署的一种实现,而流量分割则是“基于流量比例”进行灰度部署的方式。与 Kubernetes 的 Deployment 控制器的滚动更新机制相比,HTTPProxy 允许用户按需指定要切分的流量比例,而非按照Pod数量来固定分割的方式。

下面的配置清单示例(httpproxy-traffic-splitting.yaml)中定义的httpproxy资源将发往虚拟主机www.ilinux.io的以“/”为路径前缀的流量,按指定的比例切分到了demoapp和demoappv11两个后端服务之上。

apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:name: httpproxy-traffic-splittingnamespace: dev
spec:virtualhost:fqdn: www.ilinux.ioroutes:- conditions:- prefix: /services:- name: demoappport: 80weight: 90   # 该后端的流量比例- name: demoappv11port: 80weight: 10  # 该后端的流量比例

将上述配置清单中的资源创建到集群之上便可检验其工作状态,为了避免策略交叉生效,我们先卸载此前创建的其他 HTTPProxy 资源后再进行测试。

~$ kubectl delete httpproxy --all -n dev
httpproxy.projectcontour.io "httpproxy-headers-routing" deleted
~$ kubectl apply -f httpproxy-traffic-splitting.yaml
httpproxy.projectcontour.io/httpproxy-traffic-splitting created

部署完成后,我们即可向该虚拟主机发起多次请求以进行测试,一般来说,样本空间越大,真实的流量切分比例越接近于规划。例如,下面的命令向该服务发起了100次请求,并统计分别由 demoapp v1.0 和 demoapp v1.1 响应的报文数比例。

~$ v10=0; v11=0; for i in {1..100}; do \if curl -s http://www.ilinux.io/ | grep "v1.0" > /dev/null; \then let v10++; else let v11++;fi; done;~$ echo "Version 1.0: $v10  Version 1.1: $v11"Version 1.0: 89  Version 1.1: 11

事实上,我们可以把这10%的流量比例当作“金丝雀”,测试足够长一段时间,确认无误后可通过逐步修改 httpproxy-traffic-splitting 资源中各后端服务上流量比例的方式完成流量迁移,从而实现灰度发布。以不存在“中间状态”的方式在两个后端服务间分割流量,要么完全在第一个服务上,要么一次性迁往第二个服务的配置机制即为蓝绿发布。

3. 流量镜像

流量镜像用于百分百地在两个服务间复制流量。在支持蓝绿部署的场景中,流量镜像常用于将当前服务上的真实流量引入到未发布的新版本上进行测试。但流量镜像工作于“只读”模式,因为其响应报文会被全部丢弃。

下面的配置清单示例(httpproxy-traffic-mirror.yaml)将 demoapp 服务上的所有流量都镜像给 demoappv11 一份完整的副本。感兴趣的读者可自行测试。

apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:name: httpproxy-traffic-mirrornamespace: dev
spec:virtualhost:fqdn: www.ilinux.ioroutes:- conditions:- prefix: /services:- name: demoappport: 80- name: demoappv11port: 80mirror: true   # 流量镜像,所有发往demoapp的流量都镜像给当前服务一份

4. 负载均衡策略

HTTPProxy 中的负载均衡策略是路由规则中的定义,每个路由规则都可以为其后端调用的服务按需指定最为合用的负载均衡机制。目前,HTTPProxy 暴露了 Envoy 在集群上支持的部分调度算法,主要有如下几个。

  • RoundRobin:按顺序轮询选择上游端点,此为默认策略。

  • WeightedLeastRequest:加权最少连接,但该算法仅随机选择两个健康的端点,并从中挑选出负载少的端点作为调度目标。

  • Random:从后端健康端点中随机挑选端点。

  • Cookie:粘性会话调度机制,把来自某客户端的所有请求始终调度给同一个后端端点。

  • 下面的配置清单示例(httpproxy-lb-strategy.yaml)定义的路由规则会将发往www.ilinux.io的所有流量均分给demoapp和demoappv11这两个后端服务,各服务内部使用Random调度算法将流量分发至后端端点。

apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:name: httpproxy-lb-strategynamespace: dev
spec:virtualhost:fqdn: www.ilinux.ioroutes:- conditions:- prefix: /services:        # 在两个服务间均分流量- name: demoappport: 80- name: demoappv11port: 80loadBalancerPolicy:   # 使用Random调度算法strategy: Random

我们知道,HTTPProxy路由规则中,每个后端服务都会对应地转换为Envoy上配置的一个集群,于是,指定的负载均衡策略也就成为该路由规则中各服务对应集群上共用的调度策略。

(一)   HTTPProxy 服务韧性

Envoy提供了一系列的局部故障应对机制,包括超时、重试、主动健康状态检测、被动健康状态检测(异常值探测)和断路器等,Contour的HTTPProxy API封装提供了前3种类型的故障应对机制,它们都定义在路由规则之中。可用的字段及简要的功能说明如下所示。

spec:routes <[]Route> timeoutPolicy <TimeoutPolicy>     # 超时策略response <String>     # 等待服务器响应报文的超时时长idle <String>       # 超时后,Envoy维持与客户端之间连接的空闲时长retryPolicy <RetryPolicy>   # 重试策略count <Int64>       # 重试的次数,默认为1perTryTimeout <String>    # 每次重试的超时时长healthCheckPolicy <HTTPHealthCheckPolicy>   # 主动健康状态检测path <String>       # 检测针对的路径(HTTP端点)host <String>       # 检测时请求的虚拟主机intervalSeconds <Int64>   # 时间间隔,即检测频度,默认为5秒timeoutSeconds <Int64>     # 超时时长,默认为2秒unhealthyThresholdCount <Int64>   # 判定为非健康状态的阈值,即连续错误次数healthyThresholdCount <Int64>     # 判定为健康状态的阈值

1 超时和重试

分布式环境中对远程资源和服务的调用可能会由于瞬态故障而失败,例如网络连接速度慢、超时、资源过量使用或暂时不可用等,这些故障多数情况下都能够在短时间内自行纠正,因而基于特定的策略重新发送请求(重试机制)可解决大部分的此类故障,其工作逻辑如图13-12所示。而且,通过透明地重试失败的操作,使应用程序在尝试连接到服务或网络资源时能够处理瞬态故障,可以显著提高应用程序的稳定性。

图13-12 服务请求重试机制

但是,也可能存在由于意外事件导致故障并且可能需要更长时间才能恢复的情形,而故障的严重性级别有所不同,从部分连接中断到服务完全不可用皆有可能。这种情况下,连续重试和长时间的等待都没有太大意义,因而应用程序应迅速(等待一定的时间后自动超时)接受该操作已经失败并相应地处理这种失败。

下面的资源清单示例(httpproxy-retry-timeout.yaml)为部署的 demoapp 服务定义了超时和重试策略,当上游服务器响应以 5xx 状态码时,demoapp 将启动重试机制,最大尝试次数为3次,总体超时时长为2秒。

apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:name: httpproxy-retry-timeoutnamespace: dev
spec:virtualhost:fqdn: www.ilinux.ioroutes:- timeoutPolicy:       # 超时机制response: 2sidle: 5sretryPolicy:      # 重试策略count: 3         # 最大重试次数perTryTimeout: 500ms   # 单次尝试的超时时长services:- name: demoappport: 80

HTTPProxy 仅支持当上游服务器响应以5xx状态码时重试,因此它所能够应对的错误场景有限,而 Envoy 能够支持更多的重试条件,这些条件或许在未来的 Contour 版本中能够得到支持。上面的配置清单示例中的 HTTPProxy 资源为 Envoy 生成的重试策略的配置片段如下所示,它取自 Envoy 内置 Admin 接口输出的配置信息。

cluster: dev/demoapp/80/da39a3ee5e
timeout: 2s
retry_policy:retry_on: 5xxnum_retries: 3per_try_timeout: 0.500s
idle_timeout: 5s

需要注意的是,重试策略需要匹配应用程序的业务需求和故障性质,对于某些非关键操作,最好是快速失败而不是重试几次,以免影响应用程序的吞吐量。另外,还需要考虑操作幂等与否,对于幂等类操作,重试本质上是安全的;而对于非幂等类操作,重试可能导致该操作被执行多次,并产生意外的副作用。

2. 健康状态检测

HTTPProxy 资源支持的健康状态检测功能,是由 Envoy 在集群级别对后端端点主动检测实现的,Envoy 通过发往每个上游端点的 HTTP 请求的响应状态码来判定端点健康与否。这种健康状态检测机制与 Kubernetes 上对容器实施的 StartupProbe、LivenessProbe 和 ReadinessProbe 机制有所不同,它并不经由 Pod 上定义的检测点,而是使用自定义的检测端点。我们知道,Service 会对其关联的后端 Pod 经由 Endpoint 进行健康状态检测,而 Contour 的健康状态检测是在这各种检测之外,对 Service 关联的 Pod 对象又施加的一层自定义检测机制。

下面的资源清单(httpproxy-health-checks.yaml)示例在 HTTPProxy 上定义的健康状态检测将转换为 Envoy 的配置,并由 Envoy 实施检测。但相关的检测策略定义在路由规则上,而非服务级别,这意味着同一路由规则下的所有服务对应的Envoy 集群将共享这种检测机制。

apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:name: httpproxy-health-checknamespace: dev
spec:virtualhost:fqdn: www.ilinux.ioroutes:- conditions:- prefix: /healthCheckPolicy:path: /intervalSeconds: 5timeoutSeconds: 2unhealthyThresholdCount: 3healthyThresholdCount: 5services:- name: demoappport: 80- name: demoappv11port: 80

将上述配置清单的资源创建到集群上之后,它会为 Envoy 在 demoapp 和 demoappv11 两个服务对应的集群上各生成一组类似如下内容的健康状态检测策略配置段。

health_checks:
- timeout: 2sinterval: 5sunhealthy_threshold: 3healthy_threshold: 5http_health_check:host: contour-envoy-healthcheck
path: "/"

对于 Envoy 来说,集群中的各端点的健康状态检测机制必须显式定义,否则发现的所有上游主机在发现那一刻起即被视为可用。一般正确实施了存活状态和就绪状态检测的 Pod,额外定义健康状态检测机制并非特别必要,而且会增加后端端点的服务压力。但对于未能在 Pod 的主容器级别实施存活状态和就绪状态检测的场景来说,在 Ingress 控制器代理上实施主动健康状态检测就变得不可或缺。

赠书活动

为感谢广大读者对本公众号的支持,现举办《Kubernetes进阶实战(第2版)》赠书活动,参与方法如下:

1. 在本文末留言,发表对本文内容或 Kuberentes 等云原生技术的看法;

2. 转发本文并邀请朋友对您的文后留言点赞,留言点赞数最多的读者胜出,将获得《Kubernetes进阶实战(第2版)》新书一本。注意,是在本文末的留言里面点赞,不是朋友圈点赞。

3. 本次活动将送出赠书3本。

截止时间:2021年6月12日23点59分,获奖名单将于留言和公众号中公布,获奖者可在后台告知联系方式。

或者点击下面链接,直接优惠价格购买:


要想了解云原生、机器学习和区块链等技术原理,请立即长按以下二维码,关注本公众号亨利笔记 ( henglibiji ),以免错过更新。

一文搞懂HTTPProxy丨含基础、高级路由、服务韧性相关推荐

  1. 音视频面试必备:一文搞懂视频相关的基础概念

    1.引言 随着移动互联网的普及,实时音视频技术已经在越来越多的场景下发挥重要作用,已经不再局限于IM中的实时视频聊天.实时视频会议这种功能,在远程医疗.远程教育.智能家居等等场景也司空见惯. 虽然实时 ...

  2. 一文搞懂AWS EC2, IGW, RT, NAT, SG 基础篇下

    B站实操视频更新 跟着拉面学习AWS--EC2, IGW, RT, NAT, SG 简介 长文多图预警,看结论可以直接拖到"总结"部分 本文承接上一篇文章介绍以下 AWS 基础概念 ...

  3. 一文搞懂RNN(循环神经网络)

    基础篇|一文搞懂RNN(循环神经网络) https://mp.weixin.qq.com/s/va1gmavl2ZESgnM7biORQg 神经网络基础 神经网络可以当做是能够拟合任意函数的黑盒子,只 ...

  4. 一文搞懂 Python 的 import 机制

    一.前言 希望能够让读者一文搞懂 Python 的 import 机制 1.什么是 import 机制? 通常来讲,在一段 Python 代码中去执行引用另一个模块中的代码,就需要使用 Python ...

  5. 一文搞懂HMM(隐马尔可夫模型)-Viterbi algorithm

    ***一文搞懂HMM(隐马尔可夫模型)*** 简单来说,熵是表示物质系统状态的一种度量,用它老表征系统的无序程度.熵越大,系统越无序,意味着系统结构和运动的不确定和无规则:反之,,熵越小,系统越有序, ...

  6. 一文搞懂如何使用Node.js进行TCP网络通信

    摘要: 网络是通信互联的基础,Node.js提供了net.http.dgram等模块,分别用来实现TCP.HTTP.UDP的通信,本文主要对使用Node.js的TCP通信部份进行实践记录. 本文分享自 ...

  7. 一文搞懂CAN FD总线协议帧格式

    目录 1.为什么会出现CAN FD? 2.什么是CAN FD? 3.CAN FD和CAN总线协议帧异同 4.解析CAN FD帧结构 4.1.帧起始 4.2.仲裁段 4.3.控制段 4.4.数据段 4. ...

  8. 一文搞懂指标采集利器 Telegraf

    作者| 姜闻名 来源|尔达 Erda 公众号 ​ 导读:为了让大家更好的了解 MSP 中 APM 系统的设计实现,我们决定编写一个<详聊微服务观测>系列文章,深入 APM 系统的产品.架构 ...

  9. 一文搞懂k近邻(k-NN)算法(一)

    原文链接 一文搞懂k近邻(k-NN)算法(一) 前几天和德川一起在学习会上讲解了k-NN算法,这里进行总结一下,力争用最 通俗的语言讲解以便更多同学的理解. 本文目录如下: 1.k近邻算法的基本概念, ...

  10. 一文搞懂指针,指针的指针,悬浮指针,野指针

    一文搞懂指针,指针的指针,悬浮指针,野指针 学习C语言过程中,指针的概念往往是重难点,伴随着时隐时显的*,令人头晕.实际上指针并非如此复杂,掌握最基础概念,有利于我们更深刻的理解指针. [百科概念] ...

最新文章

  1. 面试必问!Tomcat 优化篇!
  2. aspx ttf文件加载不出来_加载页面信息,刷不出来心态都崩了
  3. [导入]博客搬家了,呵呵
  4. SAP UI5 应用开发教程之二十四 - 如何使用 OData 数据模型
  5. php 弹出变量,php取变量出现Notice: Undefined variable 的解决方法
  6. 关于大型网站技术演进的思考(六)--存储的瓶颈(6)
  7. Android 生态消息推送平台介绍
  8. Java 内存模型(Java Memory Model)
  9. CSDN:如何获得C币
  10. linux内核各版本的下载路径
  11. 数据库三大范式、BCNF范式、反范式
  12. IDEA主题设置更换
  13. 三星s20 android 10.0,三星S20猎户CPU系列安卓10.0 TWRP Recovery V3.4.0.10
  14. 关于linux的filp->private_data解释
  15. MyCP.java蓝墨云班课
  16. OR1200处理器的计时器模块TT介绍
  17. 【重磅】2022年通信行业白皮书汇总下载
  18. 2.OrientDB连接操作
  19. 蓝魔法师——树形DP
  20. AoA-ToF(信号到达角-飞行时间)联合估计详解

热门文章

  1. 广域网宽带接入技术四EPON技术
  2. 这些免费、可商用的图片素材网站,绝对不能错过
  3. oracle数据库的关于建表的sql语句练习
  4. 怎么彻底卸载cad2017_电脑中cad卸载不干净重装失败的处理方法
  5. 阿里云服务器设置安全组最新图文教程 新手必看!
  6. 企业网络冗余技术(EthernetChannel、HSRP、VRRP)
  7. 移动光猫超级管理员密码获取
  8. 【10】Docker的安装 --Mac
  9. 微信公众平台 微信网页授权
  10. 用聚宽数据排一排商誉雷(附结果)