当前位置: 首页 > 知识库问答 >
问题:

建模服务错误——gRPC Vs谷歌API

康烨伟
2023-03-14

处理gRPC服务中的错误通常需要status消息和errorcode。两者都有两个定义:

  • Google API定义(googleapis/go genproto)——为通用协议缓冲区类型生成的go包,以及为Google的gRPC API生成的gRPC代码

<代码>状态和<代码>代码两种定义的Go包是:

谷歌API

  • 状态:google.golang.org/genproto/googleapis/rpc/status
  • 代码:google.golang.org/genproto/googleapis/rpc/code

gRPC

  • 状态:谷歌。戈朗。org/grpc/status

由于我是自己的gRPC服务的客户,而不是现有谷歌gRPC API的客户,我想使用gRPC定义的Statuscode

然而,状态的gRPC原型文件实际上是从Google API定义中复制的。看见https://github.com/grpc/grpc/tree/master/src/proto/grpc/status.状态的go_包。proto也没有改变,所以Google API和gRPC定义都使用以下Go包

option go_package = "google.golang.org/genproto/googleapis/rpc/status;status";

结果是,定义API时使用状态的唯一方法是使用

import "google/rpc/status.proto";

...以及导入Go with中的语言绑定

import (
   "google.golang.org/genproto/googleapis/rpc/status"
)
// Go server code...

但如前所述,这是错误的,因为我不是Google API的客户端,而是我自己的gRPC服务。因此,语言绑定应该使用

import (
   "google.golang.org/grpc/status"
)
// Go server code...

正如预期的那样,如果我切换到导入gRPC语言绑定,并尝试向API客户端返回状态消息,我会得到一个编译错误

cannot use &(status.Status literal)
(value of type *"google.golang.org/grpc/internal/status".Status) as 
*"google.golang.org/genproto/googleapis/rpc/status".Status value

这是由我的引起的。proto文件使用Google API定义的状态,而服务器实现(在Go中)使用gRPC定义。

该问题会影响错误代码,因为Google API使用有符号32位整数(int32),而gRPC使用无符号32位整数(uint32)。

问题

  • 我断言我应该使用StatusCodes的gRPC定义正确吗?
  • 如果我的断言是正确的,那么在为Google API打包时,如何使用status的gRPC定义?

共有1个答案

邢运良
2023-03-14

我们需要区分几个案例。有些是显而易见的,有些则不然。

如果您的proto模式(.proto文件)没有定义直接使用状态代码的消息,那么gRPC处理程序只需使用“google.golang.org/gRPC/Status”即可满足返回类型错误。错误(),或Newf()。Err()。就这样。

例子:

// implements SomeServiceServer unary RPC GetFoo
func (s *SomeService) GetFoo(ctx context.Context, req *grpc.FooRequest) (*grpc.FooResponse, error) {
    // status is "google.golang.org/grpc/status"
    return nil, status.Error(codes.Unimplemented, "coming soon")

在这种情况下,您被迫使用googleapis实现。正如您已经看到的,status.protoGo包定义为:

option go_package = "google.golang.org/genproto/googleapis/rpc/status;status";

假设您有以下。proto文件,其中导入的状态。proto只是gRPC状态的复制粘贴。根据这个问题:

syntax = "proto3";

package test;

import "status.proto";

option go_package = ".;main";

message Foo {
  string a = 1;
  google.rpc.Status status = 2;
}

目录结构为:

/protos
|_ status.proto
|_ test.proto

你可以用以下方法编译上面的内容:

cd protos && protoc -I=. --go_out=. test.proto

呼吸然后生成的Go代码将具有以下导入

import (
    status "google.golang.org/genproto/googleapis/rpc/status"
)

你必须通过获取谷歌来满足这一点。戈朗。org/genproto

所以关于你的第一个问题,你只能在原始文件中使用googleapis中的status,因为这就是status.proto声明其Go包的方式。

由于导入的Go程序包来自googleapis,因此您必须在Go代码中使用它来初始化此类消息:

package main

import (
    "fmt"
    googleapis "google.golang.org/genproto/googleapis/rpc/status"
)

func main() {
    foo := &Foo{
        A: "foo",
        Status: &googleapis.Status{
            Code:    int32(code.Code_OK),
            Message: "all good",
        },
    }
    // fmt.Println(foo)
}

你不能。protoc用上面描述的包生成代码。如果您确实需要使用grpc go构建这些Status字段,您可以使用Status。Proto

package main

import (
    "fmt"
    "google.golang.org/grpc/codes"
    "google.golang.org/grpc/status"
)

func main() {
    foo := &Foo{
        A: "foo",
        Status: status.New(codes.OK, "all good").Proto(),
    }
    fmt.Println(foo)
}

只是为了记录,状态也可能相反。FromProto

package main

import (
    "fmt"
    googleapis_codes "google.golang.org/genproto/googleapis/rpc/code"
    googleapis "google.golang.org/genproto/googleapis/rpc/status"
    "google.golang.org/grpc/status"
)

func main() {
    gapisStatus := &googleapis.Status{
        Code: int32(googleapis_codes.Code_OK),
        Message: "all good",
    }
    grpcStatus := status.FromProto(gapisStatus)
    fmt.Println(grpcStatus)
}

作为一种行为不太好的选择,您可以简单地复制粘贴状态。proto将源代码导入项目,并手动更改go_包

option go_package = "google.golang.org/grpc/status;status";

通过这种方式,protoc将通过此导入生成Go代码,您自己的源代码将能够跟进。当然,这意味着你现在有了自己的身份分支。proto

 类似资料:
  • 我收到了这个错误 已经跟踪了https://developers.google.com/admin-sdk/directory/v1/guides/delegation 我使用这个库,并在laravel 5.7:https://github.com/spatie/laravel-google-calendar上运行它 有什么办法可以解决这个问题。请帮忙。

  • 我正在尝试向Google AdWords API发出任何请求,该请求将返回非错误。 我使用开发者令牌创建了生产MCC帐户,此外,我还从测试帐户在google开发者控制台中创建了测试MCC帐户和OAuth2应用程序。 另外,我已经测试了不同的帐户(生产MCC,测试MCC,启用adword的用户,没有adword的用户)为auth应用程序/用户从谁的请求已 适用于任何设置/不同的客户端。我正在获取访问

  • 我想使用Google服务帐户JWT令牌获取Azure服务主体(SP)的临时凭据。这是从GKE工作负载调用Azure API所必需的,而无需在GKE中存储长期SP凭据。 这样的联盟对GCP来说可能吗- [1]https://cloud.google.com/iam/docs/workload-identity-federation [2] https://docs.aws.amazon.com/IA

  • 根据这个SO线程,我知道存在版本冲突,但在谷歌发布新版本后,问题仍然存在。 错误:任务': app: Process DebugGoogleServices'执行失败。请通过更新google-service插件的版本(有关最新版本的信息可在https://bintray.com/android/android-tools/com.google.gms.google-services/获得)或将co

  • 我使用Genymotion,google play游戏服务的最后一个版本。

  • 我试图将谷歌登录集成到我的应用程序中。我没有后端服务器,我只是得到登录到我的应用程序的谷歌帐户的详细信息。 我第一次尝试使用谷歌登录的例子,但我得到了一个错误(除了打印下面的stacktrace外,没有进行任何代码更改)。我只是使用了signianctivity示例,因为我没有后端服务器。 密码 从我所读到的,这个问题可能是由SHA1一代引起的。 我遵循了完整的指南,但显然它不起作用。 我从gra