【问题标题】:gRPC Unimplemented/Unknown ServicegRPC 未实现/未知服务
【发布时间】:2021-08-03 19:58:17
【问题描述】:

我正在使用 gRPC 开发一个项目,并且最近将其迁移到让每个服务都在 Docker 容器中运行(值得补充的是,我对容器化还很陌生)。今天,在将我的一个 Go 服务移动到容器中时,我遇到了这个错误,并且已经尝试解决它几个小时,但没有成功。我得到的错误是:

“rpc 错误:代码 = 未实现的 desc = 未知服务 PowerEstimationServicePackage”

我在网上四处查看,似乎该错误虽然描述性不强,但通常意味着您的客户端正在进行的服务调用尚未由服务器在端口上注册。我现在花了几个小时查看我的代码,但我一生都无法弄清楚为什么会出现错误 - 据我所知,我已经正确注册了它!

此外,当我在本地运行 Go 服务时,它运行良好!这让我相信这个问题与我在 Docker 中运行时的端口绑定有关。我觉得我对 Docker 如何处理网络有一个合理的理解,但很可能在这里忽略了一些东西。

相关的客户端代码(本地运行)是:

const {
    addrEstimationSP = "127.0.0.1:50101"
}

// Use this to implement the power estimation service routing
type estimationServer struct {
    serverPB.UnimplementedPowerEstimationServicesServer
}

func main {
    // Create a connection over the specified tcp port
    callCounter := interceptors.ClientMetricStruct{}
    connEstimationSP := CreateInsecureServerConnection(addrEstimationSP, timeoutDuration, callCounter.ClientMetrics)

    /* Create the client and pass the connection made above to it. After the client has been
    created, we create the gRPC request */
    InfoLogger.Println("Creating clients")
    clientEstimationSP := estimationPB.NewPowerEstimationServicePackageClient(connEstimationSP)
    DebugLogger.Println("Succesfully created the clients")

    requestMessageEstimationSP := estimationPB.ServicePackageRequestMessage{
        InputFile: INPUTfilename,
        ModelType: estimationPB.ModelTypeEnum_OPENWATER,
    }

    estimationContext, _ := context.WithTimeout(context.Background(), callTimeoutDuration)
    responseEstimationSP, errEstimationSP := clientEstimationSP.PowerEstimatorService(estimationContext, &requestMessageEstimationSP)
    if errEstimationSP != nil {
        ErrorLogger.Println("Failed to make EstimationSP service call: ")
        ErrorLogger.Println(errEstimationSP)
    } else {
        DebugLogger.Println("Succesfully made service call to GoLang EstimationSP.")
        connEstimationSP.Close()
    }

    responseMessage := serverPB.PowerEstimationResponse{
        PowerEstimate: responseEstimationSP.PowerEstimate,
    }
}

,服务器端的相关代码(这是我试图移入 Docker 的服务)是:

var (
    // Addresses
    addrMyself = os.Getenv("POWERESTIMATIONHOST") + ":50101"
)

// server is used to implement PowerEstimationServicePackage
type server struct {
    serverPB.UnimplementedPowerEstimationServicePackageServer
}

func main() {
    InfoLogger.Println("Started GoLang Aggregator")

    // Create a listener on the specified tcp port
    listener, err := net.Listen("tcp", addrMyself)
    if err != nil {
        ErrorLogger.Fatalf("Failed to listen on port %v: \n%v", addrMyself, err)
    }
    InfoLogger.Println("Listeneing on port: ", addrMyself)

    // Create a gRPC server object
    estimationServer := grpc.NewServer()
    // Attach the power estimation service to the server
    serverPB.RegisterPowerEstimationServicePackageServer(estimationServer, &server{})
    // Start the server
    if err := estimationServer.Serve(listener); err != nil {
        ErrorLogger.Fatalf("Failed to expose service: \n%v", err)
    }
}


func (s *server) PowerEstimatorService(ctx context.Context, request *serverPB.ServicePackageRequestMessage) (*serverPB.EstimateResponseMessage, error) {
    ...
}

客户端能够创建与服务器的连接,但在调用 clientEstimationPB.PowerEstimatorService(...) 时出现错误。该服务在 Docker 网络中运行,因此为其地址传递环境变量。 Dockerfile 和 Docker-compose 文件如下所示:

Dockerfile:

FROM golang:alpine

# Install git.
# Git is required for fetching the dependencies.
RUN apk add --no-cache git

WORKDIR $GOPATH/src/github.com/nicholasbunn/masters/

# Create a program logs folder in the service directory
RUN mkdir ./program\ logs
RUN mkdir -p $GOPATH/src/github.com/nicholasbunn/masters/src/powerEstimationSP

COPY /src/powerEstimationSP/go.mod ./src/powerEstimationSP
COPY /src/powerEstimationSP/go.sum ./src/powerEstimationSP

# Copy over contents into image
COPY src/powerEstimationSP/interceptors/ ./src/powerEstimationSP/interceptors
COPY src/powerEstimationSP/proto/ ./src/powerEstimationSP/proto
COPY certification/ certification
COPY src/powerEstimationSP/powerEstimationSP.go ./src/powerEstimationSP
COPY src/powerEstimationSP/powerEstimationSP_test.go ./src/powerEstimationSP

COPY src/fetchDataService/proto src/fetchDataService/proto
COPY src/prepareDataService/proto src/prepareDataService/proto
COPY src/estimateService/proto src/estimateService/proto

WORKDIR $GOPATH/src/github.com/nicholasbunn/masters//src/powerEstimationSP/

# Fetch the dependecies
RUN go mod tidy

# Build the binary. for grpc gateway
RUN go build -o ./powerEstimationSP .

WORKDIR $GOPATH/src/github.com/nicholasbunn/masters/

EXPOSE 50101
ENTRYPOINT ["./src/powerEstimationSP/powerEstimationSP"]

Docker-compose.yaml:

version: "3.8"

services:
...
    powerestimationsp:
        build: 
            context: .
            dockerfile: src/powerEstimationSP/Dockerfile
        environment: 
            POWERESTIMATIONHOST: powerestimationsp
            FETCHHOST: fetchservice
            PREPAREHOST: prepareservice
            ESTIMATEHOST: estimateservice
            PROMETHEUSHOST: prometheus
        image: power_estimation_sp
        networks: 
            - southernOcean
        ports: 
            - 50101:50101
networks:
    southernOcean:

我觉得解决这个问题真的很简单,可能只是我的一个小误解,我刚刚度过了阴天的一天,所以希望一双新鲜的眼睛可以在这里提供帮助。

谢谢!

【问题讨论】:

    标签: docker docker-compose grpc grpc-go


    【解决方案1】:

    我今天下午解决了问题,将其扔在这里,以防其他人无法通过其他资源解决问题。

    问题实际上来自我的 go 模块,而不是 Docker 或我的代码。我正在处理一个未发布的代码分支,在那里我更改了 proto 文件(我实际上只是将一个小写字母更改为大写字母以保持语义一致),但我的 go.mod 文件正在拉取旧版本的proto 与较新的不兼容。客户端使用较新的,因为它在本地机器上运行,而服务器在本地运行时使用较新的,这就是它在 Docker 之外工作的原因。在我的 Dockerfile(上图)中,我运行“RUN go mod tidy”,它从我的主分支中提取旧的 proto 文件并注册了一个不同命名的服务,这就是我收到此错误的原因。

    无论如何,很高兴现在一切都解决了!希望这可以帮助其他人。

    【讨论】:

      猜你喜欢
      • 2018-10-21
      • 2019-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-10
      • 2017-12-26
      • 1970-01-01
      相关资源
      最近更新 更多