Differences

This shows you the differences between two versions of the page.

Link to this comparison view

isi:laboratoare:07 [2024/11/17 18:16]
stefanel.turcu
isi:laboratoare:07 [2024/11/21 11:04] (current)
sorin.ciolofan
Line 184: Line 184:
 </​code>​ </​code>​
  
-== Exemplu Complet ​==+== Extra == 
 +Pentru a vedea un exemplu complet despre cum două aplicații, un ''​sender''​ și un ''​receiver'',​ comunică folosind RabbitMQ, precum și pentru a citi explicații mai detaliate, vizitați acest tutorial: [[https://​www.rabbitmq.com/​tutorials/​tutorial-one-python|Hello World]].
  
-<code python>​ +În cadrul acestuia veți găsi exemplificat ​întregul proces de conectare la RabbitMQ: crearea unei cozi (queue)trimiterea ​și recepția mesajelorprecum ​și închiderea conexiunii.
-import pika +
- +
-# Conectare la RabbitMQ +
-credentials = pika.PlainCredentials("​guest",​ "​guest"​) +
-connection_params = pika.ConnectionParameters(host='​localhost',​ port=5672, credentials=credentials) +
-connection = pika.BlockingConnection(connection_params) ​  +
-# connection = pika.BlockingConnection(pika.ConnectionParameters('​localhost'​)) +
-channel = connection.channel() +
- +
-# Crearea unui queue +
-queue_name = '​my_queue'​ +
-channel.queue_declare(queue=queue_name) +
- +
-# Trimiterea unui mesaj +
-message = "Salut din RabbitMQ!"​ +
-channel.basic_publish(exchange='',​ routing_key=queue_name,​ body=message) +
-print(f"​Mesaj trimis: {message}"​) +
- +
-# Definirea callback-ului pentru a prelua mesajele +
-def callback(ch,​ method, properties, body): +
-    print(f"​Mesaj primit: {body.decode()}"​) +
- +
-# Configurarea consumatorului pentru a asculta queue-ul specificat +
-channel.basic_consume(queue=queue_name,​ on_message_callback=callback,​ auto_ack=True) +
- +
-# Începerea consumului de mesaje +
-print("​Aștept mesaje..."​) +
-channel.start_consuming() +
- +
-# Închiderea conexiunii +
-connection.close() +
-print("​Conexiunea la RabbitMQ a fost închisă."​) +
-</​code>​ +
- +
-Acest script exemplifică întregul proces de conectare la RabbitMQ, creare de queue, ​trimitere ​și recepție de mesaje, și închiderea conexiunii.+
  
 === Exemplu de Utilizare a unui Exchange ''​fanout''​ în RabbitMQ === === Exemplu de Utilizare a unui Exchange ''​fanout''​ în RabbitMQ ===
 +Până acum am văzut cum putem crea o coadă (queue), să trimitem un mesaj pe aceasta și să consumăm acel mesaj. În cadrul exemplului anterior, am presupus că un mesaj este trimis către o singură coadă. În ceea ce urmează, vom face ceva complet diferit – vom livra un mesaj către mai mulți consumatori (îl vom publica pe mai multe queue-uri). Acest pattern este cunoscut sub denumirea de **„publish/​subscribe”**.
  
 În acest exemplu, vom: În acest exemplu, vom:
Line 262: Line 229:
 connection.close() connection.close()
 </​code>​ </​code>​
- 
-== Explicații Pas cu Pas == 
- 
-1. **Crearea exchange-ului**:​ ''​broadcast_exchange''​ este un exchange de tip ''​fanout'',​ care trimite mesajele primite către toate queue-urile conectate la el, indiferent de ''​routing key''​. 
- 
-2. **Crearea queue-urilor**:​ Se creează două queue-uri, ''​queue1''​ și ''​queue2'',​ fiecare fiind destinat să primească mesajele difuzate de exchange. 
- 
-3. **Legarea queue-urilor la exchange**: ''​queue1''​ și ''​queue2''​ sunt conectate la exchange-ul ''​broadcast_exchange''​ fără a specifica ''​routing key'',​ deoarece aceasta nu este folosită în exchange-urile de tip ''​fanout''​. 
- 
-4. **Trimiterea mesajului**:​ Mesajul „Salut tuturor consumatorilor!” este trimis către exchange-ul ''​broadcast_exchange''​. Fiind de tip ''​fanout'',​ exchange-ul va transmite acest mesaj către toate queue-urile conectate (''​queue1''​ și ''​queue2''​). 
  
 == Rezultatul Așteptat == == Rezultatul Așteptat ==
Line 283: Line 240:
  
 === Partea 2 - Exerciții: === === Partea 2 - Exerciții: ===
-0. Rulați local o instanță de RabbitMQ, fie folosind //​docker-compose//​-ul pus la dispoziție mai sus, fie instalând RabbitMQ direct pe mașina voastră. **Atenție**,​ dacă optați pentru instalarea directă pe mașina voastră, va fi necesar să instalați separat plugin-ul care oferă acces la interfața web. 
  
-1. **Creează un script Python care să permită citirea textelor de la tastatură și publicarea acestora într-un exchange nou.** +<​note>​ 
-Scriptul va citi textul de la utilizator și va publica fiecare mesaj în exchange-ul RabbitMQ, care este creat programatic după realizarea cu succes a conexiunii la RabbitMQExchange-ul va fi configurat din cod imediat după inițializarea conexiunii.+Descărcați proiectul de pe GitHub: [[https://​github.com/​ACS-ISI/​Messenger/​tree/​main|Messenger]] 
 +</​note>​ 
 + 
 + 
 +<note tip> 
 +Pentru a instala toate dependențele necesare pentru laboratorul de astăzi, rulați: ''​pip install -r requirements.txt''​. Fișierul ''​requirements.txt''​ poate fi descărcat de aici: [[https://​github.com/​ACS-ISI/​Messenger/​blob/​main/​requirements.txt|requirements.txt]]. 
 +</​note>​ 
 +0. Rulați local o instanță de RabbitMQ, fie folosind //​docker-compose//​-ul pus la dispoziție mai sus, fie instalând RabbitMQ direct pe mașina voastră. **Atenție**,​ dacă optați pentru instalarea directă pe mașina voastră, va fi necesar să instalați separat plugin-ul care oferă acces la interfața web - [[https://​www.rabbitmq.com/​docs/​management|Plugin]]. 
 + 
 +1. **Creează un script Python care să permită citirea textelor de la tastatură și publicarea acestora într-un exchange nou.** ​(care este creat programatic după realizarea cu succes a conexiunii la RabbitMQ). ​Scriptul va citi textul de la utilizator și va publica fiecare mesaj în exchange-ul RabbitMQ ​(in mod ''​fanout''​). 
 + 
 +<code python>​ 
 +try: 
 +   while True: 
 +      message = input("​Message:​ ") 
 +      channel.basic_publish(exchange=exchange_name,​ routing_key='',​ body=message) 
 +finally: 
 +    connection.close() 
 +</​code>​
  
 2. **Creează un script Python care să creeze un queue, să-l lege la exchange-ul din exercițiul 1 și să afișeze fiecare mesaj primit.** 2. **Creează un script Python care să creeze un queue, să-l lege la exchange-ul din exercițiul 1 și să afișeze fiecare mesaj primit.**
-Scriptul va crea un queue nou și îl va asocia (binding) cu exchange-ul creat în exercițiul anterior. Pentru fiecare mesaj primit în queue, scriptul va afișa conținutul acestuia ​pe ecran.+Scriptul va crea un queue nou și îl va asocia (binding) cu exchange-ul creat în exercițiul anterior. Pentru fiecare mesaj primit în queue, scriptul va afișa conținutul acestuia ​în consolă.
  
 +<code python>
 +channel.queue_bind(exchange=exchange_name,​ queue=queue_name)
 +</​code>​
  
-3. **Chat interactiv** ​- Pornind de la codul pentru această aplicație de mesagerie, implementează funcționalitățile necesare, marcate cu TODO-uri in fisierul ''​message_service.py'',​ pentru ca aceasta să funcționeze complet:+3. **Chat interactiv**
  
-<​note>​ +Această aplicație presupune un server Flask care interacționează cu RabbitMQ șexpune o interfață web pentru utilizator.
-Descărcați proiectul de pe GitHub: [[https://​github.com/​ACS-ISI/​Messenger/​tree/​main|Messenger]] +
-</​note>​+
  
-  ​* a) Trimite la fiecare 30 de secunde un mesaj de tip broadcast pe exchange-ul '​chat_online_user_exchange'​ și fără nici un routing_key,​ prin care să informezi ceilalți participanți la chat că ești online și disponibil pentru conversație. Asigură-te că acest mesaj are un timp de viață de maximum 2 minute în queue. +**Implementare:​** Pornind de la codul pentru această aplicație de mesagerie, implementează funcționalitățile necesare, marcate cu TODO-uri in fisierul ''​message_service.py'',​ pentru ca aceasta să funcționeze complet: 
-  * b) Consumă mesajele care sosesc pe queue-ul tău. Adaugă un `consumer_tag` cu numele queue-ului, astfel încât consumatorul să nu mai asculte la acest queue atunci când utilizatorul se deconectează (logout). + 
-  * c) Implementează trimiterea unui mesaj către un anumit utilizator pentru a putea iniția o conversație privată cu acesta+  * TODO a) Trimite la fiecare 30 de secunde un mesaj de tip broadcast pe exchange-ul '​chat_online_user_exchange'​ și fără nici un routing_key,​ prin care să informezi ceilalți participanți la chat că ești online și disponibil pentru conversație. Asigură-te că acest mesaj are un timp de viață de maximum 2 minute în queue. 
-  * d) Testează funcționalitatea pentru a verifica dacă poți comunica cu un alt utilizator. +  * TODO b) Consumă mesajele care sosesc pe queue-ul tău. Adaugă un `consumer_tag` cu numele queue-ului, astfel încât consumatorul să nu mai asculte la acest queue atunci când utilizatorul se deconectează (logout). 
-  * e) Schimbă conexiunea la RabbitMQ cu următoarea și testează dacă poți conversa cu alți colegi.+  * TODO c) Implementează trimiterea unui mesaj către un anumit utilizator pentru a putea iniția o conversație privată cu acesta.
  
 <note tip> <note tip>
-Pentru a rula aplicația, folosește comanda: ''​flask run''​. Aceasta va rula implicit pe portul 5000, iar pentru a vizualiza interfața pusă la dispoziție de aceasta, deschideți [[http://​localhost:​5000|]]. 
  
-Pentru a rula aplicația pe un alt port decât cel implicit, rulați ''​flask run --port 5001''​. +Folosește instanța locală șrulează scriptul ​''​initialize.py'' ​din laborator, care configurează 3 utilizatori:​ **stefan**, **alex** și **maria**.
-</​note>​+
  
-<note tip> +**Testare**: Pentru a testa aplicația, puteți rula două instanțe ale aplicației pe porturi diferite, pentru a simula doi utilizatori care folosesc aplicația pe dispozitive diferiteÎn cadrul testării, punctul a) poate fi verificat individual, iar punctele b) și c) vor fi testate împreună
-**Host: ** acc-atomicsoftware.swedencentral.cloudapp.azure.com + 
-  +Pentru a rula aplicația, folosește comanda''​python app.py''​ sau ''​flask run''​. 
-**User** student + 
-  +Aceasta va rula implicit pe portul 5000, iar pentru a vizualiza interfața pusă la dispoziție ​de aceasta, deschideți [[http://​localhost:​5000|]]. 
-**Parola: ** întreabă coordonatorul ​de laborator + 
 +Pentru a rula aplicația pe un alt port decât cel implicit, rulați ''​flask run <​nowiki>​--</​nowiki>​port 5001''​.
 </​note>​ </​note>​
 +
 +**Testare:​**
 +
 +  * Testează funcționalitatea pentru a verifica dacă poți comunica cu un alt utilizator (folosind două instanțe locale de aplicație).
 +  * Schimbă conexiunea la RabbitMQ cu următoarea și testează dacă poți conversa cu alți colegi:
 +
 +<​code>​
 +Host: acc-atomicsoftware.swedencentral.cloudapp.azure.com
 +User: student
 +Parola: întreabă coordonatorul de laborator
 +</​code>​
  
 <note important>​ <note important>​
-În cadrul acestui exercițiu, nu vei declara queue-uri sau exchange-uri,​ deoarece acestea sunt deja create. Până să te conectezi la instanța din cloud, folosește instanța locală și rulează scriptul ''​initialize.py''​ din laborator, care configurează 3 utilizatori:​ **stefan**, **alex** și **maria**. +În cadrul acestui exercițiu, nu vei declara queue-uri sau exchange-uri,​ deoarece acestea sunt deja create ​pe instanța din cloud.
-</​note>​+
  
-<note tip>**Important**:​ Când te conectezi la instanța din cloud, utilizatorii vor avea formatul ''​nume_prenume_grupa''​. Dacă nu ești sigur care este utilizatorul pregătit pentru tine, conectează-te la:+**Important**:​ Când te conectezi la instanța din cloud, utilizatorii vor avea formatul ''​nume_prenume_grupa''​. Dacă nu ești sigur care este utilizatorul pregătit pentru tine, conectează-te la:
  
 [[http://​acc-atomicsoftware.swedencentral.cloudapp.azure.com:​15672]] [[http://​acc-atomicsoftware.swedencentral.cloudapp.azure.com:​15672]]
  
 cu utilizatorul si parola de mai sus și caută în tab-ul //Queues and Streams// după numele tău. Queue-ul o să se numească //​chatUser.username//,​ iar tu trebuie să folosești doar //​username//​ pentru a te conecta. În situația în care totuși nu te regăsești,​ poți folosi unul dintre utilizatorii următori: //bob//, //alice//, //stefan//, //​alex//​.</​note>​ cu utilizatorul si parola de mai sus și caută în tab-ul //Queues and Streams// după numele tău. Queue-ul o să se numească //​chatUser.username//,​ iar tu trebuie să folosești doar //​username//​ pentru a te conecta. În situația în care totuși nu te regăsești,​ poți folosi unul dintre utilizatorii următori: //bob//, //alice//, //stefan//, //​alex//​.</​note>​
 +
 +<note important>​
 +În situația în care întâmpinați o eroare similară cu "​connection lost" sau "​unable to pop from an empty queue" atunci când începeți să consumați mesaje, este indicat să adăugați o metodă nouă pentru a crea un channel și să utilizați un channel nou creat atunci când începeți să ascultați.
 +
 +<​code>​
 +  def getChannel(self):​
 +    connection = pika.BlockingConnection(self.connection_params)
 +    return connection.channel()
 +</​code>​
 +</​note>​
  
  
 **Diagrame explicative ale exercițiului 3:** **Diagrame explicative ale exercițiului 3:**
  
 +<​spoiler>​
 {{:​isi:​laboratoare:​general-architecture.jpg?​400|}} {{:​isi:​laboratoare:​general-architecture.jpg?​400|}}
  
Line 336: Line 331:
  
 {{:​isi:​laboratoare:​rabbitmq-send-message.jpg?​500|}} {{:​isi:​laboratoare:​rabbitmq-send-message.jpg?​500|}}
 +</​spoiler>​
  
  
  
isi/laboratoare/07.1731860200.txt.gz · Last modified: 2024/11/17 18:16 by stefanel.turcu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0