Knative 初体验:Serving Hello World

通过前面两章的学习你已经掌握了很多 Knative 的理论知识,基于这些知识你应该对 Knative 是谁、它来自哪里以及它要做什么有了一定的认识。可是即便如此你可能还是会有一种犹抱琵琶半遮面,看不清真容的感觉,这就好比红娘拿姑娘的 100 张生活照给你看也不如你亲自去见一面。按常理出牌,一般到这个阶段就该 Hello World 出场了。本篇文章就通过一个 Hello World 和 Knative 来一个“约会”,让你一睹 Knative 这位白富美的真容。

安装 Knative

Knative 社区提供的安装步骤见这里,整个流程大概包含如下三个部分:

  • 准备 kubernetes 环境(你可以在阿里云容器服务中快速创建一个 kubernetes 集群 )
  • 安装istio
  • 安装 Knative组件

虽然看起来只有三步,但是每一步其实都需要手动做大量的工作,执行一堆命令。另外社区文档提供的 yaml 文件默认使用了大量的 gcr.io 镜像,目前国内无法拉取 gcr.io 镜像。所以这些 yaml 文件在国内不能直接使用,至少需要手动同步 30 多个镜像才行。

不过别着急,阿里云容器服务的应用目录已经有 Knative 的安装包,现在只需要在阿里云容器服务上面点击几下鼠标就能轻轻松松搭建一个 Knative 集群 O ^ ~ ^ O O ^ ~ ^ O O ^ ~ ^ O

创建 Kubernetes 集群

阿里云容器服务可以通过管理控制台非常方便地创建 Kubernetes 集群。具体过程可以参考创建Kubernetes集群。
容器服务提供了专有集群和托管集群两种类型,如果不知道该怎么选择建议你直接选择托管版的 Kubernetes 集群。托管版无需你自己承担 Kubernetes Master 组件的管理和运维,你只需要提供 Node 节点即可。

安装 Istio

Knative Serving 运行需要基于 Istio,目前阿里云容器服务 Kubernetes 已提供了一键部署的方式来安装配置 Istio。具体过程可以参考部署Istio
登录 容器服务管理控制台,单击左侧导航栏中的集群,进入集群列表页面。选择所需的集群并单击操作列更多 > 部署 Istio。

根据需要进行配置,然后点击部署按钮。稍等十几秒钟之后,Istio 环境就可以部署完毕。

部署 Istio IngressGateway

在容器服务管理控制台的应用目录中找到 ack-istio-ingressgateway 组件。点击参数标签可以看到默认参数提供了 Istio IngressGateway 的配置项,如果需要定制化参数可以在此进行修改。选择好目标 Kubernetes 集群 然后点击创建按钮即可完成 Ingressgateway 的创建。

在容器服务左侧的容器组页面中选择 Kubernetes 集群和 istio-system namespace 确认运行状态,如下所示。

部署 Knative CRD

登录容器服务管理控制台,点击左侧的应用目录,在右侧选中 ack-knative-init,如下:

点击创建按钮部署 Knative 初始化所需的内容,包括部署 CRD 等。

部署 Knative Serving

登录容器服务管理控制台,点击左侧的应用目录,在右侧选中 ack-knative-serving,如下:

点击参数, 可以通过修改参数配置进行定制化,默认参数提供了使用 Istio IngressGateway 的配置项,然后点击创建按钮。

Serving Hello World

Serverless 一个核心思想就是按需分配,那么 Knative 是如何实现按需分配的呢?另外在前面的文章中你已经了解到 Knative Serving 在没有流量的时候是可以把 Pod 缩容到零的。接下来就通过一些例子体验一下 Knative 缩容到零和按需自动扩缩容的能力。

部署 helloworld-go 示例

Knative 官方给出了好几种语言的 Helloworld 示例,这些不同的语言其实只是编译镜像的 Dockerfile 有所不同,做好镜像之后的使用方式没什么差异。本例以 go 的 Hello World 为例进行演示。官方给出的例子都是源码,需要编译长镜像才能使用。为了你验证方便我已经提前编译好了一份镜像 registry.cn-hangzhou.aliyuncs.com/knative-sample/simple-app:07 , 你可以直接使用。

首先编写一个 Knative Service 的 yaml 文件 helloworld-go.yaml , 内容如下:

apiVersion: serving.knative.dev/v1alpha1
kind: Service
metadata:name: helloworld-gonamespace: default
spec:template:metadata:labels:app: helloworld-goannotations:autoscaling.knative.dev/target: "10"spec:containers:- image: registry.cn-hangzhou.aliyuncs.com/knative-sample/simple-app:07env:- name: SIMPLE_MSGvalue: "helloworld-go-07"

注意其中 autoscaling.knative.dev/target: "10" 这个 Annotation 是设置每一个 Pod 的可处理并发请求数 10 ,Knative KPA 自动伸缩的时候会根据当前总请求的并发数和 autoscaling.knative.dev/target 自动调整 Pod 的数量,从而达到自动扩缩的目的。更多的策略信息我会在后续的文章中一一介绍。
现在使用 kubectl 命令把 yaml 提交到 Kubernetes 中:

  • 部署 helloworld-go
└─# kubectl apply -f helloworld-go.yaml
service.serving.knative.dev/helloworld-go created
  • 查看 helloworld-go pod
└─# kubectl get pod
NAME                                              READY   STATUS    RESTARTS   AGE
helloworld-go-lq6ns-deployment-869cbcc75d-qrln7   2/2     Running   0          6s

到此 helloworld-go 已经运行起来了,接下来访问一下 helloworld-go 这个服务吧。

访问 helloworld-go 示例

在访问 helloworld-go 之前我要先来介绍一下在 Knative 模型中流量是怎么进来的。Knative Service 和 Kubernetes 原生的 Deployment 不一样,Knative 不会创建 Loadbalance 的 Service,也不能创建 NodePort 类型的 Service,所以不能通过 SLB 或者 NodePort 访问。只能通过 ClusterIP 访问。而 ClusterIP 是不能直接对外暴露的,所以必须经过 Gateway 才能把用户的流量接入进来。本例就是使用 Istio 的 Gateway 承接 Knative 的南北流量(进和出)。如下图所示是 Knative 模型中流量的转发路径。用户发起的请求首先会打到 Gateway 上面,然后 Istio 通过 VirtualService 再把请求转发到具体的 Revision 上面。当然用户的流量还会经过 Knative 的 queue 容器才能真正转发到业务容器,关于这方面的细节我在后续的文章再进行详细的介绍。

所以想要访问 Knative 的服务首先要获取 Gateway 的 IP 地址,可以通过如下方式获取 Gateway 的 IP:

└─# kubectl get svc istio-ingressgateway --namespace istio-system --output jsonpath="{.status.loadBalancer.ingress[*].ip}"
39.97.31. 219

前面也介绍了 Gateway 是通过 VirtualService 来进行流量转发的,这就要求访问者要知道目标服务的名字才行(域名),所以要先获取 helloworld-go 的域名, 注意下面这条命令中的 ${SVC_NAME} 需要替换成 helloworld-go ,这个名字必须要和 Knative Service 的名字一致,因为每一个 Service 都有一个唯一的名字。

└─# kubectl get route ${SVC_NAME} --output jsonpath="{.status.domain}"
helloworld-go.default.example.com

至此你已经拿到 IP 地址和 Hostname,可以通过 curl 直接发起请求:

└─# curl -H "Host: helloworld-go.default.example.com" "http://39.97.31. 219"
<h1>helloworld-go-07-v3</h1>

为了方便你进行测试,我提供了一个脚本 run-test.sh,你可以使用此脚本测试你自己的 Service , 你自己在测试的时候把 SVC_NAME 换成自己的 Service Name 就行了。

#!/bin/bashSVC_NAME="helloworld-go"
export INGRESSGATEWAY=istio-ingressgateway
export IP_ADDRESS=$(kubectl get svc $INGRESSGATEWAY --namespace istio-system --output jsonpath="{.status.loadBalancer.ingress[*]['ip']}")
echo "IP_ADDRESS: ${IP_ADDRESS}"export GATEWAY_IP=`kubectl get svc $INGRESSGATEWAY --namespace istio-system --output jsonpath="{.status.loadBalancer.ingress[*]['ip']}"`
export DOMAIN_NAME=`kubectl get route ${SVC_NAME} --output jsonpath="{.status.domain}"`kubectl get ksvc ${SVC_NAME} --output=custom-columns=NAME:.metadata.name,DOMAIN:.status.domain
time curl -H "Host: ${DOMAIN_NAME}" http://${IP_ADDRESS} -v

缩容到零

刚刚部署完 Service 的时候 Knative 默认会创建出一个 Pod 提供服务,如果你超过即使秒没有访问 helloworld-go 这个服务那么这个 Pod 就会自动删除,此时就是缩容到零了。现在看一下 Pod 情况, 你可能会发现没有 Pod

└─# kubectl get pod -o wide
No resources found.

现在执行一下 run-test.sh 发起一个请求到 Knative Service

└─# ./run-test.sh
IP_ADDRESS: 39.97.31. 219
NAME            DOMAIN
helloworld-go   helloworld-go.default.example.com
* Rebuilt URL to: http://39.97.31. 219/
*   Trying 39.97.31. 219...
* TCP_NODELAY set
* Connected to 39.97.31. 219 (39.97.31. 219) port 80 (#0)
> GET / HTTP/1.1
> Host: helloworld-go.default.example.com
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 200 OK
< content-length: 28
< content-type: text/html; charset=utf-8
< date: Mon, 03 Jun 2019 03:47:58 GMT
< server: istio-envoy
< x-envoy-upstream-service-time: 2681
<
* Connection #0 to host 39.97.31. 219 left intact
<h1>helloworld-go-07-v3</h1>
real    0m2.775s
user    0m0.007s
sys    0m0.007s

注意 run-test.sh 结果中,这面这一段:

real    0m2.775s
user    0m0.007s
sys    0m0.007s

real 0m2.775s 意思意思是 curl 请求执行一共消耗了 2.775s , 也就是说 Knative 从零到 1 扩容 + 启动容器再到服务响应请求总共消耗了 2.775s (我之前的测试导致在 Node 上面缓存了镜像,所以没有拉镜像的时间)。可以看出来这个速度还是很快的。

再看一下 pod 数量, 你会发现此时 Pod 自动扩容出来了。并且 Pod 数量为零时发起的请求并没有拒绝链接。

└─# kubectl get pod
NAME                                              READY   STATUS    RESTARTS   AGE
helloworld-go-p9w6c-deployment-5dfdb6bccb-gjfxj   2/2     Running   0          31s

按需分配,自动扩缩

helloworld-go 自动扩容测试

接下来再测试一下 Knative 按需扩容的功能。使用社区提供的 hey 进行测试。hey 有 Windows、Linux 和 Mac 的二进制可以在这里下载。
使用这个命令测试之前需要在本机进行 Host 绑定,对于 helloworld-go 来说要把 helloworld-go 的域名绑定到 Istio Gateway 的 IP 上,/etc/hosts 添加如下配置

39.97.31. 219  helloworld-go.default.example.com

如下所示 这条命令的意思是:

  • -z 30s 持续测试 30s
  • -c 50 保持每秒 50 个请求

测试结果如下:

└─# hey -z 30s -c 50 "http://helloworld-go.default.example.com/" && kubectl get podsSummary:Total:    30.0407 secsSlowest:    0.1453 secsFastest:    0.0266 secsAverage:    0.0378 secsRequests/sec:    1323.2700Total data:    1113056 bytesSize/request:    28 bytesResponse time histogram:0.027 [1]    |0.038 [23584]    |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■0.050 [15839]    |■■■■■■■■■■■■■■■■■■■■■■■■■■■0.062 [255]    |0.074 [30]    |0.086 [28]    |0.098 [14]    |0.110 [0]    |0.122 [0]    |0.133 [0]    |0.145 [1]    |Latency distribution:10% in 0.0330 secs25% in 0.0351 secs50% in 0.0371 secs75% in 0.0407 secs90% in 0.0428 secs95% in 0.0442 secs99% in 0.0495 secsDetails (average, fastest, slowest):DNS+dialup:    0.0001 secs, 0.0266 secs, 0.1453 secsDNS-lookup:    0.0000 secs, 0.0000 secs, 0.0036 secsreq write:    0.0000 secs, 0.0000 secs, 0.0009 secsresp wait:    0.0376 secs, 0.0266 secs, 0.1453 secsresp read:    0.0001 secs, 0.0000 secs, 0.0100 secsStatus code distribution:[200]    39752 responsesNAME                                              READY   STATUS    RESTARTS   AGE
helloworld-go-lq42n-deployment-68ddd64944-nkwpn   2/2     Running   0          77s

回想一下刚才 helloworld-go.yaml 文件配置,已经设置了 autoscaling.knative.dev/target: "10"这个 Annotation。这表示每一个 Pod 能够接受并发 10 个请求,而刚才并发请求数设置的是 50 所以理论上应该会创建出来 5 个 Pod?,

上面结果中最后一部分,是 kubectl get pods 的结果,如下所示:


NAME                                              READY   STATUS    RESTARTS   AGE
helloworld-go-lq42n-deployment-68ddd64944-nkwpn   2/2     Running   0          77s

可以看到实际只有一个 Pod,为什么呢?这是因为虽然并发 50 ,但是每一个请求很快就结束了。看一下刚才测试的结果, 截取核心的一部分展示如下。可以看到最慢的一个请求 0.1453 秒就处理完了。而且 99% 的请求 RT 都没超过 0.0495 秒。

... ...Total:    30.0407 secsSlowest:    0.1453 secsFastest:    0.0266 secsAverage:    0.0378 secsRequests/sec:    1323.2700
... ... 
Latency distribution:10% in 0.0330 secs25% in 0.0351 secs50% in 0.0371 secs75% in 0.0407 secs90% in 0.0428 secs95% in 0.0442 secs99% in 0.0495 secs
... ...

所以一秒内是可以完整的处理完 50 个请求的,也就不需要扩容了。

再换一个例子,让每一个请求处理的时间拉长一些看看效果。

autoscale-go 自动扩缩测试 
如果单个请求处理的太快就不太好展示自动扩缩的效果,那么就让单条请求处理的时间稍微长一些。Knative 官方有一个 Autoscaler 的例子 , 这个例子中每一个请求会进行一些计算,把请求时间拉长,这样就能更容易的测试。你可以直接使用 registry.cn-hangzhou.aliyuncs.com/knative-sample/autoscale-go:0.1 这个镜像进行测试。

  • 编写 Knative Service 文件 autoscale-go.yaml 如下:
└─# cat autoscale-go.yaml
apiVersion: serving.knative.dev/v1alpha1
kind: Service
metadata:name: autoscale-gonamespace: default
spec:template:metadata:labels:app: autoscale-goannotations:autoscaling.knative.dev/target: "10"spec:containers:- image: registry.cn-hangzhou.aliyuncs.com/knative-sample/autoscale-go:0.1
  • 部署 autoscale-go
└─# kubectl apply -f autoscale-go.yaml
service.serving.knative.dev/autoscale-go created

run-test.sh 中 SVC_NAME 改成  autoscale-go 然后执行 run-test.sh ,如下:

└─# ./run-test.sh
IP_ADDRESS: 39.97.31. 219
NAME           DOMAIN
autoscale-go   autoscale-go.default.example.com
* Rebuilt URL to: http://39.97.31. 219/
*   Trying 39.97.31. 219...
* TCP_NODELAY set
* Connected to 39.97.31. 219 (39.97.31. 219) port 80 (#0)
> GET / HTTP/1.1
> Host: autoscale-go.default.example.com
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 200 OK
< content-length: 0
< date: Mon, 03 Jun 2019 05:05:38 GMT
< server: istio-envoy
< x-envoy-upstream-service-time: 2912
<
* Connection #0 to host 39.97.31. 219 left intactreal    0m2.999s
user    0m0.007s
sys    0m0.008s

可以看到 autoscale-go 已经可以提供服务了。
使用 hey 命令测试之前需要在本机进行 Host 绑定,对于 autoscale-go 来说要把 autoscale-go 的域名绑定到 Istio Gateway 的 IP 上,/etc/hosts 添加如下配置

39.97.31. 219  autoscale-go.default.example.com
  • 使用 hey 进行测试:
└─# hey -z 30s -c 50 "http://autoscale-go.default.example.com?sleep=100&prime=10000&bloat=5" && kubectl get podsSummary:Total:    30.1443 secsSlowest:    6.0173 secsFastest:    0.1285 secsAverage:    0.1717 secsRequests/sec:    290.4364Total data:    875284 bytesSize/request:    99 bytesResponse time histogram:0.128 [1]    |0.717 [8704]    |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■1.306 [0]    |1.895 [0]    |2.484 [0]    |3.073 [0]    |3.662 [0]    |4.251 [0]    |4.840 [0]    |5.428 [0]    |6.017 [50]    |Latency distribution:10% in 0.1329 secs25% in 0.1356 secs50% in 0.1383 secs75% in 0.1413 secs90% in 0.1435 secs95% in 0.1450 secs99% in 0.1574 secsDetails (average, fastest, slowest):DNS+dialup:    0.0002 secs, 0.1285 secs, 6.0173 secsDNS-lookup:    0.0000 secs, 0.0000 secs, 0.0036 secsreq write:    0.0000 secs, 0.0000 secs, 0.0011 secsresp wait:    0.1713 secs, 0.1283 secs, 5.9780 secsresp read:    0.0001 secs, 0.0000 secs, 0.0066 secsStatus code distribution:[200]    8755 responsesNAME                                             READY   STATUS    RESTARTS   AGE
autoscale-go-zqcm2-deployment-6cf67b4545-2f2ck   2/2     Running   0          28s
autoscale-go-zqcm2-deployment-6cf67b4545-4xc9s   2/2     Running   0          26s
autoscale-go-zqcm2-deployment-6cf67b4545-6wt8r   2/2     Running   0          28s
autoscale-go-zqcm2-deployment-6cf67b4545-hdbnc   2/2     Running   0          30s
autoscale-go-zqcm2-deployment-6cf67b4545-w9pm7   2/2     Running   0          28s

可以看到此时 Knative 自动扩容出来了 5 个 Pod 处理请求。

总结

至此你已经完成了和 Knative Serving 的首次约会,也看到了这位白富美的真容。通过本篇文章你应该掌握
以下几点:

  • 在阿里云容器服务上面快速搭建 Knative 集群的方法
  • 理解 Knative 从零到一的含义,并且能够基于 helloworld-go 例子演示这个过程
  • 理解 Knative 按需扩缩容的含义,并且能够基于 autoscale-go 例子演示这个过程
  • 理解 Knative 按需扩容的原理,按需扩容不单单是用户发起 50 个并发、每一个 Pod 最多能够并发处理 10 个请求就一定需要创建 5 个 Pod 出来。如果请求的处理时间很短,一个 Pod 就能满足的情况下 Knative 是不会做无用的扩容的

Next

通过前面的例子相信你已经对 Knative Serving 有了更深刻的理解。但是你可能也会产生很多疑问:

  • 这里面只是展示了 Serving 的 Hello World,Eventing、Build 能不能也来一些这样的例子?
  • 为什么上面例子的域名都是 xx.example.com, 我能不能换成自己的域名?
  • Knative 流量转发的细节是怎样的?queue 的作用是什么?
  • 在前面的例子中,容器都是监听 8080 端口的,如果容器监听的不是 8080 端口那么需要怎么配置自定义的端口?
  • Knative 默认扩缩容的策略是怎样的?
  • hey 这个压测工具虽然展示了 Knative 自动扩容的过程,但是还不够直观、还有没有更好的工具来验证并发数、服务响应时间和 Knative 自动扩容 Pod 之间的关系?
  • 如果 Service 有更新,如何进行流量灰度?

所有这些疑问我会在后续的一系列文章中都会一一讲解到,敬请期待后续的文章。


原文链接
本文为云栖社区原创内容,未经允许不得转载。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java-if选择结构

if单选择结构 if双选择结构 if多选择结构 嵌套if结构 https://www.bilibili.com/video/BV12J41137hu?p36&spm_id_frompageDriver

数据仓库介绍与实时数仓案例

1.数据仓库简介 数据仓库是一个面向主题的&#xff08;Subject Oriented&#xff09;、集成的&#xff08;Integrate&#xff09;、相对稳定的&#xff08;Non-Volatile&#xff09;、反映历史变化&#xff08;Time Variant&#xff09;的数据集合&#xff0c;用于支持管理决策…

优酷背后的大数据秘密

在本文中优酷数据中台的数据技术专家门德亮分享了优酷从Hadoop迁移到阿里云MaxCompute后对业务及平台的价值。 本文内容根据演讲视频以及PPT整理而成。 大家好&#xff0c;我是门德亮&#xff0c;现在在优酷数据中台做数据相关的事情。很荣幸&#xff0c;我正好见证了优酷从没…

从提取层、处理层、基础结构入手,带你了解Spark和Kafka!

作者 | Jaskaran S. Puri译者 | 火火酱 责编 | 徐威龙封图| CSDN 下载于视觉中国电子商务市场中典型的一天是这样的&#xff1a;每分钟发生1万个事件流&#xff0c;并且要选择合适的工具对其进行处理。本文将帮助你重新创建一个场景&#xff0c;其中有大量的数据流入&#xff0…

Java-switch选择结构

基本类型 public class SwitchDemo01 {public static void main(String[] args) {// case 穿透char grade B;switch (grade) {case A:System.out.println("优秀");break;case B:System.out.println("良好");break;case C:System.out.println("及格&…

高性能服务器架构思路【不仅是思路】

在服务器端程序开发领域&#xff0c;性能问题一直是备受关注的重点。业界有大量的框架、组件、类库都是以性能为卖点而广为人知。然而&#xff0c;服务器端程序在性能问题上应该有何种基本思路&#xff0c;这个却很少被这些项目的文档提及。本文正式希望介绍服务器端解决性能问…

v-if v-show区别(面试题)

v-if、v-show顾名思义就是用来判断视图层展示效果的&#xff0c;在Vue中文社区说明文档的介绍有&#xff1a; 相同点&#xff1a; v-if与v-show都可以动态控制dom元素显示隐藏 不同点&#xff1a; 1.v-if &#xff1a;可以根据表达式的值在DOM中生成或移除一个元素。 v-show:可…

专访世界顶级游戏背后的男人

‍作者 | 华为云和TA的朋友们封图| CSDN 下载于视觉中国如今&#xff0c;对于网易不鸣工作室CEO王希来说&#xff0c;团队的代表作《战意》已经获得阶段性成功。但不为人知的是&#xff0c;从下定决心要做世界顶级游戏&#xff0c;到这款作品萌生想法&#xff0c;再到正式公测&…

Java-While循环

public class WhileDemo01 {public static void main(String[] args) {// 输出 1 ~ 100int i 0;while (i<100) {i;System.out.println(i);}// 计算 1234...100&#xff1f;int j 0;int sum 0;while (j<100){sum sum j;j;}System.out.println(sum); // 5050} }https…

如何将深度学习训练速度提升一百倍?PAISoar 来了

阿里妹导读&#xff1a;得力于数据规模增长、神经网络结构的演进和计算能力的增强&#xff0c;深度学习的图像处理、语音识别等领域取得了飞速发展。随着训练数据规模和模型复杂度的不断增大&#xff0c;如何充分利用分布式集群的计算资源加快训练速度&#xff0c;提升业务支持…

[Err] 1055 - Expression #1 of ORDER BY clause is not in GROUP BY clause 的问题 MySQL

show variables like "sql_mode"; set sql_mode; set sql_modeNO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES;

破解面试难题8个角度带你解读SQL面试技巧!

作者 | Xinran Waibel译者 | 天道酬勤 责编 | 徐威龙封图| CSDN 下载于视觉中国SQL是用于数据分析和数据处理的最重要的编程语言之一&#xff0c;因此SQL问题始终是与数据科学相关工作&#xff08;例如数据分析师、数据科学家和数据工程师&#xff09;面试过程中的一部分。 SQ…

一文读懂架构整洁之道(附知识脉络图)

程序的世界飞速发展&#xff0c;今天所掌握的技能可能明年就过时了&#xff0c;但有一些东西是历久弥新&#xff0c;永远不变的&#xff0c;掌握了这些&#xff0c;在程序的海洋里就不会迷路&#xff0c;架构思想就是这样一种东西。 本文是《架构整洁之道》的读书笔记&#xf…

python获取视频时长方法

1.使用subprocess和re import re import subprocess video r"work/train/video/a8b96f016a28d8f3836f7cbb7734ecde.mp4" import subprocessdef get_length(filename):result subprocess.run(["ffprobe", "-v", "error", "-sho…

阿里敏捷教练全面解析淘宝直播敏捷实践之路

背景介绍 阿里很少提敏捷转型或DevOps&#xff0c;阿里是强业务驱动的&#xff0c;不管用什么办法&#xff0c;一定要达到业务目标。 我来自敏捷教练团队&#xff0c;我们的职责是帮助团队拿结果。这里的团队不限于研发团队&#xff0c;我现在支持的团队包括销售团队和产品运…

int默认值为0,Integer默认值为null

前提概要 Java为每个原始类型提供了封装类&#xff0c;Integer是java为int提供的封装类。 int的默认值为0&#xff0c;而Integer的默认值为null&#xff0c;即Integer可以区分出未赋值和值为0的区别&#xff0c;int则无法表达出未赋值的情况。 代码示例 public class…

GitHub 接连封杀开源项目惹众怒,CEO 亲自道歉!

作者 | 唐小引头图 | CSDN 下载自东方 IC出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;王坚博士曾经做过这样一个非常形象的比喻&#xff0c;他将做 App 比作是在别人的花园里弄盆栽&#xff0c;「种点花草是没有问题的」&#xff0c;不过「别人叫你的产品下架你…

一键托管,阿里云全链路追踪服务正式商用:成本仅自建1/5或更少

随着互联网架构的扩张&#xff0c;分布式系统变得日趋复杂&#xff0c;越来越多的组件开始走向分布式化&#xff0c;如微服务、消息收发、分布式数据库、分布式缓存、分布式对象存储、跨域调用&#xff0c;这些组件共同构成了繁杂的分布式网络。 在一次800多人的开发者调研中&…

基于Docker的Mysql主从复制搭建_mysql5.7.x

文章目录为什么基于Docker搭建&#xff1f;一、拉取镜像创建容器1. 拉取mysql:5.7镜像2. 创建master容器3. 创建slave容器4. 查看正在运行的容器5. 此时可以使用Navicat等工具测试连接mysql二、搭建Master(主)服务器2.1. 进入到Master容器内部2.2. my.cnf编辑2.2. 重启mysql服务…

医疗保健、零售、金融、制造业……一文带你看懂大数据对工业领域的影响!...

作者 | Zubair Hassan译者 | 风车云马 责编 | 徐威龙封图| CSDN 下载于视觉中国随着大数据技术的兴起&#xff0c;工业领域在很大程度上发生了变化。智能手机和其他通讯方式的使用迅速增加&#xff0c;使得每天都能收集大量数据。以下是大数据对工业领域的影响。如今&#xff0…