如何使用消息队列,Spring Boot和Kubernetes扩展微服务

by Daniele Polencic

由Daniele Polencic

如何使用消息队列,Spring Boot和Kubernetes扩展微服务 (How to scale Microservices with Message Queues, Spring Boot, and Kubernetes)

When you design and build applications at scale, you deal with two significant challenges: scalability and robustness.

在大规模设计和构建应用程序时,您将面临两个重大挑战: 可伸缩性和鲁棒性

You should design your service so that even if it is subject to intermittent heavy loads, it continues to operate reliably.

您应该对服务进行设计,以使其即使承受间歇性重负载也能继续可靠地运行。

Take the Apple Store as an example.

以Apple Store为例。

Every year millions of Apple customers preregister to buy a new iPhone.

每年都有数百万的Apple客户预先注册购买新的iPhone。

That’s millions of people all buying an item at the same time.

数以百万计的人同时购买商品。

If you were to picture the Apple store’s traffic as requests per second over time, this is what the graph could look like:

如果您将苹果商店的流量描述为每秒随时间变化的请求,则该图可能如下所示:

Now imagine you’re tasked with the challenge of building such application.

现在想象一下,您面临构建此类应用程序的挑战。

You’re building a store where users can buy their favourite items.

您正在建立一个商店,用户可以在其中购买他们喜欢的物品。

You build a microservice to render the web pages and serve the static assets. You also build a backend REST API to process the incoming requests.

您构建了一个微服务来渲染网页并提供静态资产。 您还可以构建后端REST API来处理传入的请求。

You want the two components to be separated, because with the same REST API you could serve the website and mobile apps.

您希望将这两个组件分开,因为使用相同的REST API,您可以为网站和移动应用提供服务。

Today turned out to be the big day, and your store goes live.

今天真是重要的一天,您的商店开始营业了。

You decide to scale the application to four instances for the front-end and four instances for the backend, because you predict that the website to be busier than usual.

您决定将应用程序扩展到前端的四个实例和后端的四个实例,因为您预测该网站将比平时更忙。

You start receiving more and more traffic.

您开始收到越来越多的流量。

The front-end services are handling the traffic fine. But you notice that the backend that is connected to the database is struggling to keep up with the number of transactions.

前端服务正在处理流量问题。 但是您会注意到,连接到数据库的后端正努力跟上事务数量。

No worries, you can scale the number of replicas to 8 for the backend.

不用担心,您可以将后端的副本数扩展到8。

You’re receiving even more traffic, and the backend can’t cope with it.

您收到的流量甚至更多,后端无法应对。

Some of the services start dropping connections. Angry customers get in touch with your customer service. And now you’re drowning in traffic.

一些服务开始断开连接。 生气的客户会与您的客户服务联系。 现在,您淹没在交通中。

Your backend can’t cope with it, and it drops plenty of connections.

您的后端无法应付,并且它断开了很多连接。

You just lost a ton of money, and your customers are unhappy.

您刚刚损失了一大笔钱,而您的客户不满意。

Your application is not designed to be robust and highly available:

您的应用程序并非设计为可靠且高度可用:

  • the front-end and the backend are tightly coupled — in fact it can’t process applications without the backend

    前端和后端紧密耦合- 实际上,没有后端就无法处理应用程序

  • the front-end and backend have to scale in concert — if there aren’t enough backends, you could drown in traffic

    前端和后端必须协调一致— 如果没有足够的后端,您可能会淹没在流量中

  • if the backend is unavailable, you can’t process incoming transactions.

    如果后端不可用,则无法处理传入事务。

And lost transactions are lost revenue.

交易丢失就是收入损失。

You could redesign your architecture to decouple the front-end and the backend with a queue.

您可以重新设计架构,以使前端和后端与队列分离。

The front-end posts messages to the queue, while the backend processes the pending messages one at the time.

前端将消息发布到队列中,而后端一次处理一条待处理消息。

The new architecture has some obvious benefits:

新架构具有一些明显的好处:

  • if the backend is unavailable, the queue acts as a buffer

    如果后端不可用,则队列充当缓冲区
  • if the front-end is producing more messages than what the backend can handle, those messages are buffered in the queue

    如果前端产生的消息多于后端无法处理的消息,则这些消息将缓存在队列中
  • you can scale the backend independently of the front-end — i.e. you could have hundreds of front-end services and a single instance of the backend

    您可以独立于前端扩展后端—即,您可以拥有数百个前端服务和一个后端实例

Great, but how do you build such application?

很好,但是您如何构建这样的应用程序?

How do you design a service that can handle hundreds of thousands of requests? And how do you deploy an application that scales dynamically?

您如何设计可以处理数十万个请求的服务? 以及如何部署可动态扩展的应用程序?

Before diving into the details of deployment and scaling, let’s focus on the application.

在深入探讨部署和扩展的细节之前,让我们先关注应用程序。

编写Spring应用程序 (Coding a Spring application)

The service has three components: the front-end, the backend, and a message broker.

该服务具有三个组件:前端,后端和消息代理。

The front-end is a simple Spring Boot web app with the Thymeleaf templating engine.

前端是带有Thymeleaf模板引擎的简单Spring Boot Web应用程序。

The backend is a worker consuming messages from a queue.

后端是工作人员,使用队列中的消息。

And since Spring Boot has excellent integration with JSM, you could use that to send and receive asynchronous messages.

而且由于Spring Boot与JSM具有出色的集成 ,因此您可以使用它来发送和接收异步消息。

You can find a sample project with a front-end and backend application connected to JSM at learnk8s/spring-boot-k8s-hpa.

您可以在learnk8s / spring-boot-k8s-hpa上找到一个示例项目,该示例项目的前端和后端应用程序已连接到JSM。

Please note that the application is written in Java 10 to leverage the improved Docker container integration.

请注意,该应用程序是用Java 10编写的,以利用改进的Docker容器集成

There’s a single code base, and you can configure the project to run either as the front-end or backend.

这里只有一个代码库,您可以将项目配置为作为前端或后端运行。

You should know that the app has:

您应该知道该应用程序具有:

  • a homepage where you can buy items

    您可以在其中购买物品的主页
  • an admin panel where you can inspect the number of messages in the queue

    一个管理面板,您可以在其中检查队列中的邮件数量
  • a /health endpoint to signal when the application is ready to receive traffic

    /health端点,用于在应用程序准备好接收流量时发出信号

  • a /submit endpoint that receives submissions from the form and creates messages in the queue

    /submit端点,它接收来自表单的提交并在队列中创建消息

  • a /metrics endpoint to expose the number of pending messages in the queue (more on this later)

    /metrics端点以显示队列中待处理消息的数量(稍后会详细介绍)

The application can function in two modes:

该应用程序可以在两种模式下运行:

As a frontend, the application renders the web page where people can buy items.

作为前端 ,该应用程序呈现了人们可以在其中购买商品的网页。

As a worker, the application waits for messages in the queue and processes them.

作为工作人员 ,应用程序等待队列中的消息并对其进行处理。

Please note that in the sample project, the processing is simulated by waiting for five seconds with a Thread.sleep(5000).

请注意,在示例项目中,通过使用Thread.sleep(5000)等待五秒钟来模拟处理过程。

You can configure the application in either mode by changing the values in your application.yaml.

您可以通过更改application.yaml中的值以任何一种方式配置应用application.yaml

空运行应用程序 (Dry-run the application)

By default, the application starts as a frontend and worker.

默认情况下,该应用程序作为前端和工作程序启动。

You can run the application and, as long as you have an ActiveMQ instance running locally, you should be able to buy items and have those processed by the system.

您可以运行该应用程序,并且只要您在本地运行ActiveMQ实例,就应该能够购买商品并由系统处理这些商品。

If you inspect the logs, you should see the worker processing items.

如果检查日志,则应该看到工作程序处理项目。

It worked! Writing Spring Boot applications is easy.

有效! 编写Spring Boot应用程序很容易。

A more interesting subject is learning how to connect Spring Boot to a message broker.

一个更有趣的主题是学习如何将Spring Boot连接到消息代理。

使用JMS发送和接收消息 (Sending and receiving messages with JMS)

Spring JMS (Java Message Service) is a powerful mechanism to send and receive messages using standard protocols.

Spring JMS(Java消息服务)是使用标准协议发送和接收消息的强大机制。

If you’ve used the JDBC API in the past, you should find the JMS API familiar, since it works similarly.

如果您过去使用过JDBC API,则应该熟悉JMS API,因为它的工作原理类似。

The most popular message broker that you can consume with JMS is ActiveMQ — an open source messaging server.

可以与JMS一起使用的最流行的消息代理是ActiveMQ (一种开源消息传递服务器)。

With those two components, you can publish messages to a queue (ActiveMQ) using a familiar interface (JMS) and use the same interface to receive messages.

使用这两个组件,您可以使用熟悉的接口(JMS)将消息发布到队列(ActiveMQ),并使用相同的接口来接收消息。

And even better, Spring Boot has excellent integration with JMS, so you can get up to speed in no time.

甚至更好的是,Spring Boot与JMS具有出色的集成,因此您可以立即上手。

In fact, the following short class encapsulate the logic used to interact with the queue:

实际上,以下简短类封装了用于与队列进行交互的逻辑:

@Component
public class QueueService implements MessageListener {
private static final Logger LOGGER = LoggerFactory.getLogger(QueueService.class);
@Autowired  private JmsTemplate jmsTemplate;  public void send(String destination, String message) {    LOGGER.info("sending message='{}' to destination='{}'", message, destination);    jmsTemplate.convertAndSend(destination, message);  }
@Override  public void onMessage(Message message) {    if (message instanceof ActiveMQTextMessage) {      ActiveMQTextMessage textMessage = (ActiveMQTextMessage) message;      try {        LOGGER.info("Processing task " + textMessage.getText());        Thread.sleep(5000);        LOGGER.info("Completed task " + textMessage.getText());      } catch (InterruptedException e) {        e.printStackTrace();      } catch (JMSException e) {        e.printStackTrace();      }    } else {      LOGGER.error("Message is not a text message " + message.toString());    }  }}

You can use the send method to publish messages to a named queue.

您可以使用send方法将消息发布到命名队列。

Also, Spring Boot will execute the onMessage method for every incoming message.

另外,Spring Boot将为每个传入消息执行onMessage方法。

The last piece of the puzzle is instructing Spring Boot to use the class.

最后一个难题是指示Spring Boot使用该类。

You can process messages in the background by registering the listener in the Spring Boot application like so:

您可以通过在Spring Boot应用程序中注册侦听器来在后台处理消息,如下所示:

@SpringBootApplication@EnableJmspublic class SpringBootApplication implements JmsListenerConfigurer {  @Autowired  private QueueService queueService;
public static void main(String[] args) {    SpringApplication.run(SpringBootApplication.class, args);  }
@Override  public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) {    SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();    endpoint.setId("myId");    endpoint.setDestination("queueName");    endpoint.setMessageListener(queueService);    registrar.registerEndpoint(endpoint);  }}

Where the id is a unique identifier for the consumer and destination is the name of the queue.

id是使用者的唯一标识符, 目的地是队列的名称。

You can read the source code in full for the Spring queue service from the project on GitHub.

您可以从GitHub上的项目中完整阅读Spring队列服务的源代码

Notice how you were able to code a reliable queue in less than 40 lines of code.

请注意,您如何能够用不到40行代码来编写可靠的队列。

You’ve got to love Spring Boot.

您必须爱上Spring Boot。

您节省的所有时间都可以专注于编码 (All the time you save on deploying you can focus on coding)

You verified the application works, and it’s finally time to deploy it.

您已验证了该应用程序的工作原理,终于可以部署它了。

At this point, you could start your VPS, install Tomcat, and spend some time crafting custom scripts to test, build, package and deploy the application.

此时,您可以启动VPS,安装Tomcat,并花一些时间来制作自定义脚本来测试,构建,打包和部署应用程序。

Or you could write a description of what you wish to have: one message broker and two applications deployed with a load balancer.

或者,您可以编写自己希望拥有的描述:一个消息代理和两个使用负载平衡器部署的应用程序。

Orchestrators such as Kubernetes can read your wishlist and provision the right infrastructure.

诸如Kubernetes之类的编排人员可以阅读您的心愿单并配置正确的基础架构。

Since less time spent on the infrastructure means more time coding, you’ll deploy the application to Kubernetes this time. But before you start, you need a Kubernetes cluster.

由于花在基础架构上的时间更少意味着更多的时间编码,因此您这次将应用程序部署到Kubernetes。 但是在开始之前,您需要一个Kubernetes集群。

You could signup for a Google Cloud Platform or Azure and use the cloud provider Kubernetes offers. Or you could try Kubernetes locally before you move your application to the cloud.

您可以注册Google Cloud Platform或Azure并使用云提供商Kubernetes提供的服务。 或者,您可以在将应用程序移至云之前在本地尝试Kubernetes。

minikube is a local Kubernetes cluster packaged as a virtual machine. It’s great if you’re on Windows, Linux, and Mac as it takes five minutes to create a cluster.

minikube是打包为虚拟机的本地Kubernetes集群。 如果您使用的是Windows,Linux和Mac,那就太好了,因为创建群集需要五分钟。

You should also install kubectl, the client to connect to your cluster.

您还应该安装客户端连接到群集的kubectl

You can find the instructions on how to install minikube and kubectl from the official documentation.

您可以从官方文档中找到有关如何安装minikubekubectl说明

If you’re running on Windows, you should check out our detailed guide on how to install Kubernetes and Docker.

如果您在Windows上运行,则应该查看有关如何安装Kubernetes和Docker的详细指南

You should start a cluster with 8GB of RAM and some extra configuration:

您应该使用8GB RAM和一些额外配置启动集群:

minikube start \  --memory 8096 \  --extra-config=controller-manager.horizontal-pod-autoscaler-upscale-delay=1m \  --extra-config=controller-manager.horizontal-pod-autoscaler-downscale-delay=2m \  --extra-config=controller-manager.horizontal-pod-autoscaler-sync-period=10s

Please note that if you’re using a pre-existing minikube instance, you can resize the VM by destroying it an recreating it. Just adding the --memory 8096 won’t have any effect.

请注意,如果使用的是预先存在的minikube实例,则可以通过销毁VM并重新创建VM来调整VM的大小。 仅添加--memory 8096不会有任何效果。

Verify that the installation was successful. You should see a few resources listed as a table. The cluster is ready, perhaps you should start deploying now?

验证安装是否成功。 您应该看到一些资源以表格形式列出。 群集已准备就绪, 也许您应该立即开始部​​署?

Not yet.

还没。

You have to pack your stuff first.

您必须先打包东西。

有什么比超级罐子更好的? 货柜 (What’s better than an uber-jar? Containers)

Applications deployed to Kubernetes have to be packaged as containers. After all, Kubernetes is a container orchestrator, so it isn’t capable of running your jar natively.

部署到Kubernetes的应用程序必须打包为容器。 毕竟,Kubernetes是一个容器编排器,因此它无法在本地运行您的jar。

Containers are similar to fat jars: they contain all the dependencies necessary to run your application. Even the JVM is part of the container. So they’re technically an even fatter fat-jar.

容器类似于胖子jar:它们包含运行应用程序所需的所有依赖项。 甚至JVM都是容器的一部分。 因此,从技术上讲,它们是更胖的胖子。

A popular technology to package applications as containers is Docker.

Docker是将应用程序打包为容器的一种流行技术。

While being the most popular, Docker is not the only technology capable of running containers. Other popular options include rkt and lxd.

尽管Docker最受欢迎,但它并不是唯一能够运行容器的技术。 其他流行的选项包括rktlxd

If you don’t have Docker installed, you can follow the instructions on the official Docker website.

如果您没有安装Docker,则可以按照Docker官方网站上的说明进行操作

Usually, you build your containers and push them to a registry. It’s similar to publishing jars to Artifactory or Nexus. But in this particular case, you will work locally and skip the registry part. In fact, you will create the container image directly in minikube.

通常,您构建容器并将其推送到注册表。 这类似于将jar发布到Artifactory或Nexus。 但是在这种情况下,您将在本地工作并跳过注册表部分。 实际上,您将直接在minikube创建容器映像。

First, connect your Docker client to minikube by following the instructions printed by this command:

首先,按照此命令打印的说明将Docker客户端连接到minikube

minikube docker-env

Please note that if you switch terminals, you need to reconnect to the Docker daemon inside minikube. You should follow the same instructions every time you use a different terminal.

请注意,如果切换终端,则需要重新连接到minikube内部的Docker守护程序。 每次使用其他终端时,都应遵循相同的说明。

and from the root of the project build the container image with:

从项目的根目录使用以下命令构建容器映像:

docker build -t spring-k8s-hpa .

You can verify that the image was built and is ready to run with:

您可以验证映像是否已构建并且可以通过以下方式运行:

docker images | grep spring

Great!

大!

The cluster is ready, you packaged your application, perhaps you’re ready to deploy now?

集群已经准备好了,您打包了应用程序, 也许现在就可以部署了?

Yes, you can finally ask Kubernetes to deploy the applications.

是的,您最终可以要求Kubernetes部署应用程序。

Don’t miss then next story, experiment or tip. If you’re enjoying this article, stay tuned for more. Get new content straight to your inbox and level up your expertise in Kubernetes. Subscribe now

不要错过下一个故事,实验或技巧。 如果您喜欢本文,请继续关注。 直接将新内容发送到您的收件箱,并提高您在Kubernetes中的专业知识。 现在订阅

将您的应用程序部署到Kubernetes (Deploying your application to Kubernetes)

Your application has three components:

您的应用程序包含三个组件:

  • the Spring Boot application that renders the frontend

    呈现前端的Spring Boot应用程序
  • ActiveMQ as a message broker

    ActiveMQ作为消息代理
  • the Spring Boot backend that processes transactions

    处理事务的Spring Boot后端

You should deploy the three components separately.

您应该分别部署这三个组件。

For each of them you should create:

对于其中每个,您都应该创建:

  • A Deployment object that describes what container is deployed and its configuration

    一个Deployment对象,描述了要部署的容器及其配置

  • A Service object that acts as a load balancer for all the instances of the application created by the Deployment

    一个Service对象,充当Deployment所创建的应用程序的所有实例的负载平衡器

Each instance of your application in a deployment is called a Pod.

部署中应用程序的每个实例称为Pod

部署ActiveMQ (Deploy ActiveMQ)

Let’s start with ActiveMQ.

让我们从ActiveMQ开始。

You should create a activemq-deployment.yaml file with the following content:

您应该创建一个具有以下内容的activemq-deployment.yaml文件:

apiVersion: extensions/v1beta1kind: Deploymentmetadata:  name: queuespec:  replicas: 1  template:    metadata:      labels:        app: queue    spec:      containers:      - name: web        image: webcenter/activemq:5.14.3        imagePullPolicy: IfNotPresent        ports:          - containerPort: 61616        resources:          limits:            memory: 512Mi

The template is verbose but straightforward to read:

该模板很冗长,但易于阅读:

  • you asked for an activemq container from the official registry named webcenter/activemq

    您从名为webcenter / activemq的官方注册表中请求了activemq容器

  • the container exposes the message broker on port 61616

    容器在端口61616上显示消息代理
  • there’re 512MB of memory allocated for the container

    为该容器分配了512MB的内存
  • you asked for a single replica — a single instance of your application

    您要求一个副本–应用程序的单个实例

Create a activemq-service.yaml file with the following content:

创建具有以下内容的activemq-service.yaml文件:

apiVersion: v1kind: Servicemetadata:  name: queuespec:  ports:  - port: 61616     targetPort: 61616  selector:    app: queue

Luckily this template is even shorter!

幸运的是,该模板更短!

The yaml reads:

yaml读取:

  • you created a load balancer that exposes port 61616

    您创建了一个暴露端口61616的负载均衡器
  • the incoming traffic is distributed to all Pods (see deployment above) that has a label of type app: queue

    传入流量将分发给所有标签为app: queue类型的Pod(请参阅上面的部署)

  • the targetPort is the port exposed by the Pods

    targetPorttargetPort公开的端口

You can create the resources with:

您可以使用以下方法创建资源:

kubectl create -f activemq-deployment.yamlkubectl create -f activemq-service.yaml

You can verify that one instance of the database is running with:

您可以验证数据库的一个实例正在运行:

kubectl get pods -l=app=queue

部署前端 (Deploy the front-end)

Create a fe-deployment.yaml file with the following content:

创建具有以下内容的fe-deployment.yaml文件:

apiVersion: extensions/v1beta1kind: Deploymentmetadata:  name: frontendspec:  replicas: 1  template:    metadata:      labels:        app: frontend    spec:      containers:      - name: frontend        image: spring-boot-hpa        imagePullPolicy: IfNotPresent        env:        - name: ACTIVEMQ_BROKER_URL          value: "tcp://queue:61616"        - name: STORE_ENABLED          value: "true"        - name: WORKER_ENABLED          value: "false"        ports:        - containerPort: 8080        livenessProbe:          initialDelaySeconds: 5          periodSeconds: 5          httpGet:            path: /health            port: 8080        resources:          limits:            memory: 512Mi

The Deployment looks a lot like the previous one.

部署看起来很像上一个。

There’re some new fields, though:

不过,还有一些新字段:

  • there’s a section where you can inject environment variables

    有一个部分可以注入环境变量
  • there’s the liveness probe that tells you when the application is ready to accept traffic

    有一个活动性探针可以告诉您应用程序何时准备接受流量

Create a fe-service.yaml file with the following content:

创建具有以下内容的fe-service.yaml文件:

apiVersion: v1kind: Servicemetadata:  name: frontendspec:  ports:  - nodePort: 32000    port: 80    targetPort: 8080  selector:    app: frontend  type: NodePort

You can create the resources with:

您可以使用以下方法创建资源:

kubectl create -f fe-deployment.yamlkubectl create -f fe-service.yaml

You can verify that one instance of the front-end application is running with:

您可以验证前端应用程序的一个实例是否正在运行:

kubectl get pods -l=app=frontend

部署后端 (Deploy the backend)

Create a backend-deployment.yaml file with the following content:

创建具有以下内容的backend-deployment.yaml文件:

apiVersion: extensions/v1beta1kind: Deploymentmetadata:  name: backendspec:  replicas: 1  template:    metadata:      labels:        app: backend      annotations:        prometheus.io/scrape: 'true'    spec:      containers:      - name: backend        image: spring-boot-hpa        imagePullPolicy: IfNotPresent        env:        - name: ACTIVEMQ_BROKER_URL          value: "tcp://queue:61616"        - name: STORE_ENABLED          value: "false"        - name: WORKER_ENABLED          value: "true"        ports:        - containerPort: 8080        livenessProbe:          initialDelaySeconds: 5          periodSeconds: 5          httpGet:            path: /health            port: 8080        resources:          limits:            memory: 512Mi

Create a backend-service.yaml file with the following content:

创建具有以下内容的backend-service.yaml文件:

apiVersion: v1kind: Servicemetadata:  name: backend  spec:    ports:    - nodePort: 31000      port: 80      targetPort: 8080    selector:      app: backend    type: NodePort

You can create the resources with:

您可以使用以下方法创建资源:

kubectl create -f backend-deployment.yamlkubectl create -f backend-service.yaml

You can verify that one instance of the backend is running with:

您可以验证后端的一个实例正在运行:

kubectl get pods -l=app=backend

Deployment completed.

部署完成。

Does it really work, though?

它真的有效吗?

You can visit the application in your browser with the following command:

您可以使用以下命令在浏览器中访问该应用程序:

minikube service backend

and

minikube service frontend

If it works, you should try to buy some items!

如果可行,您应该尝试购买一些物品!

Is the worker processing transactions?

工人正在处理交易吗?

Yes, given enough time, the worker will process all of the pending messages.

是的,给定足够的时间,工作人员将处理所有待处理的消息。

Congratulations!

恭喜你!

You just deployed the application to Kubernetes!

您刚刚将应用程序部署到了Kubernetes!

手动缩放以满足不断增长的需求 (Scaling manually to meet increasing demand)

A single worker may not be able to handle a large number of messages. In fact, it can only handle one message at the time.

单个工作人员可能无法处理大量消息。 实际上,它一次只能处理一条消息。

If you decide to buy thousands of items, it will take hours before the queue is cleared.

如果您决定购买成千上万的物品,则需要几个小时才能清除队列。

At this point you have two options:

此时,您有两个选择:

  • you can manually scale up and down

    您可以手动放大和缩小
  • you can create autoscaling rules to scale up or down automatically

    您可以创建自动缩放规则以自动放大或缩小

Let’s start with the basics first.

让我们先从基础开始。

You can scale the backend to three instances with:

您可以使用以下方法将后端扩展到三个实例:

kubectl scale --replicas=5 deployment/backend

You can verify that Kubernetes created five more instances with:

您可以使用以下命令验证Kubernetes再创建了五个实例:

kubectl get pods

And the application can process five times more messages.

该应用程序可以处理五倍的消息。

Once the workers drained the queue, you can scale down with:

一旦工作人员排空队列,您可以使用以下方法进行缩减:

kubectl scale --replicas=1 deployment/backend

Manually scaling up and down is great — if you know when the most traffic hits your service.

手动放大和缩小非常好-如果您知道什么时候流量最多会影响您的服务。

If you don’t, setting up an autoscaler allows the application to scale automatically without manual intervention.

如果不这样做,则设置自动缩放器可以使应用程序自动缩放,而无需手动干预。

You only need to define a few rules.

您只需要定义一些规则。

公开应用程序指标 (Exposing application metrics)

How does Kubernetes know when to scale your application?

Kubernetes如何知道何时扩展您的应用程序?

Simple, you have to tell it.

很简单,您必须告诉它。

The autoscaler works by monitoring metrics. Only then it can increase or decrease the instances of your application.

自动缩放器通过监视指标来工作。 只有这样,它才能增加或减少应用程序的实例。

So you could expose the length of the queue as a metric and ask the autoscaler to watch that value. The more pending messages in the queue, the more instances of your application Kubernetes will create.

因此,您可以将队列的长度作为指标公开,并要求自动缩放器监视该值。 队列中待处理的消息越多,您的应用程序Kubernetes实例将创建的越多。

So how do you expose those metrics?

那么,您如何公开这些指标?

The application has a /metrics endpoint to expose the number of messages in the queue. If you try to visit that page, you’ll notice the following content:

该应用程序具有一个/metrics端点,以显示队列中的消息数。 如果您尝试访问该页面,则会注意到以下内容:

# HELP messages Number of messages in the queue# TYPE messages gaugemessages 0

The application doesn’t expose the metrics as a JSON format. The format is plain text and is the standard for exposing Prometheus metrics. Don’t worry about memorising the format. Most of the time you will use one of the Prometheus client libraries.

该应用程序不会将指标公开为JSON格式。 格式为纯文本,是公开Prometheus指标的标准 。 不用担心记住格式。 大多数时候,您将使用Prometheus客户端库之一

在Kubernetes中使用应用程序指标 (Consuming application metrics in Kubernetes)

You’re almost ready to autoscale — but you should install the metrics server first. In fact, Kubernetes will not ingest metrics from your application by default. You should enable the Custom Metrics API if you wish to do so.

您几乎可以进行自动缩放了-但您应该首先安装指标服务器。 实际上,默认情况下,Kubernetes不会从您的应用程序中获取指标。 如果需要,您应该启用Custom Metrics API

To install the Custom Metrics API, you also need Prometheus — a time series database. All the files needed to install the Custom Metrics API are conveniently packaged in learnk8s/spring-boot-k8s-hpa.

要安装Custom Metrics API,您还需要Prometheus (时间序列数据库)。 安装Custom Metrics API所需的所有文件都方便地打包在learningk8s / spring-boot-k8s-hpa中

You should download the content of that repository and change the current directory to be in the monitoring folder of that project.

您应该下载该存储库的内容,并将当前目录更改为该项目的monitoring文件夹中。

cd spring-boot-k8s-hpa/monitoring

From there you can create the Custom Metrics API with:

在此处,您可以使用以下方法创建Custom Metrics API:

kubectl create -f ./metrics-serverkubectl create -f ./namespaces.yamlkubectl create -f ./prometheuskubectl create -f ./custom-metrics-api

You should wait until the following command returns a list of custom metrics:

您应该等待以下命令返回自定义指标列表:

kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1" | jq .

Mission accomplished!

任务完成!

You’re ready to consume metrics.

您已经准备好使用指标。

In fact, you should already find a custom metric for the number of messages in the queue:

实际上,您应该已经为队列中的消息数找到了一个自定义指标:

kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/namespaces/default/pods/*/messages" | jq .

Congratulations, you have an application exposing metrics and a metric server consuming them.

恭喜,您有一个应用程序公开了指标,而一个指标服务器正在使用它们。

You can finally enable the autoscaler!

您终于可以启用自动定标器了!

Kubernetes中的自动扩展部署 (Autoscaling deployments in Kubernetes)

Kubernetes has an object called Horizontal Pod Autoscaler that is used to monitor deployments and scale the number of Pods up and down.

Kubernetes有一个称为Horizo​​ntal Pod Autoscaler的对象,该对象用于监视部署并上下缩放Pod的数量。

You will need one of those to scale your instances automatically.

您将需要其中之一来自动扩展实例。

You should create a hpa.yaml file with the following content:

您应该使用以下内容创建一个hpa.yaml文件:

apiVersion: autoscaling/v2beta1kind: HorizontalPodAutoscalermetadata:  name: spring-boot-hpaspec:  scaleTargetRef:    apiVersion: extensions/v1beta1    kind: Deployment    name: backend   minReplicas: 1  maxReplicas: 10  metrics:  - type: Pods    pods:      metricName: messages      targetAverageValue: 10

The file is cryptic, so let me translate it for you:

该文件是秘密文件,所以让我为您翻译:

  • Kubernetes watches the deployment specified in scaleTargetRef. In this case, it’s the worker.

    Kubernetes手表中指定的部署scaleTargetRef 。 在这种情况下,是工人。

  • You’re using the messages metric to scale your Pods. Kubernetes will trigger the autoscaling when there’re more than ten messages in the queue.

    您正在使用messages指标来缩放Pod 。 当队列中有十多个消息时,Kubernetes将触发自动缩放。

  • As a minimum, the deployment should have two Pods. Ten Pods is the upper limit.

    部署至少应具有两个Pod 。 上限为十豆荚

You can create the resource with:

您可以使用以下方法创建资源:

kubectl create -f hpa.yaml

After you submitted the autoscaler, you should notice that the number of replicas for the backend is two. It makes sense since you asked the autoscaler always to have at least two replicas running.

提交自动定标器后,您应该注意后端的副本数量为两个。 这很有意义,因为您要求自动定标器始终至少运行两个副本。

You can inspect the conditions that triggered the autoscaler and the events generated as a consequence with:

您可以使用以下方法检查触发自动定标器的条件以及由此产生的事件:

kubectl describe hpa

The autoscaler suggests it was able to scale the Pods to 2 and it’s ready to monitor the deployment.

自动缩放器表明它能够将Pods缩放到2,并准备监视部署。

Exciting stuff, but does it work?

令人兴奋的东西,但是行得通吗?

负载测试 (Load testing)

There’s only one way to know if it works: creating loads of messages in the queue.

只有一种方法可以知道它是否有效:在队列中创建大量消息。

Head over to the front-end application and start adding a lot of messages. As you add messages, monitor the status of the Horizontal Pod Autoscaler with:

转至前端应用程序并开始添加很多消息。 添加消息时,请使用以下方法监视“水平荚自动缩放器”的状态:

kubectl describe hpa

The number of Pods goes up from 2 to 4, then 8 and finally 10.

豆荚的数量从2增至4,然后是8,最后是10。

The application scales with the number of messages! Hurrah!

该应用程序随消息数量扩展! 欢呼!

You just deployed a fully scalable application that scales based on the number of pending messages on a queue.

您刚刚部署了一个完全可伸缩的应用程序,该应用程序根据队列中待处理消息的数量进行扩展。

On a side note, the algorithm for scaling is the following:

附带说明一下,缩放算法如下:

MAX(CURRENT_REPLICAS_LENGTH * 2, 4)

The documentation doesn’t help a lot when it comes to explaining the algorithm. You can find the details in the code.

关于解释算法,文档没有太大帮助。 您可以在代码中找到详细信息

Also, every scale-up is re-evaluated every minute, whereas any scale down every two minutes.

而且,每一次放大都会每分钟进行重新评估,而每两分钟缩小一次。

All of the above are settings that can be tuned.

以上所有都是可以调整的设置。

You’re not done yet, though.

不过,您还没有完成。

有什么比自动缩放实例更好? 自动扩展群集。 (What’s better than autoscaling instances? Autoscaling clusters.)

Scaling Pods across nodes works fabulously. But what if you don’t have enough capacity in the cluster to scale your Pods?

跨节点扩展Pod的效果非常好。 但是,如果群集中没有足够的容量来扩展Pod怎么办?

If you reach peak capacity, Kubernetes will leave the Pods in a pending state and wait for more resources to be available.

如果您达到峰值容量,Kubernetes将使Pod处于挂起状态并等待更多资源可用。

It would be great if you could use an autoscaler similar to the Horizontal Pod Autoscaler, but for Nodes.

如果您可以使用类似于Horizo​​ntal Pod Autoscaler的自动缩放器,但适用于Nodes,那就太好了。

Good news!

好消息!

You can have a cluster autoscaler that adds more nodes to your Kubernetes cluster as you need more resources.

您可以拥有一个集群自动缩放器,该集群可以在需要更多资源时向Kubernetes集群添加更多节点。

The cluster autoscaler comes in different shapes and sizes. And it’s also cloud provider specific.

群集自动缩放器具有不同的形状和大小。 而且它也是特定于云提供商的。

Please note that you won’t be able to test the autoscaler with minikube, since it is single node by definition.

请注意,您将无法使用minikube测试自动缩放minikube ,因为根据定义它是单节点。

You can find more information about the cluster autoscaler and the cloud provider implementation on Github.

您可以在Github上找到有关集群自动缩放器云提供商实现的 更多信息

回顾 (Recap)

Designing applications at scale requires careful planning and testing.

大规模设计应用程序需要仔细的计划和测试。

Queue-based architecture is an excellent design pattern to decouple your microservices and ensure they can be scaled and deployed independently.

基于队列的体系结构是一种出色的设计模式,可以使您的微服务脱钩,并确保它们可以独立扩展和部署。

And while you can roll out your deployment scripts, it’s easier to leverage a container orchestrator such as Kubernetes to deploy and scale your applications automatically.

尽管可以部署部署脚本,但利用容器协调器(例如Kubernetes)更容易自动部署和扩展应用程序。

那是所有人! (That’s all folks!)

Thanks to Nathan Cashmore, and Andy Griffiths for their feedback!

感谢Nathan CashmoreAndy Griffiths的反馈!

If you enjoyed this article, you might find interesting reading:

如果您喜欢这篇文章,可能会发现有趣的阅读内容:

成为在Kubernetes中部署和扩展应用程序的专家 (Become an expert at deploying and scaling applications in Kubernetes)

Learning how to deploy and scale applications with the Horizontal Pod Autoscaler is only the beginning!

学习如何使用Horizo​​ntal Pod Autoscaler部署和扩展应用程序仅仅是个开始!

Get a head start with our hands-on courses and learn how to master Kubernetes.

首先体验我们的动手课程,并学习如何掌握Kubernetes。

Learn how to:

了解如何:

  • Handle the busiest traffic websites without breaking a sweat

    轻松处理最繁忙的交通网站
  • Scale your jobs to thousands of servers and reduce the waiting time from days to minutes

    将您的工作扩展到数千台服务器,并将等待时间从几天减少到几分钟
  • Enjoy peace of mind knowing that your apps are highly available with a multi-cloud setup

    知道您的应用程序在多云设置下高度可用,让您高枕无忧
  • Save ton of cash on your cloud bill by using only the resources your need

    仅使用您需要的资源即可在云账单上节省大量现金
  • Supercharge your delivery pipeline and deploy application around the clock

    增强您的交付管道并全天候部署应用程序

Become an expert in Kubernetes

成为Kubernetes的专家

Originally published at learnk8s.io on July 11, 2018.

最初于2018年7月11日发布在learningk8s.io

翻译自: https://www.freecodecamp.org/news/how-to-scale-microservices-with-message-queues-spring-boot-and-kubernetes-f691b7ba3acf/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值