میکروسروس های لاراول با RabbitMQ و Docker.

پیشنهادی که در این پست درک می کنید ، چگونه می توانید یک معماری ساده میکروسرویس را تهیه کنید ، بدون تمام درام هایی که با آن پیش می رود. ما با یک نقطه شروع می کنیم که می تواند برای هر زمینه ای استفاده کند. خوب ، بگذارید این کار را انجام دهید
اولین قدم می دانست و بارگیری یک مخزن Laravel است که از صفحه رسمی آن Laravel Opalitical توصیه می شود. سپس Docker (من از Docker Desktop استفاده می کنم زیرا برای من بسیار آسان است) اگر از لینوکس استفاده می کنید ، باید به Docker Official Linux بروید.
یک بار که قبلاً با Enviroment بود ، برای آماده سازی معماری ما رفتیم! برای این وبلاگ ما با یک درخواست رستوران به Buesine کار می کنیم ، که اساساً از طریق API-Manager (مشتری) ما به کلیه خدمات میکروسروس هایی که موسیقی ، فروشگاه های مواد غذایی و دستور العمل ها هستند ، نامیدیم. این میکروسرویسها با خود ارتباط برقرار می کنند و سپس پاسخی به مدیر API باز می گردند ، همه درخواست های مشتری را به دست می آورد. به یاد داشته باشید یک پروژه ایجاد کنید (میکروسرویس برای هر ماژول)
معماری ما مانند:
api-manager
cousine
grocery-store
recipes
مرحله بعدی بارگیری سرور RabbitMQ ، برای برقراری ارتباط از محیط محلی است. می توانید با استفاده از:docker run --name rabbitmq bitnami/rabbitmq:latest
خوب تقریباً آماده … پس از آماده شدن همه ، زمان ایجاد پرونده .yaml ما برای هر پروژه است. اینجا را ترک کنید که چگونه باید آن را انجام دهید:
برای خدمات API-Manager و Anothers ، ما با ایجاد یک پرونده docker-compose با نام شروع می کنیم: docker-compose.yml
شما چیزی شبیه به
به یاد داشته باشید که باید در ریشه سرویس یا میکروسرویس باشد
اکنون ، شما باید یک سند آهنگسازی Docker را به شرح زیر بدست آورید:
services:
db:
image: mysql:latest
container_name: mysql
ports:
- "3306:3306"
volumes:
- mysql-volumes:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: laravel
networks:
- app-network
laravel-app:
build:
context: ./docker/php
container_name: laravel-app
volumes:
- .:/home/source/main
working_dir: /home/source/main
networks:
- app-network
nginx:
build:
context: ./docker/nginx
container_name: todo-nginx
ports:
- "8000:80"
depends_on:
- laravel-app
volumes:
- .:/home/source/main
networks:
- app-network
volumes:
mysql-volumes:
driver: local
networks:
app-network:
driver: bridge
name: app-network
به همین ترتیب برای هر سرویس. در اینجا:
پسر عموی
services:
db:
image: mysql:latest
container_name: mysql-cousine
ports:
- "3307:3306"
volumes:
- mysql-volumes-cousine:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: laravel_cousine
networks:
- app-network
laravel-app:
build:
context: ./docker/php
container_name: micro-cousine
volumes:
- .:/home/source/main
working_dir: /home/source/main
networks:
- app-network
nginx:
build:
context: ./docker/nginx
container_name: todo-nginx-cousine
ports:
- "8001:80"
depends_on:
- laravel-app
volumes:
- .:/home/source/main
networks:
- app-network
volumes:
mysql-volumes-cousine:
driver: local
networks:
app-network:
driver: bridge
name: app-network
دستور العمل ها
services:
db:
image: mysql:latest
container_name: mysql-recipes
ports:
- "3309:3306"
volumes:
- mysql-volumes-recipes:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: laravel_recipes
networks:
- app-network
laravel-app:
build:
context: ./docker/php
container_name: micro-recipes
volumes:
- .:/home/source/main
working_dir: /home/source/main
networks:
- app-network
nginx:
build:
context: ./docker/nginx
container_name: todo-nginx-recipes
ports:
- "8003:80"
depends_on:
- laravel-app
volumes:
- .:/home/source/main
networks:
- app-network
volumes:
mysql-volumes-recipes:
driver: local
networks:
app-network:
driver: bridge
name: app-network
فروشگاه مواد غذایی
services:
db:
image: mysql:latest
container_name: mysql-grosery-store
ports:
- "3308:3306"
volumes:
- mysql-volumes-grosery-store:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: laravel_grocery
networks:
- app-network
laravel-app:
build:
context: ./docker/php
container_name: micro-grosery-store
volumes:
- .:/home/source/main
working_dir: /home/source/main
networks:
- app-network
nginx:
build:
context: ./docker/nginx
container_name: todo-nginx-grosery-store
ports:
- "8002:80"
depends_on:
- laravel-app
volumes:
- .:/home/source/main
networks:
- app-network
volumes:
mysql-volumes-grosery-store:
driver: local
networks:
app-network:
driver: bridge
name: app-network
سپس برای هر سرویس: docker compose up
به یاد داشته باشید که هر میکروسرویس با تنظیمات پایگاه داده های خود کار می کند ، شما باید به کنسول دسترسی پیدا کرده و دسترسی به پایگاه داده ها را تنظیم کنید.
مهم: شما باید پایگاه داده های خود را در ظرف خود تنظیم کنید ، اجازه دسترسی به کمک هزینه ، ایجاد کاربر و غیره را دهید.
در این قسمت لحظه به لحظه برای کدگذاری و تنظیم است. در این حالت ، مدیر API تمام درخواست های مشتری را اداره می کند ، سپس این درخواست را برای هر میکروسرویس (بوین ، فروشگاه های مواد غذایی ، دستور العمل ها) ارسال کنید.
successful()) {
return response()->json($response->json(), 200);
} else {
return response()->json(['error' => 'No se pudieron obtener los datos'], $response->status());
}
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
SendMQ::handle('send_store_cousine_queue','send_store_cousine_exchange','cousine_key', $request->all());
SendMQ::close();
return response()->json(['message' => 'Mensaje enviado correctamente']);
}
/**
* Display the specified resource.
*/
public function show(string $id)
{
$response = Http::get('http://nginx/api/cousine/'.$id);
if ($response->successful()) {
return response()->json($response->json(), 200);
} else {
return response()->json(['error' => 'No se pudieron obtener los datos'], $response->status());
}
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
{
$payload = [
'order_number' => $request->order_number,
'status_id' => $request->status_id,
'id' => $id
];
// Despachar el job para actualizar una receta específica
SendMQ::handle('send_update_cousine_queue','send_update_cousine_exchange','cousine_key_update', $payload);
SendMQ::close();
}
public function updateWithIngredientsUpdated(Request $request, string $id)
{
$payload = [
'order_number' => $request->order_number,
'status_id' => $request->status_id,
'recipe_id' => $request->recipe_id,
'id' => $id
];
// Despachar el job para actualizar una receta específica
SendMQ::handle('send_update_cousine_ingredient_queue','send_update_cousine_ingredient_exchange','cousine_key_update_ingredient', $payload);
SendMQ::close();
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
DeleteCousineJob::dispatch($id);
return response()->json(['message' => 'Cousine deleted'], 200);
}
}
بله می دانم … سوال شما این است ¿کلاس SendMQ را از کجا می گیرم؟
در این مثال ، من می خواهم نشان دهم ، چگونه می توان از استراتژی ها هنگام استفاده از میکروسرویس استفاده کرد ، لازم نیست که همه چیز را با RabbitMQ یا Kafka یا SQS پیاده سازی کنید ، رویدادها کارگردانی می کند. شما می توانید ترکیب کنید به شما نیاز دارد. برای این مثال ، من یک پوشه سرویس و با 2 سرویس ایجاد کردم: ConsumEMQ و SendMQ ، هرکدام مسئولیت آنها را بر عهده دارند. در اینجا یک کد بگذارید:
SENDMQ: کلاس
channel();
}
}
/**
* Envia un mensaje a la cola de mensajeria indicada.
*
* @param string $queueName Nombre de la cola de mensajeria.
* @param string $exchangeName Nombre de la exchange de mensajeria.
* @param string $routingKey Clave de routing para la cola especificada.
* @param mixed $data Contenido del mensaje.
*/
public static function handle($queueName, $exchangeName, $routingKey, $data)
{
self::connect();
self::$channel->exchange_declare($exchangeName, 'direct', false, false, false);
self::$channel->queue_declare($queueName, false, false, false, false);
self::$channel->queue_bind($queueName, $exchangeName, $routingKey);
$msg = new AMQPMessage(json_encode($data));
self::$channel->basic_publish($msg, $exchangeName, $routingKey);
}
/**
* Cierra la conexi n a RabbitMQ.
*
* Este m todo debe ser llamado cuando se haya terminado
* de enviar mensajes y se desee liberar los recursos
* relacionados con la conexi n.
*/
public static function close()
{
if (self::$channel) {
self::$channel->close();
}
if (self::$connection) {
self::$connection->close();
}
}
}
رفیق
channel();
}
}
public static function handle($queueName)
{
self::connect();
// Declarar la cola
self::$channel->queue_declare($queueName, false, false, false, false);
// Callback para manejar los mensajes recibidos
$msgCallback = function (AMQPMessage $msg) {
Log::info(' [x] Recibiendo: ' . $msg->body);
// Almacenar el mensaje recibido
$list = json_decode($msg->body, true);
CousineController::setDataList($list);
};
// Configurar el consumidor
self::$channel->basic_consume($queueName, '', false, true, false, false, $msgCallback);
// Mantener el consumidor activo hasta que se detenga
echo " [*] Waiting for messages. To exit press CTRL+C\n";
while (self::$channel->is_consuming()) {
self::$channel->wait();
}
return self::$receivedData; // Retornar los datos recibidos
}
public static function getReceivedData()
{
return self::$receivedData;
}
public static function close()
{
if (self::$channel) {
self::$channel->close();
}
if (self::$connection) {
self::$connection->close();
}
}
}
سپس اجازه دهید مبادله ما را پیکربندی کنیم. روی *پیکربندی * پوشه شما باید یک فایل با نامی ایجاد کنید که ارتباط شما با RabbitMQ را مشخص کند. برای این مورد: amqp.php. زمینه بعدی است
return [
/*
|--------------------------------------------------------------------------
| Define which configuration should be used
|--------------------------------------------------------------------------
*/
'use' => env('AMQP_ENV', 'production'),
/*
|--------------------------------------------------------------------------
| AMQP properties separated by key
|--------------------------------------------------------------------------
*/
'properties' => [
'production' => [
'host' => env('AMQP_HOST', 'localhost'),
'port' => env('AMQP_PORT', 5672),
'username' => env('AMQP_USER', 'myuser'),
'password' => env('AMQP_PASSWORD', 'mypass'),
'vhost' => env('AMQP_VHOST', "https://dev.to/"),
'connect_options' => [],
'ssl_options' => [],
'exchange' => 'amq.topic',
'exchange_type' => 'topic',
'exchange_passive' => false,
'exchange_durable' => true,
'exchange_auto_delete' => false,
'exchange_internal' => false,
'exchange_nowait' => false,
'exchange_properties' => [],
'queue_force_declare' => false,
'queue_passive' => false,
'queue_durable' => true,
'queue_exclusive' => false,
'queue_auto_delete' => false,
'queue_nowait' => false,
'queue_properties' => ['x-ha-policy' => ['S', 'all']],
'consumer_tag' => '',
'consumer_no_local' => false,
'consumer_no_ack' => false,
'consumer_exclusive' => false,
'consumer_nowait' => false,
'consumer_properties' => [],
'timeout' => 0,
'persistent' => false,
'publish_timeout' => 0, // Only applicable when a publish is marked as mandatory
'qos' => false,
'qos_prefetch_size' => 0,
'qos_prefetch_count' => 1,
'qos_a_global' => false
],
],
];
با این همه چیز ، ما در حال حاضر برای کار هستیم …
*من صبر می کنم که برای شما مفید باشد .. به یاد داشته باشید که نظر خود را ترک کنید یا بپرسید. شما همیشه خوش آمدید *
پیوند کامل در اینجا
من را دنبال کنید: brngranado در اینستاگرام ، X ، LinkedIn ، موضوعات.