1. Introduction
1.导言
In this tutorial, we’ll explore how to build event-driven microservices using the Orkes Conductor and Spring. We’ll use Conductor to orchestrate microservices using HTTP endpoints and service workers.
在本教程中,我们将探讨如何使用 Orkes Conductor 和 Spring 构建事件驱动的微服务。我们将使用 Conductor 来使用 HTTP 端点和服务工作者协调微服务。
2. Event-Driven Microservices
2.事件驱动型微服务
Microservices offer a great way to create a modular architecture that can be scaled and managed independently. Developers typically design microservices as single-responsibility services that perform one thing exceptionally well. However, an application flow typically requires coordination across multiple microservices to achieve the business goals.
微服务是创建可独立扩展和管理的模块化架构的绝佳方法。开发人员通常将微服务设计为单一责任服务,这些服务能够出色地完成一件事情。但是,应用程序流通常需要多个微服务之间的协调才能实现业务目标。
Event-driven architecture robustly facilitates communication among microservices over eventing systems, ensuring scalability and durability of the flows. For these reasons, event-driven microservices have recently gained popularity and are especially useful when implementing asynchronous flows.
事件驱动架构可通过事件系统有力地促进微服务之间的通信,确保流量的可扩展性和耐用性。基于这些原因,事件驱动型微服务最近越来越受欢迎,在实现异步流时尤其有用。
2.1. Shortcomings of Event-Driven Systems
2.1.事件驱动系统的缺点
While great at decoupling service interaction, with event-driven systems come several challenges:
虽然事件驱动系统在解耦服务交互方面表现出色,但也带来了一些挑战:
- Difficult to visualize the execution flow – All the communication among microservices happens over the event bus, so it’s difficult to visualize and reason about the business flows. This makes it harder to identify, debug, and recover from failures. Often, distributed traces and centralized logging are used to solve the problem.
- No single authority for the application state – Typically, each service maintains its local database, which acts as a system of record for that service. For example, a credit card service could have a database with a list of credit card payments and relevant information. However, across multiple service calls, the overall state of the application is distributed, making it difficult to visualize application flow, handle compensating transactions in case of failures, and query the application’s state at a given time.
- Easy to build, difficult to scale – Frameworks like Spring simplify the building of event-driven applications that can connect to various pub/sub systems. However, developers often invest a significant amount of time addressing challenges such as operationalizing the systems, scaling to handle large workloads, or building applications with very complex connectivity rules.
3. Event-Driven Architecture With Conductor
3.使用指挥器的事件驱动架构
Netflix originally built Conductor as a platform for orchestrating microservices. Developers at Netflix designed and built Conductor to create event-driven microservices and to address some of the shortcomings listed above.
Netflix最初是将 Conductor 作为协调微服务的平台来构建的。Netflix 的开发人员设计并构建了 Conductor,以创建 事件驱动的微服务,并解决上述的一些不足之处。
As an orchestrator, Conductor allows us to define the flow of service executions either in code or in JSON and enables us to wire up services or write service workers using any of the supported language SDK. Conductor, as a fully open-source platform, operates under the Apache 2.0 license.
作为一个协调器,Conductor 允许我们在代码或 JSON 中定义服务执行流程,并允许我们使用任何支持的语言 SDK 连接服务或编写服务工作者。作为一个完全开源的平台,Conductor 采用 Apache 2.0 许可。
Conductor’s polyglot nature allows us to write service workers in any language or have services and workers in different languages, even within a single application flow.
Conductor 的多语言特性允许我们使用任何语言编写服务工作者,或者使用不同语言编写服务和工作者,甚至在一个应用程序流中也是如此。
Conductor lets us create re-usable, single responsibility principle event-driven services that respond to events. Conductor can also be used to wire up services that are exposed over HTTP using persisted queues.
通过 Conductor,我们可以创建可重用的、遵循单一责任原则的事件驱动服务,以响应事件。指挥器还可用于连接使用持久队列通过 HTTP 公开的服务。
4. Event-Driven Microservices With Conductor and Spring
4.使用 Conductor 和 Spring 实现事件驱动的微服务
Now, let’s explore an example Spring Boot application that leverages Conductor to orchestrate across microservices.
现在,让我们探索一个利用 Conductor 跨微服务协调的 Spring Boot 应用程序示例。
4.1. Setting up Orkes Conductor
4.1.设置 Orkes Conductor
Orkes Conductor can be configured in various ways. First, we can set it up locally using Docker, or alternatively, we can utilize the free developer sandbox Playground.
Orkes Conductor 可以通过多种方式进行配置。首先,我们可以使用 Docker进行本地设置,或者使用免费的开发者沙盒 Playground。
There’s also a Slack community available that might be a good place to check out with any queries related to Conductor.
还有一个黑客社区,如果您有任何与指挥相关的问题,这里可能是一个不错的选择。
4.2. Method 1 – Installing and Running Locally Using Docker
4.2.方法 1 – 使用 Docker 在本地安装和运行
First, let’s ensure that Docker is installed on the device.
首先,确保设备上已安装 Docker。
Then, we employ the following Docker command to initiate the server on port 9090 and the UI on port 1234:
然后,我们使用以下 Docker 命令启动端口为 9090 的服务器和端口为 1234 的用户界面:
docker run --init -p 9090:8080 -p 1234:5000 --mount source=redis,target=/redis \
--mount source=postgres,target=/pgdata orkesio/orkes-conductor-community-standalone:latest
Let’s create a simple Spring Boot application that does two things:
让我们创建一个简单的 Spring Boot 应用程序来做两件事:
- Create a Microservice worker using Conductor.
- Orchestrate between these two services:
- An HTTP endpoint https://orkes-api-tester.orkesconductor.com/api
- The service worker we created in the first step.
Here’s how we can create a simple service worker using a task worker in Conductor that doesn’t need to be exposed over an HTTP endpoint:
以下是我们如何使用 Conductor 中的任务工作者创建一个简单的服务工作者,而无需通过 HTTP 端点进行公开:
@WorkerTask(value = "fraud-check-required")
public FraudCheckResult isFraudCheckRequired(BigDecimal amount) {
return fraudCheckService.checkForFraud(amount);
}
Let’s create a simple workflow that calls a sample HTTP endpoint to get customer details (https://orkes-api-tester.orkesconductor.com/api) and the service worker that runs the fraud check we just implemented above in parallel.
让我们创建一个简单的工作流,调用示例 HTTP 端点来获取客户详细信息(https://orkes-api-tester.orkesconductor.com/api),并调用服务工作者来并行运行我们刚刚在上面实施的欺诈检查。
We execute the workflow using the following command, resulting in a workflow accessible at http://localhost:1234/workflowDef/microservice_orchestration:
我们使用以下命令执行工作流,结果是可以在 http://localhost:1234/workflowDef/microservice_orchestration 访问工作流:
curl -X 'POST' 'http://localhost:9090/api/metadata/workflow' \
-H 'accept: */*' \
-H 'Content-Type: application/json' \
-d '{
"name": "microservice_orchestration",
"description": "microservice_orchestration_example_workflow",
"version": 1,
"tasks": [
{
"name": "fork_task",
"taskReferenceName": "fork_task_ref",
"inputParameters": {},
"type": "FORK_JOIN",
"forkTasks": [
[
{
"name": "fraud-check-required",
"taskReferenceName": "fraud-check-required_ref",
"inputParameters": {
"amount": "${workflow.input.amount}"
},
"type": "SIMPLE"
}
],
[
{
"name": "get_customer_details",
"taskReferenceName": "get_customer_details_ref",
"inputParameters": {
"http_request": {
"uri": "https://orkes-api-tester.orkesconductor.com/api",
"method": "GET",
"accept": "application/json",
"contentType": "application/json"
}
},
"type": "HTTP"
}
]
]
},
{
"name": "join_task",
"taskReferenceName": "join_task_ref",
"type": "JOIN",
"joinOn": [
"get_customer_details_ref",
"fraud-check-required_ref"
]
}
],
"inputParameters": [
"amount"
],
"schemaVersion": 2,
"restartable": true
}'
Let’s run the newly created workflow by making an HTTP POST request:
让我们通过 HTTP POST 请求来运行新创建的工作流:
curl -X 'POST' \
'http://localhost:9090/api/workflow/microservice_orchestration' \
-H 'accept: text/plain' \
-H 'Content-Type: application/json' \
-d '{
"amount": 1000.00
}'
We can verify the completed execution by navigating to “Executions” on the Orkes Conductor UI and checking the workflow execution ID.
我们可以通过浏览 Orkes Conductor UI 上的”Executions“(执行)并检查工作流执行 ID 来验证已完成的执行。
Now, let’s delve into how we can employ this orchestration across services in our application. We’ll expose an endpoint that executes this workflow, effectively creating a new API endpoint that orchestrates the microservices using event-driven design.
现在,让我们深入探讨一下如何在应用程序中跨服务采用这种协调方式。我们将公开一个执行此工作流的端点,从而有效地创建一个新的 API 端点,使用事件驱动设计来协调微服务。
Here’s the sample command:
下面是示例命令:
curl -X 'POST' \
'http://localhost:8081/checkForFraud' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"accountId": "string",
"amount": 12
}'
4.3. Method 2 – Using Orkes Playground
4.3.方法 2 – 使用 Orkes Playground
Let’s create a free account and leverage Playground to test Conductor in real-time by following these steps:
让我们按照以下步骤创建一个免费账户,并利用 Playground 实时测试 Conductor:
- Login to https://play.orkes.io/.
- Create an account to get started with Orkes Conductor.
Now, let’s create a new workflow in Playground or, for ease of testing, we can also use the following workflow:
现在,让我们在 Playground 中创建一个新的工作流程,或者,为了便于测试,我们也可以使用下面的工作流程:
In order to create a connection between Orkes Playground and the worker, we need to create an application in Orkes Conductor. Let’s follow these steps:
为了在 Orkes Playground 和 Worker 之间建立连接,我们需要在 Orkes Conductor 中创建一个应用程序。让我们按照以下步骤操作
- On Orkes Playground, navigate to Access Control > Applications.
- Click ‘Create Application‘ and provide an app name.
- Choose the ‘Application role‘ as ‘Worker‘.
- Click ‘Create access key‘ and copy and keep the key ID & key secret.
Next, let’s grant access to run the workflow by following these steps:
接下来,让我们按照以下步骤授予运行工作流程的权限:
- Under the ‘Permissions‘ section, we click ‘+Add permission‘.
- Under the ‘Workflows‘ tab, we choose ‘microservice_orchestration‘, and under the ‘Tasks‘ tab, let’s choose ‘fraud_check_required‘
- Choose ‘EXECUTE‘ permission and add permissions.
Now, let’s open the worker, and under the application.properties file, provide the generated key ID & secret. We should replace conductor.server.url with https://play.orkes.io/api:
现在,让我们打开 Worker,并在 application.properties 文件中提供生成的密钥 ID 和秘钥。我们应将 conductor.server.url 替换为 https://play.orkes.io/api:
conductor.security.client.key-id=your_key_id
conductor.security.client.secret=your_key_secret
conductor.server.url=https://play.orkes.io/api
Let’s run the application. We can see that the worker polls for the Conductor tasks and picks the task once available.
让我们运行应用程序。我们可以看到, Worker 会轮询 Conductor 任务,并在任务可用时选择任务。
Now, we use the http://localhost:8081/checkForFraud endpoint that we created in our Spring Boot application, and it will use play.orkes.io as the Conductor backend server to run the workflow.
现在,我们使用在 Spring Boot 应用程序中创建的 http://localhost:8081/checkForFraud端点,它将使用 play.orkes.io 作为 Conductor 后端服务器来运行工作流。
5. Conclusion
5.结论
Event-driven microservices open up exciting possibilities for building scalable and responsive software systems. In this article, we’ve gone through the fundamentals of event-driven microservices, highlighting their advantages and challenges.
事件驱动型微服务为构建可扩展、响应迅速的软件系统提供了令人兴奋的可能性。在本文中,我们将介绍事件驱动型微服务的基本原理,并重点介绍其优势和挑战。
We’ve explored how microservices, with their modular and single-responsibility nature, offer an excellent foundation for creating complex applications.
我们已经探讨了微服务的模块化和单一责任性质如何为创建复杂的应用程序奠定了良好的基础。
As always, the source code for the article is available over on GitHub.
与往常一样,本文的源代码可在 GitHub 上获取。