在分布式系统中,我们通过通过服务总线/消息队列传递消息来实现系统之间的松散耦合。有时,当消息的发送量很高时(即每单位时间传入的消息数大于每单位时间处理的消息数),队列最终将容纳无限数量的消息。消息队列最终可能会由于内存不足错误而失败,并且客户端可能永远不会收到其已发送消息的响应!为避免这种情况,我们通常以最多流量来计划N台服务器,但是如果这么多服务器很少接收处理任何消息,则最终需要为这些未使用的服务器付费。
具有成本效益的解决方案将是自动缩放!这个概念并不新鲜。在本文中,我们将基于Kubernetes集群中的CPU使用率来扩展/扩展消息消费者。这样,当1台服务器努力处理所有消息时,我们带来了更多服务器以加快处理速度,以减少单台服务器上的负载并平衡工作量。
案例
将重用我们之前在这里使用过的应用程序。checkout出来以更好地理解。
- 我们的应用程序将在请求到达时将一些任务放入消息队列中。
- 任务将在斐波那契数列中找到第N个位置!我将使用2 ^ N算法使过程非常缓慢。
- 将有一些类别,如低,高,紧急来对任务进行优先级排序。显然,应该首先执行紧急任务!
- 任务执行器是使用消息的消息处理器。默认情况下,我们将有1个消息处理器启动并始终运行。
- 但是有时1个节点可能还不够。
- 根据CPU利用率,我们的自动缩放器会弹出更多Pod。
优点:
这种方法有几个优点。
- 生产者和消费者之间的松散耦合。
- 我们可以根据需求动态扩展或扩展。(在本文中,我们使用CPU利用率。我们也可以根据队列中的消息计数使用)
- 可靠
- 负载均衡。单个服务器不负责处理所有消息。负载分布在多个消息处理器/消费者之间。
Kubernetes资源
- 我们将创建如图所示的资源。
- Redis配置:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: redis-master
name: redis-master
spec:
replicas: 1
selector:
matchLabels:
app: redis-master
template:
metadata:
labels:
app: redis-master
spec:
containers:
- image: redis
name: redis-master
ports:
- containerPort: 6379
---
apiVersion: v1
kind: Service
metadata:
labels:
app: redis-master
name: redis-master
spec:
ports:
- name: redis-port
port: 6379
protocol: TCP
targetPort: 6379
selector:
app: redis-master
type: ClusterIP
- 任务调度器
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: task-scheduler
name: task-scheduler
spec:
replicas: 1
selector:
matchLabels:
app: task-scheduler
template:
metadata:
labels:
app: task-scheduler
spec:
containers:
- image: vinsdocker/task-scheduler
name: task-scheduler
env:
- name: REDIS_HOST
value: redis-master
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
labels:
app: task-scheduler
name: task-scheduler
spec:
ports:
- name: task-scheduler
port: 8080
protocol: TCP
targetPort: 8080
nodePort: 32001
selector:
app: task-scheduler
type: NodePort - 任务执行者
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: task-executor
name: task-executor
spec:
replicas: 1
selector:
matchLabels:
app: task-executor
template:
metadata:
labels:
app: task-executor
spec:
containers:
- image: vinsdocker/task-executor
name: task-executor
env:
- name: REDIS_HOST
value: redis-master
resources:
requests:
cpu: 200m
memory: 512Mi - 水平Pod自动缩放器(HPA):
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: task-executor
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: task-executor
minReplicas: 1
maxReplicas: 3
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50
资源利用率:
- 当没有负载时,集群的CPU /内存利用率或多或少是这样的。
NAME CPU(cores) MEMORY(bytes)
redis-master-65f7f8cf88-8tqxm 3m 2Mi
task-executor-7dd8855487-2gzbf 4m 184Mi
task-scheduler-86d64c5598-kd6sr 3m 192Mi - HPA输出如下所示(kubectl get hpa)。
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
task-executor Deployment/task-executor 3%/50% 1 3 1 5m - 我向任务计划程序发送了数百条消息,并等待2分钟。
- 我可以看到CPU利用率增加,任务执行程序的数量从1增加到3。
// kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
task-executor Deployment/task-executor 205%/50% 1 3 3 7m
// kubectl top pods
NAME CPU(cores) MEMORY(bytes)
redis-master-65f7f8cf88-8tqxm 5m 3Mi
task-executor-7dd8855487-2gzbf 526m 176Mi
task-executor-7dd8855487-5897f 489m 176Mi
task-executor-7dd8855487-t8tbp 512m 179Mi
task-scheduler-86d64c5598-kd6sr 3m 189Mi - 处理完消息后,请等待5分钟,然后kubernetes会扩展这些使用消费者。
成功演示基于CPU利用率的消息使用方自动扩展,以实现负载均衡,松耦合和加速消息处理。