#python #node.js #grpc #grpc-python #grpc-node
#python #node.js #grpc #grpc-python #grpc-узел
Вопрос:
У меня есть сервер gRPC, реализованный на python, и я вызываю RPC из NodeJS, но он выдает ошибку «Метод не найден». Когда я вызываю с помощью клиента python, запрос выполняется успешно.
stream_csv.proto
syntax = "proto3";
package csv;
service Stream {
rpc csvToObject(CSVDataRequest) returns (stream CSVDataResponse) {};
rpc sayHello(HelloRequest) returns (HelloReply);
}
message CSVDataRequest{
string url = 1;
enum Protocol {
HTTP = 0;
HTTPS = 1;
FTP = 2;
SFTP = 3;
}
Protocol protocol = 2;
}
message CSVDataResponse{
repeated string row = 1;
}
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
client.js
var PROTO_PATH = '../stream_csv.proto';
var grpc = require('grpc');
var protoLoader = require('@grpc/proto-loader');
var packageDefinition = protoLoader.loadSync(
PROTO_PATH,
{keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true
});
var proto = grpc.loadPackageDefinition(packageDefinition).csv;
function main() {
var client = new proto.Stream('localhost:5000',
grpc.credentials.createInsecure());
var user;
if (process.argv.length >= 3) {
user = process.argv[2];
} else {
user = 'world';
}
console.log(user);
client.sayHello({name: user}, function(err, response) {
console.log(err);
});
}
main();
server.py
импорт grpc импорт stream_csv_pb2 импорт urllib.запрос из urllib.ошибка импорт HTTPError, URLError из параллельных фьючерсов импорта
class DataService:
def csv_to_object(self, request, context):
url = request.url
protocol = stream_csv_pb2.CSVDataRequest.Protocol.Name(
request.protocol)
fetch_url = protocol.lower() "://" url
try:
with urllib.request.urlopen(fetch_url) as data:
for line in data:
decoded_line = line.decode()
val = decoded_line.split(',')
print(val)
print("Data send")
yield stream_csv_pb2.CSVDataResponse(row=val)
print("Sending finished!")
except URLError as e:
context.abort(grpc.StatusCode.UNKNOWN,
'Randomly injected failure.')
# return stream_csv_pb2.CSVDataResponse(row=[], error=e.reason)
def SayHello(self, request, context):
name = request.name
print(name)
return stream_csv_pb2.HelloReply(message='Hello %s' % (name))
def add_DataServicer_to_server(servicer, server):
rpc_method_handlers = {
'CSVToObject': grpc.unary_stream_rpc_method_handler(
servicer.csv_to_object,
request_deserializer=stream_csv_pb2.CSVDataRequest.FromString,
response_serializer=stream_csv_pb2.CSVDataResponse.SerializeToString,
),
'SayHello': grpc.unary_unary_rpc_method_handler(
servicer.SayHello,
request_deserializer=stream_csv_pb2.HelloRequest.FromString,
response_serializer=stream_csv_pb2.HelloReply.SerializeToString,
)
}
generic_handler = grpc.method_handlers_generic_handler(
'stream_csv.Stream', rpc_method_handlers)
server.add_generic_rpc_handlers((generic_handler,))
def serve():
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
add_DataServicer_to_server(DataService(), server)
server.add_insecure_port('[::]:5000')
server.start()
server.wait_for_termination()
if __name__ == '__main__':
serve()
Ошибка
Error: 12 UNIMPLEMENTED: Method not found!
at Object.exports.createStatusError (/home/shantam/Documents/grepsr/client/node_modules/grpc/src/common.js:91:15)
at Object.onReceiveStatus (/home/shantam/Documents/grepsr/client/node_modules/grpc/src/client_interceptors.js:1209:28)
at InterceptingListener._callNext (/home/shantam/Documents/grepsr/client/node_modules/grpc/src/client_interceptors.js:568:42)
at InterceptingListener.onReceiveStatus (/home/shantam/Documents/grepsr/client/node_modules/grpc/src/client_interceptors.js:618:8)
at callback (/home/shantam/Documents/grepsr/client/node_modules/grpc/src/client_interceptors.js:847:24) {
code: 12,
metadata: Metadata { _internal_repr: {}, flags: 0 },
details: 'Method not found!'
}
Комментарии:
1. Вы решили это? Если нет, я посмотрю позже сегодня
2. @DazWilkin да, я решил эту проблему. Я неправильно скомпилировал файл .proto.
3. Полезно знать! Кстати, вы можете переключиться на
@grpc/grpc-js
. Ваш код работает с подкачкой.
Ответ №1:
Я написал более простой вариант ваших реализаций сервера Python (и Golang).
Оба работают с вашим узлом.JS-клиент как есть.
Я думаю, возможно, ваша проблема так же проста, как необходимость назвать rpc sayHello
(а не SayHello
).
from concurrent import futures
import logging
import grpc
import stream_csv_pb2
import stream_csv_pb2_grpc
class Stream(stream_csv_pb2_grpc.StreamServicer):
def sayHello(self, request, context):
logging.info("[sayHello]")
return stream_csv_pb2.HelloReply(message='Hello, %s!' % request.name)
def serve():
logging.info("[serve]")
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
stream_csv_pb2_grpc.add_StreamServicer_to_server(Stream(), server)
server.add_insecure_port('[::]:50051')
server.start()
server.wait_for_termination()
if __name__ == '__main__':
logging.basicConfig()
serve()
И:
node client.js
Greeting: Hello, Freddie!
null
Обычно (!) gRPC следует руководству по стилю Protobufs для службы обработки запросов, имен rpc и сообщений и использует подчеркивания в другом месте, см. Руководство по стилю. При protoc
компиляции результаты не всегда совпадают идеально (например, функции Python в формате camelCased, а не в нижнем регистре с подчеркиванием).
Обычно ваш прототип будет:
service Stream {
rpc CsvToObject(CSVDataRequest) returns (stream CSVDataResponse) {};
rpc SayHello(HelloRequest) returns (HelloReply);
}
… и тогда сгенерированная Python функция тоже будет (!) SayHello
.
Комментарии:
1. Проблема заключалась в том, что я неправильно скомпилировал файл ‘.proto’.
2. Я думаю, возможно, ваша проблема так же проста, как необходимость назвать rpc sayHello (а не sayHello). Это сработало для меня