gRPC实现推荐系统客户端和服务端

编写客户端

在toutiao-backend/common/rpc目录下新建client.py

import grpc
import reco_pb2
import reco_pb2_grpc
import time


def feed_articles(stub):
    # 构建rpc调用的调用参数
    user_request = reco_pb2.UserRequest()
    user_request.user_id = '1'
    user_request.channel_id = 1
    user_request.article_num = 10
    user_request.time_stamp = round(time.time()*1000)

    # 通过stub进行方法调用,并接收调用返回值
    ret = stub.user_recommend(user_request)
    print('ret={}'.format(ret))

def run():
    """
    rpc客户端调用的方法
    """
    # 使用with语句连接rpc服务器
    with grpc.insecure_channel('127.0.0.1:8888') as channel:
        # 创建调用rpc远端服务的辅助对象stub
        stub = reco_pb2_grpc.UserRecommendStub(channel)
        # 通过stub进行rpc调用
        feed_articles(stub)

if __name__ == '__main__':
    run()

补全服务端

为了方便看到效果,我们编写补全服务端代码。

注意:此处实际推荐的代码在后续推荐系统课程中会涉及到

在toutiao-backend/common/rpc目录下新建server.py文件

import reco_pb2
import reco_pb2_grpc
import grpc
from concurrent.futures import ThreadPoolExecutor
import time


# rpc接口定义中服务对应成Python的类
class UserRecommendService(reco_pb2_grpc.UserRecommendServicer):

    # 在接口定义的同名方法中补全,被调用时应该执行的逻辑
    def user_recommend(self, request, context):
        # request是调用的请求数据对象
        user_id = request.user_id
        channel_id = request.channel_id
        article_num = request.article_num
        time_stamp = request.time_stamp

        response = reco_pb2.ArticleResponse()
        response.exposure = 'exposure param'
        response.time_stamp = round(time.time()*1000)
        recommends = []
        for i in range(article_num):
            article = reco_pb2.Article()
            article.track.click = 'click param {}'.format(i+1)
            article.track.collect = 'collect param {}'.format(i+1)
            article.track.share = 'share param {}'.format(i+1)
            article.track.read = 'read param {}'.format(i+1)
            article.article_id = i+1
            recommends.append(article)
        response.recommends.extend(recommends)

        # 最终要返回一个调用结果
        return response


def serve():
    """
    rpc服务端启动方法
    """
    # 创建一个rpc服务器
    server = grpc.server(ThreadPoolExecutor(max_workers=10))

    # 向服务器中添加被调用的服务方法
    reco_pb2_grpc.add_UserRecommendServicer_to_server(UserRecommendService(), server)

    # 微服务器绑定ip地址和端口
    server.add_insecure_port('127.0.0.1:8888')

    # 启动rpc服务
    server.start()

    # start()不会阻塞,此处需要加上循环睡眠 防止程序退出
    while True:
        time.sleep(10)


if __name__ == '__main__':
    serve()

下面是一个使用JSON作为序列化协议的gRPC通信的客户端服务端的示例,其中定义了一个名为`HelloWorld`的简单服务,客户端发送一个名为`name`的字符串,服务端返回一个包含`Hello, name!`的字符串: #### 服务端 ```cpp #include <iostream> #include <memory> #include <string> #include <grpcpp/grpcpp.h> #include <grpcpp/server.h> #include <grpcpp/server_builder.h> #include <grpcpp/server_context.h> #include "helloworld.grpc.pb.h" using grpc::Server; using grpc::ServerBuilder; using grpc::ServerContext; using grpc::Status; using helloworld::HelloRequest; using helloworld::HelloReply; using helloworld::Greeter; class GreeterServiceImpl final : public Greeter::Service { Status SayHello(ServerContext* context, const HelloRequest* request, HelloReply* reply) override { std::string prefix("Hello, "); reply->set_message(prefix + request->name()); return Status::OK; } }; void RunServer() { std::string server_address("0.0.0.0:50051"); GreeterServiceImpl service; grpc::EnableDefaultHealthCheckService(true); grpc::reflection::InitProtoReflectionServerBuilderPlugin(); ServerBuilder builder; builder.AddListeningPort(server_address, grpc::InsecureServerCredentials()); builder.RegisterService(&service); std::unique_ptr<Server> server(builder.BuildAndStart()); std::cout << "Server listening on " << server_address << std::endl; server->Wait(); } int main(int argc, char** argv) { RunServer(); return 0; } ``` #### 客户端 ```cpp #include <iostream> #include <memory> #include <string> #include <grpcpp/grpcpp.h> #include <grpcpp/ext/proto_server_reflection_plugin.h> #include <grpcpp/health_check_service_interface.h> #include "helloworld.grpc.pb.h" using grpc::Channel; using grpc::ClientContext; using grpc::Status; using helloworld::HelloRequest; using helloworld::HelloReply; using helloworld::Greeter; class GreeterClient { public: GreeterClient(std::shared_ptr<Channel> channel) : stub_(Greeter::NewStub(channel)) {} std::string SayHello(const std::string& name) { HelloRequest request; request.set_name(name); HelloReply reply; ClientContext context; std::string serializedRequest, serializedReply; grpc::SerializationTraits<HelloRequest>::serialize(request, &serializedRequest); Status status = stub_->CallRPC("SayHello", serializedRequest, &serializedReply); if (status.ok()) { grpc::SerializationTraits<HelloReply>::deserialize(serializedReply, &reply); return reply.message(); } else { std::cout << "RPC failed: " << status.error_message() << std::endl; return ""; } } private: std::unique_ptr<Greeter::Stub> stub_; }; int main(int argc, char** argv) { std::string name("World"); GreeterClient greeter(grpc::CreateChannel("localhost:50051", grpc::InsecureChannelCredentials())); std::string reply = greeter.SayHello(name); std::cout << "Received: " << reply << std::endl; return 0; } ``` 在这个例子中,我们使用了`grpc::SerializationTraits`类将请求和响应对象序列化为JSON字符串。`GreeterClient`类实现客户端的逻辑,`SayHello`函数发送一个`HelloRequest`对象到服务端,并返回一个包含`Hello, name!`的字符串。在`main`函数中,我们使用`CreateChannel`函数创建一个与服务端通信的通道,并使用`GreeterClient`类进行通信。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梦实学习室

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值