119 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			119 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| ---
 | ||
| title: Async messaging with RabbitMQ and Tortoise
 | ||
| localeTitle: الرسائل غير المتزامنة مع RabbitMQ والسلحفاة
 | ||
| ---
 | ||
| RabbitMQ يحدث ليكون أسهل وسيط منصات منصة الوسيط رسالة باستخدام بروتوكول AMQ هناك اليوم. ويترجم استخدامه في الهندسة المعمارية الدقيقة إلى مكاسب هائلة في الأداء ، فضلاً عن الوعد بالموثوقية. في هذا الدليل ، سنستكشف أساسيات استخدام RabbitMQ مع Node.js.
 | ||
| 
 | ||
| ## نظرية
 | ||
| 
 | ||
| في أبسط مستوياتها الأساسية ، سيكون لديك بشكل مثالي خدمتين مختلفتين تتفاعلان مع بعضهما البعض من خلال Rabbit - _ناشر_ _ومشترك_ . عادةً ما ينشر الناشر الرسائل إلى أرنب ، ويستمع أحد المشتركين إلى هذه الرسائل ، وينفذ الرمز على أساس تلك الرسائل. لاحظ أنه يمكن أن يكونا في نفس الوقت - يمكن للخدمة أن تنشر رسائل إلى أرنب وتستهلك الرسائل في نفس الوقت ، مما يجعل الأنظمة القوية بالفعل مصممة.
 | ||
| 
 | ||
| ينشر الناشر عادةً الرسائل التي تحتوي على _مفتاح توجيه_ إلى شيء يسمى _التبادل_ . يستمع المستهلك إلى _قائمة انتظار_ في نفس التبادل ، منضمة إلى مفتاح التوجيه. من الناحية المعمارية ، سيستخدم النظام الأساسي الخاص بك تبادلًا واحدًا للأرانب ، وستكون أنواع مختلفة من الوظائف / الخدمات لها مفاتيح التوجيه الخاصة بها وقوائم الانتظار ، حتى تعمل ميزة pub-sub بشكل فعال. يمكن أن تكون الرسائل عبارة عن سلاسل؛ يمكن أن تكون أيضًا كائنات محلية - تقوم مكتبات عميل AMQP بالرفع الثقيل لتحويل الكائنات من لغة إلى أخرى. ونعم ، هذا يعني أنه يمكن كتابة الخدمات بلغات مختلفة ، طالما أنهم قادرون على فهم AMQP.
 | ||
| 
 | ||
| ## ابدء
 | ||
| 
 | ||
| سنقوم بإعداد مثال بسيط للغاية حيث ينشر برنامج ناشر رسالة إلى أرنب تحتوي على عنوان URL ، ويستمع برنامج نصي للمستهلك إلى Rabbit ، ويأخذ عنوان URL المنشور ، ويستدعيه ويعرض النتائج. يمكنك العثور على عينة منتهية على [جيثب](https://github.com/rudimk/freecodecamp-guides-rabbitmq-tortoise) .
 | ||
| 
 | ||
| أولاً ، دعنا نبدأ مشروع npm:
 | ||
| 
 | ||
| `$ npm init`
 | ||
| 
 | ||
| يمكنك دائمًا النقر على " `Enter` بالكامل واستخدام الخيارات الافتراضية - أو يمكنك ملئها. الآن ، دعنا نركب الحزم التي نحتاجها. سنستخدم [السلحفاة](https://www.npmjs.com/package/tortoise) للتفاعل مع RabbitMQ. سنستخدم أيضًا [العقدة-كرون](https://www.npmjs.com/package/node-cron) لجدولة النشر الفعلي للرسائل.
 | ||
| 
 | ||
| `$ npm install --save tortoise node-cron`
 | ||
| 
 | ||
| الآن يجب أن تبدو `package.json` تشبه إلى حد كبير هذا:
 | ||
| 
 | ||
|  `{ 
 | ||
|   "name": "freecodecamp-guides-rabbitmq-tortoise", 
 | ||
|   "version": "1.0.0", 
 | ||
|   "description": "Sample code to accompany the FreeCodeCamp guide on async messaging with RabbitMQ and Tortoise.", 
 | ||
|   "main": "index.js", 
 | ||
|   "scripts": { 
 | ||
|     "test": "echo \"Error: no test specified\" && exit 1" 
 | ||
|   }, 
 | ||
|   "repository": { 
 | ||
|     "type": "git", 
 | ||
|     "url": "git+https://github.com/rudimk/freecodecamp-guides-rabbitmq-tortoise.git" 
 | ||
|   }, 
 | ||
|   "keywords": [ 
 | ||
|     "rabbitmq", 
 | ||
|     "tortoise", 
 | ||
|     "amqp" 
 | ||
|   ], 
 | ||
|   "author": "Rudraksh MK", 
 | ||
|   "license": "MIT", 
 | ||
|   "bugs": { 
 | ||
|     "url": "https://github.com/rudimk/freecodecamp-guides-rabbitmq-tortoise/issues" 
 | ||
|   }, 
 | ||
|   "homepage": "https://github.com/rudimk/freecodecamp-guides-rabbitmq-tortoise#readme", 
 | ||
|   "dependencies": { 
 | ||
|     "node-cron": "^1.2.1", 
 | ||
|     "tortoise": "^1.0.1" 
 | ||
|   } 
 | ||
|  } 
 | ||
| ` 
 | ||
| 
 | ||
| نحن الآن جاهزون لنقم بإنشاء ناشر أولاً.
 | ||
| 
 | ||
|  ``const Tortoise = require('tortoise') 
 | ||
|  const cron = require('node-cron') 
 | ||
|  
 | ||
|  const tortoise = new Tortoise(`amqp://rudimk:YouKnowWhat@$localhost:5672`) 
 | ||
| `` 
 | ||
| 
 | ||
| بعد استيراد `tortoise` `node-cron` ، لقد ذهبنا إلى الأمام وأضفت اتصالاً بـ RabbitMQ. بعد ذلك ، دعنا نكتب وظيفة سريعة وقذرة تنشر رسالة إلى أرنب:
 | ||
| 
 | ||
|  `function scheduleMessage(){ 
 | ||
|     let payload = {url: 'https://randomuser.me/api'} 
 | ||
|     tortoise 
 | ||
|     .exchange('random-user-exchange', 'direct', { durable:false }) 
 | ||
|     .publish('random-user-key', payload) 
 | ||
|  } 
 | ||
| ` 
 | ||
| 
 | ||
| هذا بسيط بما فيه الكفاية. لقد حددنا قاموسًا يحتوي على عنوان URL [لواجهة](https://randomuser.me/) برمجة تطبيقات [RandomUser.me](https://randomuser.me/) ، والتي يتم نشرها بعد ذلك إلى `random-user-exchange` تبادل `random-user-exchange` على RabbitMQ ، مع `random-user-key` التوجيه `random-user-key` . كما ذكرنا من قبل ، فإن مفتاح التوجيه هو الذي يحدد من الذي يستهلك رسالة. الآن ، دعنا نكتب قاعدة جدولة ، لنشر هذه الرسالة كل 60 ثانية.
 | ||
| 
 | ||
|  `cron.schedule('60 * * * * *', scheduleMessage) 
 | ||
| ` 
 | ||
| 
 | ||
| وناشرنا جاهز! ولكن في الحقيقة ليس جيدًا بدون المستهلك أن يستهلك هذه الرسائل فعليًا! لكننا نحتاج أولاً إلى مكتبة يمكنها الاتصال بعنوان URL في هذه الرسائل. شخصيا ، أنا استخدم `superagent` : `npm install --save superagent` .
 | ||
| 
 | ||
| الآن ، في `consumer.js` :
 | ||
| 
 | ||
|  ``const Tortoise = require('tortoise') 
 | ||
|  const superagent = require('superagent') 
 | ||
|  
 | ||
|  const tortoise = new Tortoise(`amqp://rudimk:YouKnowWhat@$localhost:5672`) 
 | ||
| `` 
 | ||
| 
 | ||
| بعد ذلك ، دعنا نكتب دالة متزامنة تستدعي عنوان URL وتعرض النتيجة:
 | ||
| 
 | ||
|  `async function getURL(url){ 
 | ||
|     let response = await superagent.get(url) 
 | ||
|     return response.body 
 | ||
|  } 
 | ||
| ` 
 | ||
| 
 | ||
| وقت كتابة التعليمات البرمجية لاستهلاك الرسائل فعليًا:
 | ||
| 
 | ||
|  `tortoise 
 | ||
|  .queue('random-user-queue', { durable: false }) 
 | ||
|  // Add as many bindings as needed 
 | ||
|  .exchange('random-user-exchange', 'direct', 'random-user-key', { durable: false }) 
 | ||
|  .prefetch(1) 
 | ||
|  .subscribe(function(msg, ack, nack) { 
 | ||
|   // Handle 
 | ||
|   let payload = JSON.parse(msg) 
 | ||
|   getURL(payload['url']).then((response) => { 
 | ||
|     console.log('Job result: ', response) 
 | ||
|   }) 
 | ||
|   ack() // or nack() 
 | ||
|  }) 
 | ||
| ` 
 | ||
| 
 | ||
| هنا ، أخبرنا `tortoise` أن نستمع إلى `random-user-queue` ، وهذا يرتبط `random-user-key` `random-user-exchange` . بمجرد استلام الرسالة ، يتم استرداد الحمولة من `msg` ، ويتم تمريرها إلى `getURL` ، والتي بدورها تقوم بإرجاع Promation مع استجابة JSON المطلوبة من RandomUser API.
 | ||
| 
 | ||
| ## استنتاج
 | ||
| 
 | ||
| البساطة المرتبطة باستخدام RabbitMQ للمراسلة لا مثيل لها ، ومن السهل جدًا الوصول إلى أنماط الخدمة الدقيقة المعقدة بالفعل ، مع بضعة أسطر من الشفرات فقط. أفضل جزء هو أن المنطق وراء الرسائل لا يتغير حقاً عبر اللغات - تعمل Crystal أو Go أو Python أو Ruby مع Rabbit بنفس الطريقة تقريبًا - وهذا يعني أنه يمكن أن يكون لديك خدمات مكتوبة بلغات مختلفة تتواصل جميعها مع بعضها البعض دون بذل أي جهد ، مما يتيح لك استخدام أفضل لغة لهذا المنصب. |