服务器和拨号选项

我们简要提到了 ServerOptionDialOption,分别是 grpc.ServerOption 对象和 grpc.WithTransportCredentials 函数。然而,实际上有很多其他的选项可供选择。为了提高可读性,我不会详细讲解每一个选项,但我想介绍一些你可能会用到的主要选项。所有的 ServerOptions 可以在 grpc-go 仓库的 server.go 文件中找到( 链接 ),而 DialOptions 则可以在 dialoptions.go 文件中找到( 链接)。

grpc.Creds

这是一个在服务器和客户端两端都可以使用的选项,我们将在讨论如何保护 API 时使用它。

目前,我们看到可以通过调用 grpc.WithTransportCredentials 并传入 insecure.NewCredentials 来建立一个不安全的连接。这意味着请求和响应不会被加密,任何人都可以拦截这些消息并读取它们。

grpc.Creds 允许我们提供一个 TransportCredentials 对象实例,这是所有支持的传输安全协议(如 TLSSSL)的通用接口。如果我们有一个名为 server.crt 的证书文件和一个名为 server.pem 的密钥文件,我们可以创建如下的 ServerOption

certFile := "server.crt"
keyFile := "server.pem"
creds, err := credentials.NewServerTLSFromFile(certFile, keyFile)

if err != nil {
    log.Fatalf("failed loading certificates: %v\n", err)
}
opts = append(opts, grpc.Creds(creds))

同样,在客户端,我们将使用一个 证书授权机构(CA) 证书,并需要创建以下 DialOptions 以便与服务器通信:

certFile := "ca.crt"
creds, err := credentials.NewClientTLSFromFile(certFile, "")

if err != nil {
    log.Fatalf("error while loading CA trust certificate: %v\n", err)
}
opts = append(opts, grpc.WithTransportCredentials(creds))

目前,你不需要太担心这些内容。如我所提到的,我们将在稍后的章节中使用这些选项,并且会详细讲解如何获取证书。

grpc.*Interceptor

如果你不熟悉拦截器,它们是一些在处理请求(服务器端)或发送请求(客户端)之前或之后被调用的代码。其主要目的是通常用来为请求添加一些额外的信息,但它们也可以用来记录请求日志,或者在请求没有正确的头部信息时拒绝该请求。

我们稍后会看到如何定义拦截器,但可以想象我们有一段代码用于记录请求,还有另一段代码检查是否设置了授权头部。我们可以在服务器端将这些拦截器链式调用,如下所示:

opts = append(opts, grpc.ChainUnaryInterceptor(LogInterceptor(), CheckHeaderInterceptor()))

注意,拦截器的顺序很重要,因为它们会按照 grpc.ChainUnaryInterceptor 函数中提供的顺序依次调用。

在客户端,我们也可以有类似的日志拦截器,另一个拦截器可以为请求添加授权头部,并使用缓存的 token 来进行身份验证。这会像下面这样:

opts = append(opts, grpc.WithChainUnaryInterceptor(LogInterceptor(), AddHeaderInterceptor()))

最后,注意你还可以使用其他函数来添加这些拦截器。以下是一些其他函数:

  • WithUnaryInterceptor 用于设置单一的 unary RPC 拦截器

  • WithStreamInterceptor 用于设置单一的流式 RPC 拦截器

  • WithChainStreamInterceptor 用于链式调用多个流式 RPC 拦截器

我们看到了一些可以在服务器端和客户端配置的重要选项。通过使用凭据,我们可以确保通信双方的通信安全;通过使用拦截器,我们可以在发送或接收请求之前运行任意的代码。显然,我们这里只看了两个选项,实际上在服务器端和客户端还有很多其他选项。如果你有兴趣查看所有选项,欢迎访问本节开头提到的 GitHub 仓库。