我想在以下場景中使用grpc-python,但不知道如何實作。
場景是,在python服務器中,它使用類來計算和更新實體的狀態,然后將該狀態發送給相應的客戶端;在客戶端,多個客戶端需要與服務器通信才能得到一個結果,而不受其他客戶端的干擾。
具體來說,假設有一個類的初始值self.i = 0,那么客戶端每次呼叫該類的更新函式時,都會執行self.i=self.i 1并回傳self.i。實際上有兩個客戶端同時呼叫這樣的更新函式,比如client1第三次呼叫update,client2第一次呼叫update。
我認為這可以通過為每個客戶端創建執行緒以避免沖突來解決。如果新客戶端呼叫,則會創建新的thead;如果現有客戶端呼叫,將使用現有執行緒。但我不知道如何實作?
希望您能夠幫助我。提前致謝。
uj5u.com熱心網友回復:
我想我自己解決了這個問題。如果您有任何其他更好的解決方案,您可以在這里發布。
我在 grpc-python 介紹中編輯了 helloworld 示例來解釋我的目標。
對于 helloworld.proto
syntax = "proto3";
option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";
option java_outer_classname = "HelloWorldProto";
option objc_class_prefix = "HLW";
package helloworld;
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
rpc Unsubscribe (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
我添加了取消訂閱功能以允許一個特定的客戶端與服務器斷開連接。
在 hello_server.py 中
import grpc
import helloworld_pb2
import helloworld_pb2_grpc
import threading
from threading import RLock
import time
from concurrent import futures
import logging
class Calcuate:
def __init__(self):
self.i = 0
def add(self):
self.i =1
return self.i
class PeerSet(object):
def __init__(self):
self._peers_lock = RLock()
self._peers = {}
self.instances = {}
def connect(self, peer):
with self._peers_lock:
if peer not in self._peers:
print("Peer {} connecting".format(peer))
self._peers[peer] = 1
a = Calcuate()
self.instances[peer] = a
output = a.add()
return output
else:
self._peers[peer] = 1
a = self.instances[peer]
output = a.add()
return output
def disconnect(self, peer):
print("Peer {} disconnecting".format(peer))
with self._peers_lock:
if peer not in self._peers:
raise RuntimeError("Tried to disconnect peer '{}' but it was never connected.".format(peer))
del self._peers[peer]
del self.instances[peer]
def peers(self):
with self._peers_lock:
return self._peers.keys()
class Greeter(helloworld_pb2_grpc.GreeterServicer):
def __init__(self):
self._peer_set = PeerSet()
def _record_peer(self, context):
return self._peer_set.connect(context.peer())
def SayHello(self, request, context):
output = self._record_peer(context)
print("[thread {}] Peers: {}, output: {}".format(threading.currentThread().ident, self._peer_set.peers(), output))
time.sleep(1)
return helloworld_pb2.HelloReply(message='Hello, {}, {}!'.format(request.name, output))
def Unsubscribe(self, request, context):
self._peer_set.disconnect(context.peer())
return helloworld_pb2.HelloReply(message='{} disconnected!'.format(context.peer()))
def serve():
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server)
server.add_insecure_port('[::]:50051')
server.start()
server.wait_for_termination()
if __name__ == '__main__':
logging.basicConfig()
serve()
context.peer() 的使用改編自 Richard Belleville在這篇文章中的回答。您可以將 add() 函式更改為可用于更新實體狀態的任何其他函式。
在 hello_client.py 中
from __future__ import print_function
import logging
import grpc
import helloworld_pb2
import helloworld_pb2_grpc
def run():
# NOTE(gRPC Python Team): .close() is possible on a channel and should be
# used in circumstances in which the with statement does not fit the needs
# of the code.
with grpc.insecure_channel('localhost:50051') as channel:
stub = helloworld_pb2_grpc.GreeterStub(channel)
response = stub.SayHello(helloworld_pb2.HelloRequest(name='you'))
print("Greeter client received: " response.message)
response = stub.SayHello(helloworld_pb2.HelloRequest(name='Tom'))
print("Greeter client received: " response.message)
response = stub.SayHello(helloworld_pb2.HelloRequest(name='Jerry'))
print("Greeter client received: " response.message)
stub.Unsubscribe(helloworld_pb2.HelloRequest(name="end"))
if __name__ == '__main__':
logging.basicConfig()
run()
如果我們同時運行多個hello_client.py,服務器可以區分不同的客戶端并向它們發送正確的對應資訊。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/366717.html
標籤:Python 多线程 grpc grpc-python
