通过Dapr实现一个简单的基于.net的微服务电商系统(十一)——一步一步教你如何撸Dapr之自动扩/缩容
上一篇我们讲到了dapr提供的bindings,通过绑定可以让我们的程序轻装上阵,在极端情况下几乎不需要集成任何sdk,仅需要通过httpclient+text.json即可完成对外部组件的调用,这样只需要对外暴露一个轻量级的http服务器提供restapi即可作为一个云函数提供对外服务。上一篇我们同时也提到了在serverless框架下的函数还可以按需进行自动扩容缩容的,在极端情况下甚至可以将实例缩容至0,理想情况下serverless在无人访问时不占用系统除磁盘外的任何资源,当有访问时通过自动化扩容快速启动应用实例提供服务,当请求增多/减少时又相应的进行自动化扩容/缩容,当请求完全没有时再次缩容到0。那今天我们就看看我们如何通过dapr+prometheus+keda来实现一套自动化扩容缩容吧。
目录:
一、通过Dapr实现一个简单的基于.net的微服务电商系统
二、通过Dapr实现一个简单的基于.net的微服务电商系统(二)——通讯框架讲解
三、通过Dapr实现一个简单的基于.net的微服务电商系统(三)——一步一步教你如何撸Dapr
四、通过Dapr实现一个简单的基于.net的微服务电商系统(四)——一步一步教你如何撸Dapr之订阅发布
五、通过Dapr实现一个简单的基于.net的微服务电商系统(五)——一步一步教你如何撸Dapr之状态管理
六、通过Dapr实现一个简单的基于.net的微服务电商系统(六)——一步一步教你如何撸Dapr之Actor服务
七、通过Dapr实现一个简单的基于.net的微服务电商系统(七)——一步一步教你如何撸Dapr之服务限流
八、通过Dapr实现一个简单的基于.net的微服务电商系统(八)——一步一步教你如何撸Dapr之链路追踪
九、通过Dapr实现一个简单的基于.net的微服务电商系统(九)——一步一步教你如何撸Dapr之OAuth2授权 && 百度版Oauth2
十、通过Dapr实现一个简单的基于.net的微服务电商系统(十)——一步一步教你如何撸Dapr之绑定
十一、通过Dapr实现一个简单的基于.net的微服务电商系统(十一)——一步一步教你如何撸Dapr之自动扩/缩容
十二、通过Dapr实现一个简单的基于.net的微服务电商系统(十二)——istio+dapr构建多运行时服务网格
十三、通过Dapr实现一个简单的基于.net的微服务电商系统(十三)——istio+dapr构建多运行时服务网格之生产环境部署
十四、通过Dapr实现一个简单的基于.net的微服务电商系统(十四)——开发环境容器调试小技巧
十五、通过Dapr实现一个简单的基于.net的微服务电商系统(十五)——集中式接口文档实现
十六、通过Dapr实现一个简单的基于.net的微服务电商系统(十六)——dapr+sentinel中间件实现服务保护
十七、通过Dapr实现一个简单的基于.net的微服务电商系统(十七)——服务保护之动态配置与热重载
十八、通过Dapr实现一个简单的基于.net的微服务电商系统(十八)——服务保护之多级缓存
十九、通过Dapr实现一个简单的基于.net的微服务电商系统(十九)——分布式事务之Saga模式
二十、通过Dapr实现一个简单的基于.net的微服务电商系统(二十)——Saga框架实现思路分享
附录:(如果你觉得对你有用,请给个star)
一、电商Demo地址
照例得先唠唠这个扩容缩容机制到底是如何实现的熟悉k8sHPA机制的同学请跳过,k8s的HPA(Horizontal Pod Autoscaler),我们直接搬官方文档定义吧:“Pod 水平自动扩缩(Horizontal Pod Autoscaler) 可以基于 CPU 利用率自动扩缩 ReplicationController、Deployment、ReplicaSet 和 StatefulSet 中的 Pod 数量。 除了 CPU 利用率,也可以基于其他应程序提供的自定义度量指标 来执行自动扩缩。 Pod 自动扩缩不适用于无法扩缩的对象,比如 DaemonSet。”,单靠HPA提供的CPU/MEM利用率来做自动扩缩容很难用于真实的生产环境,同时HPA只能作用于1->N,N->1的情况。而serverless需要涵盖实例从0->N,N->0的情况,所以单靠HPA是无法满足我们的诉求的。而这个时候就需要一款基于HPA扩展的k8s组件来为我们提供相应的服务。而Dapr选择微软自家的KEDA(已经开源并捐献给了CNCF基金会)。注意KEDA并不是为了覆盖HPA的功能,而是作为一个轻量化的组件集成在k8s里为hpa提供扩展服务。
除了keda,我们还需要一些指标,因为keda需要某些指标来作为其对pod的扩容和缩容的凭据,这部分指标目前恰好可以用dapr已经集成好的prometheus来提供。之前链路追踪其实就是dapr+zipkin,而指标同样也可以通过dapr+prometheus来完成。关于指标这部分在dapr的官方文档里monitoring有详细描述,使用起来和之前我们介绍的链路追踪无太大差异,所以就不单开文章讲解了,有诉求的同学可以直接访问文档来自行搭建。
好了,接下来我们开始搭建,不过照例还是先上流程图。注意此图仅仅是简易示例,真实的调用链会涉及更多的细节,此处不展开:
首先我们需要将prometheus安装进来,通过Dapr提供的指南,我们可以使用helm进行安装。
kubectl create namespace dapr-monitoring helm repo add prometheus-community https://prometheus-community.github.io/helm-charts helm repo update helm install dapr-prom prometheus-community/prometheus -n dapr-monitoring
tips:由于一个诡异的bug导致在windows平台下的docker环境内无法启动node-exporter,如果你不幸遇到了,可以使用这行代码解决,具体的issuse在这里
kubectl patch ds dapr-prom-prometheus-node-exporter --type "json" -p '[{"op": "remove", "path" : "/spec/template/spec/containers/0/volumeMounts/2/mountPropagation"}]' -n dapr-monitoring
检查你的dapr-monitoring,确保所有pod都能启动,接着我们需要公开prometheus-server用于访问页面。通过kubectl edit svc dapr-prom-prometheus-server -n dapr-monitoring 打开svc将spec.service.type从ClusterIP改为NodePort,如果你需要固定端口,再增加spec.ports.nodePort即可。保存文档后我们再查询kubectl get svc dapr-prom-prometheus-server -n dapr-monitoring 看看端口号是多少,然后访问loalhost:port,如果出现以下页面,则说明prometheus部署成功:
由于dapr会自动将指标写入prometheus,当我们操作一下我们的电商demo之后,我们就可以从prometheus查询到对应指标的情况了,以http请求数的情况为例:
prometheus先放一边,接着我们安装KEDA,依然参考dapr的文档,不过接下来我们和官方文档有一点出入,官方文档演示的是通过component让keda监听kafka,通过流量指标来确定扩容/缩容订阅器的。我们这里的演示是让keda监听prometheus的特定指标dapr_http_server_request_count来实现扩容/缩的。原理都一样,即借助keda来实现。接下来依然是通过helm安装keda。
helm repo add kedacore https://kedacore.github.io/charts helm repo update kubectl create namespace keda helm install keda kedacore/keda --namespace keda
同样安装完毕后,观察我们的keda,确保两个pod都已经正确running之后,我们尝试对我们的网关配置keda的ScaledObject来实现自动扩容/缩容:首先还是编写一个ScaledObject,这是keda安装后会自动在k8s里申明的CRD资源符
apiVersion: keda.sh/v1alpha1 kind: ScaledObject metadata: name: prometheus-scaledobject namespace: dapreshop spec: scaleTargetRef: name: apigateway pollingInterval: 15 #指定keda的采集频次,单位秒 minReplicaCount: 1 #指定默认规格 maxReplicaCount: 10 #最大扩容规格 triggers: - type: prometheus metadata: serverAddress: http://dapr-prom-prometheus-server.dapr-monitoring.svc.cluster.local #prometheus服务的svc用于keda采集指标 metricName: dapr_http_server_request_count #具体的指标名 query: sum(rate(dapr_http_server_request_count{app_id="apigateway"}[2m])) #这是prometheus特有的PromQL,这段query的意思是我们需要采集以2分钟为一个维度对网关的请求平均访问速率,这里不展开,大家可以搜PromQL中文文档了解更多 threshold: '3' #阈值
当我们apply这个yaml之后,可以通过kubectl get so,hpa观察我们的scaleobject和hpa的资源是否创建成功,一切OK后,我们通过postman的runner请求网关,看看hpa是否可以工作吧:
可以看到请求过来后,我们的指标已经被正确的收集到了,接着我们查询一下网关的情况,可以看到已经被正确的扩容了:
当请求归零后,过一段时间再次访问会发现实例被缩容到了默认规格。这就是今天对dapr+keda实现动态扩容/缩容的介绍。当然要做到真正的云函数那样的从0实例快速冷启动还需要一个过程,冷启动在传统云商提供的云函数环境里是通过预热池实现的,而本地化搭建要实现0实例冷启动需要AOT的支持,至少就目前而言.netcore尚未支持AOT编译成本地代码的情况下还很遥远。但是不能说没有实现serverless冷启动做这个就没有意义,当我们在特定场景比如做活动需要动态扩容/缩容时,完全可以通过keda去实现。当请求稀少的夜间我们完全就可以将实例缩容到1份继续运行,或者类似于dapr官方文档示例那样的订阅器平时不需要运行时完全可以缩容到0个实例,等待消息来触发扩容运行消费。