新文章 网摘 文章 随笔 日记

Dapr学习笔记

文章转自:https://zhuanlan.zhihu.com/p/553300443?utm_id=0

 

Dapr(Distributed Application Runtime),为应用提供分布式能力的运行时。

Any Language、Any Framework、Any Where

1、分布式应用需求

  • 服务发现:服务注册、服务治理、弹性伸缩
  • 服务调用:重试、熔断、限流
  • 数据状态:数据读写、读写一致性、幂等、缓存、数据流
  • 发布订阅:服务解耦、异步处理
  • 配置管理:服务参数、中间件参数、账号密码等
 SpingCloudDapr
服务发现 Euraka、ZooKeeper、Consul、Nacos Sidecar、虚拟机:mDNS、k8s:Service
负载均衡 Ribbon、客户端负载均衡 Sidecar负责实现
状态存储 引入数据库中间件SDK自行处理 State组件抽象
并发处理 实现分布式锁,自行处理 Actor组件抽象
发布订阅 引入中间件SDK Pubsub组件抽象
重试 SpingCloud Retry invoker参数,Sidecar负责实现
熔断 SpingCloud Hystrix invoker参数,Sidecar负责实现
配置管理 SpingCloud Config Secret组件
健康检查 SpingBoot-Starter-actuator Sidecar负责实现
链路追踪    

2、Sidecar架构

Dapr 以 Sidecar 架构的方式公开其API,可以是容器、也可以是进程,不需要应用代码包含任何Dapr运行时代码。

POST http://localhost:3500/v1.0/invoke/cart/method/neworder
GET http://localhost:3500/v1.0/state/inventory/items

 

3、服务调用 Service Invoke

Dapr的服务调用

Service A 对 Service B 发起 HTTP/gRPC 的调用

  • Service A先请求本地的sidecar:
    • http://localhost:<dapr-port>/v1.0/invoke/<application-id>/method/<method-name>
  • Service A的Dapr 使用运行在给定托管平台(hosting platform)上的名称解析组件(name resolution component ),基于application-id/method-name来发现 Service B 的位置(对端的sidecar的地址和端口,不是对端服务的地址和端口),所以这里的服务发现都是sidecar的服务发现,可以认为是“代理人”之间的对话;
  • Service A的Dapr 将消息转发至 Service B 的 Dapr 边车(Sidecar);
  • Service B 的 Dapr 边车将请求转发至 Service B 上的服务 (或方法) ,Service B 随后运行其相应的业务逻辑代码;
  • Service B 发送响应给 Service A,响应将先发给 Service B 的边车,Service B 的 Dapr 边车将消息(应用响应结果)转发至 Service A 的 Dapr 边车;
  • Service A 从Service A的Dapr边车接收响应信息;

【备注】Dapr 边车之间的所有调用考虑到性能都优先使用 gRPC,仅服务与 Dapr 边车之间的调用可以是 HTTP 或 gRPC。

3.1、服务调用负载均衡

Dapr的服务调用负载均衡

【注意】服务调用是基于重试来判断后端服务的可用性,设置3次重试次数,即1+3次后会判断某后端服务失败。存在一定的服务不一致性情况。

 

4、Dapr安装 (Linux环境)

4.1、安装dapr cli (安装脚手架)

a. 如果执行的机器可以科学访问,则执行:

wget -q https://raw.githubusercontent.com/dapr/cli/master/install/install.sh -O - | /bin/bash

b. 如果不行,则执行:

找一台可以上外网的服务器,执行完上面的安装程序后执行:
scp /usr/local/bin/dapr root@Dest_IP:/usr/local/bin

4.2、本地初始化:dapr init

dapr init执行结果

执行后检查:

# dapr -v
CLI version: 1.8.1 
Runtime version: 1.8.4

说明CLI版本是1.8.1,但runtime则是最新的1.8.4

执行:docker ps

docker ps 执行结果

4.3、安装kubernetes环境的dapr环境

1、初始化:dapr init -k

dapr init -k 执行结果

相关pod会创建在dapr-system这个name space中:

执行:kubectl get po -n dapr-system查看pod运行情况:

查看dap相关pod的运行状态

同时dapr init会自动创建如下的services:

dapr services列表

检查安装状态:

dapr status -k
dapr status -k 输出结果

 

2、安装数据存储Redis

和本地安装不同,kubernetes上的初始化不会自动安装状态存储。在Kubernetes上的状态存储可以有多种选择,包括Redis、CosmosDB, DynamoDB, Cassandra等,这里选择最通用的Redis作为状态存储:

#helm repo add bitnami https://charts.bitnami.com/bitnami
"bitnami" has been added to your repositories

#helm repo update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "bitnami" chart repository

#helm install redis bitnami/redis
NAME: redis
LAST DEPLOYED: Sun Aug 14 06:05:14 2022
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
CHART NAME: redis
CHART VERSION: 17.0.10
APP VERSION: 7.0.4

** Please be patient while the chart is being deployed **

Redis&reg; can be accessed on the following DNS names from within your cluster:

    redis-master.default.svc.cluster.local for read/write operations (port 6379)
    redis-replicas.default.svc.cluster.local for read-only operations (port 6379)

To get your password run:
    export REDIS_PASSWORD=$(kubectl get secret --namespace default redis -o jsonpath="{.data.redis-password}" | base64 -d)

To connect to your Redis&reg; server:
1. Run a Redis&reg; pod that you can use as a client:
   kubectl run --namespace default redis-client --restart='Never'  --env REDIS_PASSWORD=$REDIS_PASSWORD  --image docker.io/bitnami/redis:7.0.4-debian-11-r11 --command -- sleep infinity

   Use the following command to attach to the pod:
   kubectl exec --tty -i redis-client \
   --namespace default -- bash

2. Connect using the Redis&reg; CLI:
   REDISCLI_AUTH="$REDIS_PASSWORD" redis-cli -h redis-master
   REDISCLI_AUTH="$REDIS_PASSWORD" redis-cli -h redis-replicas

To connect to your database from outside the cluster execute the following commands:

    kubectl port-forward --namespace default svc/redis-master 6379:6379 &
    REDISCLI_AUTH="$REDIS_PASSWORD" redis-cli -h 127.0.0.1 -p 6379

基于helm的这个安装会部署一个1主3从的Redis集群:

# kubectl get po -n default | grep redi
redis-master-0                     1/1     Running   0          109m
redis-replicas-0                   1/1     Running   0          109m
redis-replicas-1                   1/1     Running   0          108m
redis-replicas-2                   1/1     Running   0          107m

4、部署statestore:

考虑到后续有计划部署dapr的实例,所以这里提前下载相关代码。查看github里dapr的quickstart里Hello-kubernetes这个例子。下载最新版本1.6.0的source code

解压代码后,在目录quickstarts-1.6.0/hello-kubernetes/deploy 下查看文件 redis.yaml,执行:

#kubectl apply -f redis.yaml
component.dapr.io/statestore created

检查:

# dapr components -A -k
⚠  In future releases, this command will only query the "default" namespace by default. Please use the --namespace flag for a specific namespace, or the --all-namespaces (-A) flag for all namespaces.
  NAMESPACE  NAME        TYPE         VERSION  SCOPES  CREATED              AGE  
  default    statestore  state.redis  v1               2022-08-14 06:21.42  1h 

 

5、访问Dapr Dashboard

在Dapr安装到Kubernetes上时会自动创建服务dapr-dashboard,可以为此服务设置外部访问,如基于node-port模式,则可以直接访问该dashboard:

dapr dashboard

5、测试本地部署的Dapr的 API

5.1、启动Dapr运行环境:

dapr run --app-id myapp --dapr-http-port 3500

 

5.2、Dapr 任务执行API

a、保存状态:即POST KV:key: name,value: Bruce Waye,对象:/state/statestore

curl -X POST -H "Content-Type: application/json" -d '[{ "key": "name", "value": "dapr test app"}]' http://localhost:3500/v1.0/state/statestore

b、查询状态:Dapr会将状态信息保存在Redis,查询redis即可获得状态数据

docker exec -it dapr_redis redis-cli
keys *                               output --》 "myapp||name" 
hgetall "myapp||name"                output --》1) "data"
                                                2) "\"dapr test app\""
                                                3) "version"
                                                4) "1"

c、删除状态:

curl -v -X DELETE -H "Content-Type: application/json" http://localhost:3500/v1.0/state/statestore/name

 

6、部署Kubernetes上的Dapr示例应用hello-kubernetes

6.1、准备应用镜像

在4.3章节下载的quickstart目录,根据自己部署环境的docker registry情况来生成所需的node容器和python容器,下面是使用我在上的镜像库:

#cd quickstarts-1.6.0/hello-kubernetes/node
#docker build -t jerryjedi/hello-k8s-node:0.1 .

#cd quickstarts-1.6.0/hello-kubernetes/python
#docker build -t jerryjedi/pythonapp:0.1 .

#docker login
#docker push jerryjedi/hello-k8s-node:0.1
#docker push jerryjedi/pythonapp:0.1

6.2、部署示例应用

#cd quickstarts-1.6.0/hello-kubernetes/deploy
1、修改node.yaml和python.yaml中的image位置:
image: dapriosamples/hello-k8s-node:latest --》 image: docker.io/jerryjedi/hello-k8s-node:0.1
image: dapriosamples/hello-k8s-python:latest --》 image: docker.io/jerryjedi/pythonapp:0.1
2、修改node.yaml中的Service定义中的type:
type: LoadBalance   --> type: NodePort    因为我的环境没有为kubernetes准备LoadBalance的配置
#kubectl apply -f node.yaml
#kubectl apply -f python.yaml

6.3、检查部署

应用会部署到default这个name space中,在部署成功后,会有如下的deployment和pod:

类型Node应用Python应用
deployment deployment.apps/nodeapp deployment.apps/pythonapp
Services service/nodeapp
service/nodeapp-dapr
service/pythonapp-dapr

6.4、运行检查

在部署pythonapp后,这个应用会连续往node发送new order:

message = {"data": {"orderId": n}}
response = requests.post(dapr_url, json=message, timeout=5, headers = {"dapr-app-id": "nodeapp"} )

检查方法一:

查看node的日志,可以看到每隔1秒有新的order进来:

#kubectl logs --selector=app=node -c node
Got a new order! Order ID: 27
Successfully persisted state.
Got a new order! Order ID: 28
Successfully persisted state.
。。。。。。

 

检查方法二:

由于前面已经在node.yaml中启用了service的类型为NodePort,则可以在查看启用的外部访问端口:

 #kubectl get services -n default | grep node-app
nodeapp          NodePort    10.233.26.48    <none>        80:30839/TCP 

在kubernetes运行的节点上访问:

#curl http://ip_nodeapp_running_node:30839/order
{"orderId":31}

 

检查方法三:

启动Redis Client:

#export REDIS_PASSWORD=$(kubectl get secret --namespace default redis -o jsonpath="{.data.redis-password}" | base64 --decode)
#kubectl run --namespace default redis-client --rm --tty -i --restart='Never' --env DIS_PASSWORD=$REDIS_PASSWORD --image docker.io/bitnami/redis:6.0.9-debian-10-r38 -- bash

在Redis Client的Console中查看:

#redis-cli -h redis-master -a $REDIS_PASSWORD      --》 上面的REDIS_PASSWORD替换到这里
redis-master:6379> keys *
1) "nodeapp||order"

redis-master:6379> hgetall nodeapp||order
1) "data"
2) "{\"orderId\":31}"
3) "version"
4) "839"

 

发布于 2022-08-13 17:03
分布式系统
Dapr
posted @ 2023-06-20 14:48  岭南春  阅读(94)  评论(0)    收藏  举报