首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >gRPC betterproto socket.gaierror:[Errno 8] nodename或servname提供或不知道

gRPC betterproto socket.gaierror:[Errno 8] nodename或servname提供或不知道
EN

Stack Overflow用户
提问于 2022-07-22 18:38:19
回答 1查看 180关注 0票数 0

我正在使用gRPC创建微服务。为了从.proto文件生成代码,我使用的是更好的而不是grpcio工具。当我使用Flask作为客户端应用程序来调用服务器的函数时,它会产生错误:

代码语言:javascript
运行
复制
    _, protocol = await self._loop.create_connection(
  File "/opt/homebrew/Cellar/python@3.9/3.9.12_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/base_events.py", line 1026, in create_connection
    infos = await self._ensure_resolved(
  File "/opt/homebrew/Cellar/python@3.9/3.9.12_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/base_events.py", line 1405, in _ensure_resolved
    return await loop.getaddrinfo(host, port, family=family, type=type,
  File "/opt/homebrew/Cellar/python@3.9/3.9.12_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/base_events.py", line 861, in getaddrinfo
    return await self.run_in_executor(
  File "/opt/homebrew/Cellar/python@3.9/3.9.12_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/concurrent/futures/thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/opt/homebrew/Cellar/python@3.9/3.9.12_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/socket.py", line 954, in getaddrinfo
    for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
socket.gaierror: [Errno 8] nodename nor servname provided, or not known

我使用的是MacOS,Python3.9.12,protobuf预发布版本。如何解决这个错误?

db.proto

代码语言:javascript
运行
复制
syntax = "proto3";

package db;

import "google/protobuf/timestamp.proto";

message Box {
  string name = 1;
  int32 id = 2;
  int32 price = 3;
  string description = 4;
  string category = 5;
  int32 quantity = 6;
  google.protobuf.Timestamp created_at = 7;
}

enum RequestStatus
{
    OK = 0;
    ERROR = 1;
}


message GetAllBoxesRequest {
}

message GetBoxesResponse {
  repeated Box box = 1;
  RequestStatus status = 2;
}

service DatabaseService {
  rpc GetBoxes(GetAllBoxesRequest) returns (GetBoxesResponse) {}
}

这里是从betterproto生成的文件

db/init.py

代码语言:javascript
运行
复制
# Generated by the protocol buffer compiler.  DO NOT EDIT!
# sources: db.proto
# plugin: python-betterproto
from dataclasses import dataclass
from datetime import datetime
from typing import Dict, List

import betterproto
from betterproto.grpc.grpclib_server import ServiceBase
import grpclib


class RequestStatus(betterproto.Enum):
    OK = 0
    ERROR = 1


@dataclass(eq=False, repr=False)
class Box(betterproto.Message):
    name: str = betterproto.string_field(1)
    id: int = betterproto.int32_field(2)
    price: int = betterproto.int32_field(3)
    description: str = betterproto.string_field(4)
    category: str = betterproto.string_field(5)
    quantity: int = betterproto.int32_field(6)
    created_at: datetime = betterproto.message_field(7)


@dataclass(eq=False, repr=False)
class GetAllBoxesRequest(betterproto.Message):
    pass


@dataclass(eq=False, repr=False)
class GetBoxesResponse(betterproto.Message):
    box: List["Box"] = betterproto.message_field(1)
    status: "RequestStatus" = betterproto.enum_field(2)


class DatabaseServiceStub(betterproto.ServiceStub):
    
    async def get_boxes(self) -> "GetBoxesResponse":

        request = GetAllBoxesRequest()

        return await self._unary_unary(
            "/db.DatabaseService/GetBoxes", request, GetBoxesResponse
        )

    


class DatabaseServiceBase(ServiceBase):
    
    async def get_boxes(self) -> "GetBoxesResponse":
        raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)

    async def __rpc_get_boxes(self, stream: grpclib.server.Stream) -> None:
        request = await stream.recv_message()

        request_kwargs = {}

        response = await self.get_boxes(**request_kwargs)
        await stream.send_message(response)

    def __mapping__(self) -> Dict[str, grpclib.const.Handler]:
        return {
            "/db.DatabaseService/GetBoxes": grpclib.const.Handler(
                self.__rpc_get_boxes,
                grpclib.const.Cardinality.UNARY_UNARY,
                GetAllBoxesRequest,
                GetBoxesResponse,
            ),
        }

server.py

代码语言:javascript
运行
复制
import asyncio
import logging
from db import (
    DatabaseServiceBase,
    Box,
    RequestStatus,
    GetBoxesResponse,
)
from grpclib.server import Server
from pymongo import MongoClient

log = logging.getLogger(__name__)


def get_database():
    CONNECTION_STRING = f"mongodb://{DB_USERNAME}:{DB_USER_PASSWORD}@{DB_HOST}:{DB_PORT}"

    # Create a connection using MongoClient
    client = MongoClient(CONNECTION_STRING)

    # Create the database and return it
    return client.boxes

boxes_db = get_database()


def dict_to_box(data):
    if "_id" in data:
        data["id"] = data.pop("_id")
    return Box(**data)


class DatabaseService(DatabaseServiceBase):

    async def get_boxes(self) -> "GetBoxesResponse":
        boxes = boxes_db.boxes.find()
        list_of_boxes = [dict_to_box(box) for box in boxes]
        return GetBoxesResponse(box=list_of_boxes, status=RequestStatus.OK)


async def main():
    server = Server([DatabaseService()])
    await server.start("127.0.0.1", 50051)
    await server.wait_closed()


if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())

由于betterproto生成异步函数,所以我额外安装了Flask异步:pip install "flask[async]"。您可以在下面的app.py中看到,我正在使用异步函数。

app.py (瓶)

代码语言:javascript
运行
复制
import os
import asyncio

from flask import Flask, render_template
from grpclib.client import Channel

import db

app = Flask(__name__)

SERVICE_HOST = os.getenv("SERVICE_HOST", "127.0.0.1")
SERVICE_PORT = os.getenv("SERVICE_PORT", 50051)


@app.route("/")
async def render_homepage():
    service_channel = Channel(f"{SERVICE_HOST}:{SERVICE_PORT}")
    service = db.DatabaseServiceStub(service_channel)

    get_boxes_response = await service.get_boxes() # <-- Error is throwing here

    service_channel.close()
    return render_template(
        "index.html",
        boxes=get_boxes_response.box,
    )

if __name__ == '__main__':
    app.run(debug=True)
EN

Stack Overflow用户

发布于 2022-07-23 04:47:43

回答我自己的问题!

我发现我是用错误的方式向app.py发送对撞机,这应该是Channel(host=SERVICE_HOST, port=SERVICE_PORT)而不是Channel(f"{SERVICE_HOST}:{SERVICE_PORT}")

票数 0
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73084753

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档