rabbitmq中文教程python版 - 遠端過程呼叫
原始碼:https://github.com/ltoddy/rabbitmq-tutorial
遠端過程呼叫(RPC)
(using the Pika Python client)
本章節教程重點介紹的內容
在第二篇教程中,我們學習瞭如何使用工作佇列在多個工作人員之間分配耗時的任務。
但是如果我們需要在遠端計算機上執行某個功能並等待結果呢?那麼,這是一個不同的事情。
這種模式通常稱為遠端過程呼叫(RPC)。
在本教程中,我們將使用RabbitMQ構建一個RPC系統:一個客戶端和一個可擴充套件的RPC伺服器。
由於我們沒有任何值得分發的耗時任務,我們將建立一個返回斐波那契數字的虛擬RPC服務。
客戶端介面
為了說明如何使用RPC服務,我們將建立一個簡單的客戶端類。它將公開一個名為call的方法 ,
它傳送一個RPC請求並阻塞,直到收到答案:
fibonacci_rpc = FibonacciRpcClient()
result = fibonacci_rpc.call(4)
print("fib(4) is %r" % result)
*有關RPC的說明*
雖然RPC是計算中很常見的模式,但它經常被吹毛求疵。當程式設計師不知道函式呼叫是本地的還是
慢速的RPC時會出現這些問題。像這樣的混亂導致不可預知的問題,並增加了除錯的不必要的複雜性,
而不是我們想要的簡化軟體。
銘記這一點,請考慮以下建議:
* 確保顯而易見哪個函式呼叫是本地的,哪個是遠端的。
* 記錄您的系統。清楚元件之間的依賴關係。
* 處理錯誤情況。當RPC伺服器長時間關閉時,客戶端應該如何反應?
有疑問時避免RPC。如果可以的話,你應該使用非同步管道 - 而不是類似於RPC的阻塞,
其結果被非同步推送到下一個計算階段。
回撥佇列
一般來說,通過RabbitMQ來執行RPC是很容易的。客戶端傳送請求訊息,伺服器回覆響應訊息。
為了接收響應,客戶端需要傳送一個“回撥”佇列地址和請求。讓我們試試看:
result = channel.queue_declare(exclusive=True)
callback_queue = result.method.queue
channel.basic_publish(exchange='',
routing_key='rpc_queue',
properties=pika.BasicProperties(
reply_to = callback_queue,
),
body=request)
訊息屬性
AMQP 0-9-1協議預定義了一組包含14個屬性的訊息。大多數屬性很少使用,但以下情況除外:
delivery_mode:將訊息標記為持久(值為2)或瞬態(任何其他值)。你可能會記得第二篇教程中的這個屬性。
content_type:用於描述編碼的MIME型別。例如,對於經常使用的JSON編碼,將此屬性設定為application/json是一種很好的做法。
reply_to:通常用於命名回撥佇列。
correlation_id:用於將RPC響應與請求關聯起來。
相關ID
在上面介紹的方法中,我們建議為每個RPC請求建立一個回撥佇列。這是非常低效的,
但幸運的是有一個更好的方法 - 讓我們為每個客戶端建立一個回撥佇列。
這引發了一個新問題,在該佇列中收到回覆後,不清楚回覆屬於哪個請求。那是什麼時候使用correlation_id屬性。
我們將把它設定為每個請求的唯一值。稍後,當我們在回撥佇列中收到訊息時,我們將檢視此屬性,
並基於此屬性,我們將能夠將響應與請求進行匹配。如果我們看到未知的correlation_id值,
我們可以放心地丟棄該訊息 - 它不屬於我們的請求。
您可能會問,為什麼我們應該忽略回撥佇列中的未知訊息,而不是丟擲錯誤?
這是由於伺服器端可能出現競爭狀況。雖然不太可能,但在傳送給我們答案之後,但在傳送請求的確認訊息之前,
RPC伺服器可能會死亡。如果發生這種情況,重新啟動的RPC伺服器將再次處理該請求。
這就是為什麼在客戶端,我們必須優雅地處理重複的響應,理想情況下RPC應該是等冪的。
總結
我們的RPC會像這樣工作:
- 當客戶端啟動時,它建立一個匿名獨佔回撥佇列。
- 對於RPC請求,客戶端將傳送具有兩個屬性的訊息:reply_to,該訊息設定為回撥佇列和correlation_id,該值設定為每個請求的唯一值。
- 該請求被髮送到rpc_queue佇列。
- RPC worker(又名:伺服器)正在等待該佇列上的請求。當出現請求時,它執行該作業,並使用reply_to欄位中的佇列將結果傳送回客戶端。
- 客戶端在回撥佇列中等待資料。當出現訊息時,它會檢查correlation_id屬性。如果它匹配來自請求的值,則返回對應用程式的響應。
把它放在一起
rpc_server.py的程式碼:
#!/usr/bin/env python
import pika
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
channel.queue_declare(queue='rpc_queue')
def fib(n):
if n == 0:
return 0
elif n == 1:
return 1
else:
return fib(n - 1) + fib(n - 2)
def on_request(ch, method, props, body):
n = int(body)
print(" [.] fib(%s)" % n)
response = fib(n)
ch.basic_publish(exchange='',
routing_key=props.reply_to,
properties=pika.BasicProperties(
correlation_id=props.correlation_id),
body=str(response))
ch.basic_ack(delivery_tag=method.delivery_tag)
channel.basic_qos(prefetch_size=1)
channel.basic_consume(on_request, queue='rpc_queue')
print(" [x] Awaiting RPC requests")
channel.start_consuming()
伺服器程式碼非常簡單:
- (4)像往常一樣,我們首先建立連線並宣告佇列。
- (11)我們宣告我們的斐波那契函式。它只假定有效的正整數輸入。(不要指望這個版本適用於大數字,它可能是最慢的遞迴實現)。
- (20)我們宣告瞭basic_consume的回撥,它是RPC伺服器的核心。它在收到請求時執行。它完成工作並將響應發回。
- (34)我們可能想執行多個伺服器程式。為了在多臺伺服器上平均分配負載,我們需要設定prefetch_count設定。
rpc_client.py的程式碼:
#!/usr/bin/env python
import pika
import uuid
class FibonacciRpcClient:
def __init__(self):
self.connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
self.channel = self.connection.channel()
result = self.channel.queue_declare(exclusive=True)
self.callback_queue = result.method.queue
self.channel.basic_consume(self.on_response, no_ack=True)
def on_response(self, ch, method, props, body):
if self.corr_id == props.corrrelation_id:
self.response = body
def call(self, n):
self.response = None
self.corr_id = str(uuid.uuid4())
self.channel.basic_publish(exchange='',
routing_key='rpc_queue',
properties=pika.BasicProperties(
reply_to=self.callback_queue,
correlation_id=self.corr_id),
body=str(n))
while self.response is None:
self.connection.process_data_events()
return int(self.response)
fibonacci_rpc = FibonacciRpcClient()
print(" [x] Requesting fib(30)")
response = fibonacci_rpc.call(30)
print(" [.] Got %r" % response)
客戶端程式碼稍有涉及:
- (8)我們建立連線,通道併為回覆宣告獨佔的“回撥”佇列。
- (17)我們訂閱'回撥'佇列,以便我們可以接收RPC響應。
- (19)對每個響應執行的'on_response'回撥函式做了一個非常簡單的工作,對於每個響應訊息它檢查correlation_id是否是我們正在尋找的。如果是這樣,它將儲存self.response中的響應並打破消費迴圈。
- (23)接下來,我們定義我們的主要呼叫方法 - 它執行實際的RPC請求。
- (25)在這個方法中,首先我們生成一個唯一的correlation_id數並儲存 - 'on_response'回撥函式將使用這個值來捕獲適當的響應。
- (29)接下來,我們釋出具有兩個屬性的請求訊息:reply_to和correlation_id。
- (32)在這一點上,我們可以坐下來等待,直到適當的迴應到達。
- (41)最後,我們將回復返回給使用者。
相關文章
- Google遠端過程呼叫-GRPCGoRPC
- RPC(遠端過程呼叫)詳解RPC
- RabbitMQ 入門 - 遠端呼叫 (RPC)MQRPC
- 使用python遠端操作linux過程解析PythonLinux
- vnc遠端控制軟體中文版,細數五款好用的vnc遠端控制軟體中文版VNC
- 遠端桌面連線中文版 遠端桌面軟體使用方法
- ibatis呼叫oracle儲存過程(極簡版)BATOracle儲存過程
- rabbitmq 新增遠端訪問功能MQ
- Servlet呼叫過程Servlet
- Microsoft Remote Desktop Mac中文版 微軟遠端ROSREMMac微軟
- TeamViewer 15.13.6中文官方版(遠端控制)View
- java通過url呼叫遠端介面返回json資料JavaJSON
- RabbitMQ訊息佇列(七):適用於雲端計算叢集的遠端呼叫(RPC)MQ佇列RPC
- 遠端桌面工具哪個好?Microsoft Remote Desktop遠端桌面連線工具中文版ROSREM
- Go語言高併發與微服務實戰專題精講——遠端過程呼叫 RPCGo微服務RPC
- 呼叫儲存過程儲存過程
- RabbitMQ安裝過程詳解MQ
- 基於 Spring 的遠端過程呼叫(RPC):RMI、Hessian/Burlap、Spring HttpInvoker 四種實現方式詳解SpringRPCHTTP
- 分散式系統:遠端呼叫分散式
- 遠端呼叫中介軟體(RPC)RPC
- RCF--RPC(遠端呼叫框架)RPC框架
- Metasploit遠端呼叫Nessus出錯
- Termius for Mac(遠端管理軟體) 8.4.0中文版Mac
- 多協議遠端管理Termius 啟用中文版最新協議
- ToDesk 1.0.0928a 中文版 Mac必備遠端控制工具Mac
- Microsoft Remote Desktop漢化版下載 微軟遠端桌面中文版ROSREM微軟
- linux呼叫儲存過程Linux儲存過程
- Winform呼叫儲存過程ORM儲存過程
- Dubbo-go 原始碼筆記(二)客戶端呼叫過程Go原始碼筆記客戶端
- RabbitMQ Go客戶端教程5——topicMQGo客戶端
- SpringCloud(一)微服務遠端呼叫 -- RestTemplateSpringGCCloud微服務REST
- [譯]RabbitMQ教程C#版 - 主題MQC#
- mysql如何呼叫儲存過程MySql儲存過程
- jsp中呼叫儲存過程JS儲存過程
- 函式棧幀(呼叫過程)函式
- 系統呼叫篇——3環層面呼叫過程
- Storm系列(五)DRPC實現遠端呼叫ORMRPC
- 徒手擼框架--實現 RPC 遠端呼叫框架RPC