Skip to content

Commit 1d78dbe

Browse files
authored
Create 2023-08-18-microservice-communication-with-laravel-workflow.md
1 parent 7535652 commit 1d78dbe

File tree

1 file changed

+201
-0
lines changed

1 file changed

+201
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
---
2+
slug: microservice-communication-with-laravel-workflow
3+
title: "Microservice Communication with Laravel Workflow"
4+
authors:
5+
name: Richard
6+
title: Core Team
7+
url: https://github.com/rmcdaniel
8+
image_url: https://github.com/rmcdaniel.png
9+
tags: [microservices, laravel-workflow, communication, distributed-systems]
10+
---
11+
12+
![captionless image](https://miro.medium.com/v2/resize:fit:1400/format:webp/1*nCy08NPtCpERqC09SVBFfg.jpeg)
13+
14+
In the evolving landscape of microservices, communication has always been a focal point. Microservices can interact in various ways, be it through HTTP/REST calls, using messaging protocols like RabbitMQ or Kafka, or even employing more recent technologies like gRPC. Yet, regardless of the communication method, the goal remains the same: seamless, efficient, and robust interactions. Today, we’ll explore how Laravel Workflow can fit into this picture and optimize the communication between microservices in a unique way.
15+
16+
## The Challenge
17+
18+
In a microservices architecture, decoupling is the name of the game. You want each service to have a single responsibility, to be maintainable, and to be independently deployable. Yet, in the world of workflows, this becomes challenging. How do you split a workflow from its activity and yet ensure they communicate seamlessly?
19+
20+
## Laravel Workflow to the Rescue!
21+
22+
[Laravel Workflow](https://github.com/laravel-workflow/laravel-workflow) handles the discovery and orchestration for you! With a shared database and queue connection, you can have your workflow in one Laravel app and its activity logic in another.
23+
24+
### Defining Workflows and Activities
25+
26+
#### 1. Create a workflow.
27+
```php
28+
use Workflow\ActivityStub;
29+
use Workflow\Workflow;
30+
31+
class MyWorkflow extends Workflow
32+
{
33+
public function execute($name)
34+
{
35+
$result = yield ActivityStub::make(MyActivity::class, $name);
36+
return $result;
37+
}
38+
}
39+
```
40+
41+
#### 2. Create an activity.
42+
```php
43+
use Workflow\Activity;
44+
45+
class MyActivity extends Activity
46+
{
47+
public function execute($name)
48+
{
49+
return "Hello, {$name}!";
50+
}
51+
}
52+
```
53+
54+
#### 3. Run the workflow.
55+
```php
56+
use Workflow\WorkflowStub;
57+
58+
$workflow = WorkflowStub::make(MyWorkflow::class);
59+
$workflow->start('world');
60+
while ($workflow->running());
61+
$workflow->output();
62+
// Output: 'Hello, world!'
63+
```
64+
65+
The workflow will manage the activity and handle any failures, retries, etc. Think of workflows like job chaining on steroids because you can have conditional logic, loops, return a result that can be used in the next activity, and write everything in typical PHP code that is failure tolerant.
66+
67+
## Balancing Shared and Dedicated Resources
68+
69+
When working with microservices, it’s common for each service to have its dedicated resources, such as databases, caches, and queues. However, to facilitate communication between workflows and activities across services, a shared connection (like a database or queue) becomes essential. This shared connection acts as a bridge for data and task exchanges while ensuring:
70+
71+
1. **Isolation**: Dedicated resources prevent cascading failures.
72+
2. **Performance**: Each service can be optimized independently.
73+
3. **Security**: Isolation limits potential attack vectors.
74+
75+
## Step-By-Step Integration
76+
77+
### 1. Install `laravel-workflow` in all microservices.
78+
Follow the [installation guide](https://laravel-workflow.com/docs/installation/).
79+
80+
### 2. Create a shared database/redis connection in all microservices.
81+
```php
82+
// config/database.php
83+
'connections' => [
84+
'shared' => [
85+
'driver' => 'mysql',
86+
'host' => env('SHARED_DB_HOST', '127.0.0.1'),
87+
'database' => env('SHARED_DB_DATABASE', 'forge'),
88+
'username' => env('SHARED_DB_USERNAME', 'forge'),
89+
'password' => env('SHARED_DB_PASSWORD', ''),
90+
],
91+
],
92+
```
93+
94+
### 3. Configure a shared queue connection.
95+
```php
96+
// config/queue.php
97+
'connections' => [
98+
'shared' => [
99+
'driver' => 'redis',
100+
'connection' => 'shared',
101+
'queue' => env('SHARED_REDIS_QUEUE', 'default'),
102+
],
103+
],
104+
```
105+
106+
### 4. Ensure only one microservice publishes Laravel Workflow migrations.
107+
Update the migration to use the shared database connection.
108+
```php
109+
// database/migrations/..._create_workflows_table.php
110+
class CreateWorkflowsTable extends Migration
111+
{
112+
protected $connection = 'shared';
113+
}
114+
```
115+
116+
### 5. Extend workflow models in each microservice to use the shared connection.
117+
```php
118+
// app/Models/StoredWorkflow.php
119+
namespace App\Models;
120+
use Workflow\Models\StoredWorkflow as BaseStoredWorkflow;
121+
122+
class StoredWorkflow extends BaseStoredWorkflow
123+
{
124+
protected $connection = 'shared';
125+
}
126+
```
127+
128+
### 6. Publish Laravel Workflow config and update it with shared models.
129+
```sh
130+
php artisan vendor:publish --provider="Workflow\Providers\WorkflowServiceProvider" --tag="config"
131+
```
132+
133+
### 7. Set workflows and activities to use the shared queue.
134+
```php
135+
// app/Workflows/MyWorkflow.php
136+
class MyWorkflow extends Workflow
137+
{
138+
public $connection = 'shared';
139+
public $queue = 'workflow';
140+
}
141+
```
142+
```php
143+
// app/Workflows/MyActivity.php
144+
class MyActivity extends Activity
145+
{
146+
public $connection = 'shared';
147+
public $queue = 'activity';
148+
}
149+
```
150+
151+
### 8. Ensure microservices define empty counterparts for workflow and activity classes.
152+
#### In the workflow microservice:
153+
```php
154+
class MyWorkflow extends Workflow
155+
{
156+
public $connection = 'shared';
157+
public $queue = 'workflow';
158+
public function execute($name)
159+
{
160+
yield ActivityStub::make(MyActivity::class, $name);
161+
}
162+
}
163+
class MyActivity extends Activity
164+
{
165+
public $connection = 'shared';
166+
public $queue = 'activity';
167+
}
168+
```
169+
170+
#### In the activity microservice:
171+
```php
172+
class MyWorkflow extends Workflow
173+
{
174+
public $connection = 'shared';
175+
public $queue = 'workflow';
176+
}
177+
class MyActivity extends Activity
178+
{
179+
public $connection = 'shared';
180+
public $queue = 'activity';
181+
public function execute($name)
182+
{
183+
return "Hello, {$name}!";
184+
}
185+
}
186+
```
187+
188+
### 9. Ensure all microservices have the same `APP_KEY` in their `.env` file.
189+
This is crucial for proper job serialization across services.
190+
191+
### 10. Run queue workers in each microservice.
192+
```sh
193+
php artisan queue:work shared --queue=workflow
194+
php artisan queue:work shared --queue=activity
195+
```
196+
197+
## Conclusion
198+
By following the steps above, you can ensure seamless interactions between microservices while maintaining modularity and scalability. Laravel Workflow takes care of the discovery and orchestration for you. 🚀
199+
200+
Thanks for reading!
201+

0 commit comments

Comments
 (0)