gRPC技术优势在哪里?有什么缺点和应对策略?

举报
Jet Ding 发表于 2020/09/30 15:31:38 2020/09/30
【摘要】 gRPC(gRPC Remote Procedure Calls)是一个开源的远程过程调用(RPC)系统,由谷歌公司最先在2015年开发。它使用HTTP/2作为传输方式,协议缓冲器作为接口描述语言,提供了认证、双向流和流控制、阻塞或非阻塞绑定、取消和超时等功能。它可以为许多编程语言生成跨平台的客户端和服务器绑定。最常见的使用场景包括在微服务架构中的服务连接,以及移动设备、网页客户端连接到后端服务等

【引言】

gRPC(gRPC Remote Procedure Calls)是一个开源的远程过程调用(RPC)系统,由谷歌公司最先在2015年开发。它使用HTTP/2作为传输方式,协议缓冲器作为接口描述语言,提供了认证、双向流和流控制、阻塞或非阻塞绑定、取消和超时等功能。它可以为许多编程语言生成跨平台的客户端和服务器绑定。最常见的使用场景包括在微服务架构中的服务连接,以及移动设备、网页客户端连接到后端服务等。

 

【概述】

gRPC中,客户端应用程序可以直接调用不同服务器应用程序上的方法,就像调用本地对象接口一样,这让你更容易创建分布式应用和服务。和许多RPC系统一样,gRPC也是围绕着定义一个服务的思想,指定可以远程调用的方法,参数和返回类型。在服务器端,服务程序实现这个接口,并运行gRPC服务器来处理客户端的调用。在客户端上有一个存根,这个存根提供与服务器相同的方法。

image.png


gRPC客户端和服务器可以在各种环境下运行和对话,并且可以用gRPC支持的任何一种语言编写。比如,你可以轻松地用Java创建一个gRPC服务器,用GoPythonRuby的客户端来调用。此外,最新的Google API都会有gRPC版本的接口,让你可以轻松地将Google功能构建到你的应用程序中。

 

gRPC的优点】

性能

gRPC消息使用Protobuf进行序列化,Protobuf是一种高效的二进制消息格式。Protobuf在服务器和客户端上的序列化速度非常快。Protobuf序列化的结果是消息的有效载荷小,这对于移动应用等有限带宽的场景来说非常重要。

 

gRPC是为HTTP/2设计的,这是HTTP的一个重要修订版,它比HTTP 1.x提供了显著的性能优势。

 

l  二进制框架和压缩技术的使用使得HTTP/2协议在发送和接收方面都非常紧凑和高效。

l  在单一TCP连接上实现多个HTTP/2调用的复用。多路复用消除了线头阻塞。

 

代码通过工具生成

所有的gRPC框架都提供了一流的代码生成支持。gRPC开发的一个核心文件是.proto文件,它定义了gRPC服务和消息的契约。从这个文件中,gRPC框架将代码生成一个服务基类、消息和一个完整的客户端。

 

通过在服务器和客户端之间共享.proto文件,消息和客户端的代码可以从端到端的生成。客户端的代码生成消除了客户端和服务器上的消息重复,为你创建一个强类型化的客户端。在有很多服务的应用程序中,不需要编写客户端,这可以节省大量的开发时间。

 

严格的规范

目前还没有一个针对使用JSONHTTP API的正式规范。开发者们一直对URLHTTP动词和响应代码的最佳格式争论不休。

 

gRPC规范对gRPC服务必须遵循的格式是有规定的。gRPC消除了争论,从而节省了开发者的时间,因为gRPC在不同平台和实现上是一致的。

 

流处理

 

HTTP/2为长效实时通信流提供了基础,gRPC通过HTTP/2提供了一流的流处理支持。

 

一个gRPC服务支持所有的流处理组合:

 

l  单一式(无流处理)

l  服务器到客户端的流处理

l  客户端到服务器的流处理

l  双向流处理

 

超时取消机制

gRPC允许客户端指定他们愿意等待多长时间完成一个RPC。把这个时间决定的最后期限被发送至服务器,服务器可以决定超过最后期限时采取什么行动。例如,服务器可以在超时后取消正在进行中的gRPCHTTP或数据库请求。

 

通过对gRPC调用设置超时取消机制,有助于实现对资源的限制使用。

 

gRPC的缓冲器与认证】

【使用协议缓冲器】

 

gRPC使用协议缓冲区对数据进行编码。与使用JSONHTTP API不同,它们有一个更严格的规范。

 

协议缓冲区是Google成熟的开源机制,用于序列化结构化数据(尽管它可以使用其他数据格式,如JSON)。以下是对其工作原理的简单介绍。

 

在使用协议缓冲区时,第一步是在proto文件中定义要序列化的数据结构:是一个普通的文本文件,扩展名为.proto。协议缓冲区的数据是以消息的形式结构化,每个消息都是一个小的逻辑信息记录,其中包含一系列称为字段的名-值对。下面是一个简单的例子:

message Person {

  string name = 1;

  int32 id = 2;

  bool has_ponycopter = 3;

}

 

接着,一旦你指定了你的数据结构,你就可以使用协议缓冲区编译器 protoc 从你的 proto 定义中生成你喜欢的编程语言的数据访问类。这些类为每个字段提供了简单的访问器,如 name() set_name(),以及将整个结构序列化/解析为原始字节的方法。因此,例如,如果你选择的语言是C++,用上面的例子中运行,编译器会生成一个名为Person的类。然后你可以在你的应用程序中使用这个类来填充、序列化和检索Person协议缓冲区消息。

 

你在普通的proto文件中定义gRPC服务,RPC方法参数和返回类型指定为协议缓冲区消息:

// greeter 服务定义.

service Greeter {

    // 发出问候

    rpc SayHello (HelloRequestreturns (HelloReply) {}

  }

  

  // 请求信息包含用户名字

  message HelloRequest {

    string name = 1;

  }

  

  // 响应消息包含问候消息

  message HelloReply {

    string message = 1;

  }

 

gRPC 使用 protoc 和一个特殊的 gRPC 插件来从你的 proto 文件中生成代码:你会得到生成的 gRPC 客户端和服务器代码,以及用于补足、序列化和检索消息类型的常规协议缓冲区代码。

 

【协议缓冲区版本】

虽然协议缓冲区已经向开源用户提供了一段时间,目前推荐使用协议缓冲区3版(proto3),它的语法稍有简化,并添加了一些有用的新功能,而且支持了更多的语言。

Proto3目前支持JavaC++DartPythonObjective-CC#Android JavaRubyGolangJavaScript,,还有更多语言正在开发中。

 

一般来说,虽然可以使用proto2(当前默认的协议缓冲区版本),但建议你使用gRPC时使用proto3,因为它支持gRPC目前支持的所有语言,同时也避免了proto2客户端与proto3服务器的兼容性问题,反之亦然。

 

【认证】

gRPC支持使用TLS和基于令牌的认证。与Google服务的连接必须使用TLS

 

gRPC设计的初衷是可以与各种认证机制一起工作,从而可以很容易地通过gRPC与其他系统对话。

 

gRPC还提供了一个简单的认证API,让您在创建通道或调用时提供所有必要的认证信息作为凭证。

 

凭证类型

凭证可以分为两种类型:

 

l  通道凭证,附加在通道上,如SSL凭证。

l  调用凭证,它附加到一个调用(或C++中的ClientContext)上。

 

你也可以在CompositeChannelCredentials中结合这些内容,例如,你可以为通道指定SSL的详细信息,并为通道上的每个呼叫指定呼叫凭证。CompositeChannelCredentials 将通道凭证和呼叫凭证关联起来,以创建一个新的通道凭证。其结果将在信道上的每一次呼叫中发送与组成的CallCredentials相关联的认证数据。

 

比如说,你可以从一个SSLCredentials和一个AccessTokenCredentials创建一个ChannelCredentials。当应用到一个Channel时,其结果将为这个通道上的每个呼叫发送相应的访问令牌。

 

单个CallCredentials也可以用CompositeCallCredentials组成。在呼叫中使用的CallCredentials将触发与两个CallCredentials相关联的认证数据的发送。

 

SSL/TLS

gRPC具有SSL/TLS集成功能,提倡使用SSL/TLS来验证服务器,并对客户端和服务器之间交换的所有数据进行加密。客户端可选择提供相互认证的证书机制。

使用客户端SSL/TLS

现在我们来看看Credentials是如何与我们支持的一种认证机制一起工作的。我们假定最简单的验证场景,客户端只想验证服务器并加密所有数据。这个例子是用C++语言编写的,但所有语言的API都是类似的。

 

// 创建一个默认的SSL ChannelCredentials对象。

auto channel_creds = grpc::SslCredentials(grpc::SslCredentialsOptions());

// 使用上一步中创建的凭证创建一个通道。

auto channel = grpc::CreateChannel(server_name, channel_creds);

// 在通道上创建一个存根。

std::unique_ptr<Greeter::Stubstub(Greeter::NewStub(channel));

// 在存根上进行实际的RPC调用。

grpc::Status s = stub->sayHello(&context, *request, response);

 

对于高级用例,如修改根CA或使用客户端证书,可以在传递给工厂方法的 SslCredentialsOptions 参数中设置相应的选项。

 

基于令牌的身份验证

gRPC提供了一个通用的机制,可以将基于元数据的凭证附加到请求和响应中。这种机制专门用于访问Google API服务。 一般来说,Google不允许没有SSL/TLS的连接,而且大多数gRPC语言实现也不会让你在未加密的通道上发送凭证。

 

使用基于谷歌令牌的身份验证

gRPC应用程序可以使用一个简单的API来创建一个在各种部署场景中与Google进行认证的凭证。例子:

 

auto creds = grpc::GoogleDefaultCredentials();

// 创建一个通道,存根并进行RPC调用(与上例的功能一样)

auto channel = grpc::CreateChannel(server_name, creds);

std::unique_ptr<Greeter::Stubstub(Greeter::NewStub(channel));

grpc::Status s = stub->sayHello(&context, *request, response);

 

这个通道凭证对象适用于使用服务账户的应用程序和在 Google Compute Engine (GCE) 中运行的应用程序。在前一种情况下,服务账户的私钥是从环境变量 GOOGLE_APPLICATION_CREDENTIALS 中命名的文件中加载的。这些密钥用于生成附加到相应通道上的每个出站RPC的承载令牌。

 

对于在 GCE 中运行的应用程序,可以在 VM 设置期间配置一个默认服务帐户和相应的 OAuth2 作用域。在运行时,该凭证处理与认证系统的通信,以获取OAuth2访问令牌,并将其附加到相应通道上的每个出站RPC上。

 

扩展gRPC以支持其他认证机制

凭证插件API允许开发人员插入自己的凭证类型。这些插件有:

l  MetadataCredentialsPlugin抽象类,它包含纯虚拟的GetMetadata方法,需要由开发者创建的子类来实现。

l  MetadataCredentialsFromPlugin函数,它从

MetadataCredentialsPlugin中创建一个CallCredentials

 

下面是一个简单的凭证插件的例子,它可以在自定义头中设置一个认证依据。

 

类实现:

class MyCustomAuthenticator : public grpc::MetadataCredentialsPlugin {

 public:

  MyCustomAuthenticator(const grpc::string& ticket) : ticket_(ticket) {}

 

  grpc::Status GetMetadata(

      grpc::string_ref service_urlgrpc::string_ref method_name,

      const grpc::AuthContext& channel_auth_context,

      std::multimap<grpc::stringgrpc::string>* metadataoverride {

    metadata->insert(std::make_pair("x-custom-auth-ticket", ticket_));

    return grpc::Status::OK;

  }

 

 private:

  grpc::string ticket_;

};

 

 

类调用:

auto call_creds = grpc::MetadataCredentialsFromPlugin(

    std::unique_ptr<grpc::MetadataCredentialsPlugin>(

        new MyCustomAuthenticator("super-secret-ticket")));

 

通过在核心层插入gRPC凭证实现,可以实现更深层次的集成。

 

更多例子

这些认证机制将适用于所有gRPC支持的语言。

 

Go

无加密或认证
客户端:

 

conn_ := grpc.Dial("localhost:50051", grpc.WithInsecure())

// 此处需要添加错误处理

client := pb.NewGreeterClient(conn)

// ...

 

服务器端:

 

s := grpc.NewServer()

lis_ := net.Listen("tcp""localhost:50051")

// 此处需要添加错误处理

s.Serve(lis)

 

使用服务器认证 SSL/TLS
客户端:

 

creds_ := credentials.NewClientTLSFromFile(certFile, "")

conn_ := grpc.Dial("localhost:50051", grpc.WithTransportCredentials(creds))

// 此处需要添加错误处理

client := pb.NewGreeterClient(conn)

// ...

 

服务器端:

 

creds_ := credentials.NewServerTLSFromFile(certFile, keyFile)

s := grpc.NewServer(grpc.Creds(creds))

lis_ := net.Listen("tcp""localhost:50051")

// 此处需要添加错误处理

s.Serve(lis)

 

使用谷歌认证

pool_ := x509.SystemCertPool()

// 此处需要添加错误处理

creds := credentials.NewClientTLSFromCert(pool, "")

perRPC_ := oauth.NewServiceAccountFromFile("service-account.json", scope)

conn_ := grpc.Dial(

    "greeter.googleapis.com",

    grpc.WithTransportCredentials(creds),

    grpc.WithPerRPCCredentials(perRPC),

)

// 此处需要添加错误处理

client := pb.NewGreeterClient(conn)

// ...

 

 

Ruby

无加密或认证

stub = Helloworld::Greeter::Stub.new('localhost:50051', :this_channel_is_insecure)

 

使用服务器认证 SSL/TLS

creds = GRPC::Core::ChannelCredentials.new(load_certs)  # load_certs通常加载一个CA根文件

stub = Helloworld::Greeter::Stub.new('myservice.example.com', creds)

 

使用谷歌认证

require 'googleauth'  # from http://www.rubydoc.info/gems/googleauth/0.1.0

...

ssl_creds = GRPC::Core::ChannelCredentials.new(load_certs)  # load_certs通常加载一个CA根文件

authentication = Google::Auth.get_application_default()

call_creds = GRPC::Core::CallCredentials.new(authentication.updater_proc)

combined_creds = ssl_creds.compose(call_creds)

stub = Helloworld::Greeter::Stub.new('greeter.googleapis.com', combined_creds)

 

 

C++

无加密或认证

auto channel = grpc::CreateChannel("localhost:50051"InsecureChannelCredentials());

std::unique_ptr<Greeter::Stubstub(Greeter::NewStub(channel));

...

 

使用服务器认证 SSL/TLS

auto channel_creds = grpc::SslCredentials(grpc::SslCredentialsOptions());

auto channel = grpc::CreateChannel("myservice.example.com", channel_creds);

std::unique_ptr<Greeter::Stubstub(Greeter::NewStub(channel));

...

 

使用谷歌认证

auto creds = grpc::GoogleDefaultCredentials();

auto channel = grpc::CreateChannel("greeter.googleapis.com", creds);

std::unique_ptr<Greeter::Stubstub(Greeter::NewStub(channel));

...

 

C#

无加密或认证

var channel = new Channel("localhost:50051"ChannelCredentials.Insecure);

var client = new Greeter.GreeterClient(channel);

...

 

使用服务器认证 SSL/TLS

var channelCredentials = new SslCredentials(File.ReadAllText("roots.pem"));  // Load a custom roots file.

var channel = new Channel("myservice.example.com"channelCredentials);

var client = new Greeter.GreeterClient(channel);

 

使用谷歌认证

using Grpc.Auth;  // Grpc.Auth NuGet包中获取

...

// 加载Google应用的默认凭证与公开信任的根。

var channelCredentials = await GoogleGrpcCredentials.GetApplicationDefaultAsync();

 

var channel = new Channel("greeter.googleapis.com"channelCredentials);

var client = new Greeter.GreeterClient(channel);

...

 

认证单个RPC调用

var channel = new Channel("greeter.googleapis.com"new SslCredentials());  // Use publicly trusted roots.

var client = new Greeter.GreeterClient(channel);

...

var googleCredential = await GoogleCredential.GetApplicationDefaultAsync();

var result = client.SayHello(requestnew CallOptions(credentialsgoogleCredential.ToCallCredentials()));

...

 

Python

无加密或认证

import grpc

import helloworld_pb2

 

channel = grpc.insecure_channel('localhost:50051')

stub = helloworld_pb2.GreeterStub(channel)

 

使用服务器认证 SSL/TLS
客户端:

import grpc

import helloworld_pb2

 

with open('roots.pem''rb'as f:

    creds = grpc.ssl_channel_credentials(f.read())

channel = grpc.secure_channel('myservice.example.com:443', creds)

stub = helloworld_pb2.GreeterStub(channel)

 

服务器端:

import grpc

import helloworld_pb2

from concurrent import futures

 

server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))

with open('key.pem''rb'as f:

    private_key = f.read()

with open('chain.pem''rb'as f:

    certificate_chain = f.read()

server_credentials = grpc.ssl_server_credentials( ( (private_key, certificate_chain), ) )

此处要将GreeterServicer添加到服务器

server.add_secure_port('myservice.example.com:443', server_credentials)

server.start()

 

 

使用JWT进行谷歌认证

import grpc

import helloworld_pb2

 

from google import auth as google_auth

from google.auth import jwt as google_auth_jwt

from google.auth.transport import grpc as google_auth_transport_grpc

 

credentials, _ = google_auth.default()

jwt_creds = google_auth_jwt.OnDemandCredentials.from_signing_credentials(

    credentials)

channel = google_auth_transport_grpc.secure_authorized_channel(

    jwt_creds, None'greeter.googleapis.com:443')

stub = helloworld_pb2.GreeterStub(channel)

 

使用Oauth2令牌进行谷歌认证

import grpc

import helloworld_pb2

 

from google import auth as google_auth

from google.auth.transport import grpc as google_auth_transport_grpc

from google.auth.transport import requests as google_auth_transport_requests

 

credentials, _ = google_auth.default(scopes=(scope,))

request = google_auth_transport_requests.Request()

channel = google_auth_transport_grpc.secure_authorized_channel(

    credentials, request, 'greeter.googleapis.com:443')

stub = helloworld_pb2.GreeterStub(channel)

 

Java

无加密或认证

        ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost"50051).usePlaintext(true).build();

        GreeterGrpc.GreeterStub stub = GreeterGrpc.newStub(channel);

 

使用服务器认证 SSL/TLS

Java中,建议使用OpenSSL

 

要在服务器上启用TLS,需要以PEM格式指定证书链和私钥。这样的私钥不应该使用密码。证书链中证书的顺序很重要:更具体地说,最上面的证书必须是主机CA,而最下面的证书必须是根CA。标准的TLS端口是443,但为了避免申请操作系统的额外权限,下面用的是8443

        Server server = ServerBuilder.forPort(8443)

        // 启用TLS

        .useTransportSecurity(certChainFile, privateKeyFile)

        .addService(TestServiceGrpc.bindService(serviceImplementation))

        .build();

    server.start();

 

如果客户端不知道发证机构,那么应该分别向NettyChannelBuilderOkHttpChannelBuilder提供一个正确配置的SSLContextSSLSocketFactory

在客户端,使用SSL/TLS的服务器认证大体是这样的:

        // 通过服务器认证 SSL/TLS

        ManagedChannel channel = ManagedChannelBuilder.forAddress("myservice.example.com"443).build();

        GreeterGrpc.GreeterStub stub = GreeterGrpc.newStub(channel);

 

        // 具有服务器认证SSL/TLS;自定义CA根证书;不适用于Android

        ManagedChannel channel = NettyChannelBuilder.forAddress("myservice.example.com"443)

                .sslContext(GrpcSslContexts.forClient().trustManager(new File("roots.pem")).build()).build();

        GreeterGrpc.GreeterStub stub = GreeterGrpc.newStub(channel);

 

使用谷歌认证

下面的代码片段显示了如何使用服务账户使用gRPC调用Google Cloud PubSub API。凭证是从存储在一个已知位置的密钥中加载的,或者通过检测应用程序运行在一个可以自动提供密钥的环境中,例如Google Compute Engine等,来加载。虽然这个例子是针对Google及其服务的,但类似的模式也可以适用于其他服务提供商。

        GoogleCredentials creds = GoogleCredentials.getApplicationDefault();

        ManagedChannel channel = ManagedChannelBuilder.forTarget("greeter.googleapis.com")

            .build();

        GreeterGrpc.GreeterStub stub = GreeterGrpc.newStub(channel)

            .withCallCredentials(MoreCallCredentials.from(creds));

 

Node.js

无加密或认证

var stub = new helloworld.Greeter('localhost:50051'grpc.credentials.createInsecure());

 

使用服务器认证 SSL/TLS

var ssl_creds = grpc.credentials.createSsl(root_certs);

var stub = new helloworld.Greeter('myservice.example.com'ssl_creds);

 

使用谷歌认证

// 使用谷歌认证

var GoogleAuth = require('google-auth-library'); // from https://www.npmjs.com/package/google-auth-library

...

var ssl_creds = grpc.credentials.createSsl(root_certs);

(new GoogleAuth()).getApplicationDefault(function(errauth) {

  var call_creds = grpc.credentials.createFromGoogleCredential(auth);

  var combined_creds = grpc.credentials.combineChannelCredentials(ssl_credscall_creds);

  var stub = new helloworld.Greeter('greeter.googleapis.com'combined_credentials);

});

 

使用Oauth2令牌(传统方法)进行谷歌认证

var GoogleAuth = require('google-auth-library'); // from https://www.npmjs.com/package/google-auth-library

...

var ssl_creds = grpc.Credentials.createSsl(root_certs); // load_certs通常加载一个CA根文件

var scope = 'https://www.googleapis.com/auth/grpc-testing';

(new GoogleAuth()).getApplicationDefault(function(errauth) {

  if (auth.createScopeRequired()) {

    auth = auth.createScoped(scope);

  }

  var call_creds = grpc.credentials.createFromGoogleCredential(auth);

  var combined_creds = grpc.credentials.combineChannelCredentials(ssl_credscall_creds);

  var stub = new helloworld.Greeter('greeter.googleapis.com'combined_credentials);

});

 

PHP

无加密或认证

$client = new helloworld\GreeterClient('localhost:50051', [

    'credentials' => Grpc\ChannelCredentials::createInsecure(),

]);

 

使用谷歌认证

function updateAuthMetadataCallback($context)

{

    $auth_credentials = ApplicationDefaultCredentials::getCredentials();

    return $auth_credentials->updateMetadata($metadata = [], $context->service_url);

}

$channel_credentials = Grpc\ChannelCredentials::createComposite(

    Grpc\ChannelCredentials::createSsl(file_get_contents('roots.pem')),

    Grpc\CallCredentials::createFromPlugin('updateAuthMetadataCallback')

);

$opts = [

  'credentials' => $channel_credentials

];

$client = new helloworld\GreeterClient('greeter.googleapis.com', $opts);

 

 

使用Oauth2令牌(传统方法)进行谷歌认证

// 需要设置环境变量 "GOOGLE_APPLICATION_CREDENTIALS "

$scope = "https://www.googleapis.com/auth/grpc-testing";

$auth = Google\Auth\ApplicationDefaultCredentials::getCredentials($scope);

$opts = [

  'credentials' => Grpc\Credentials::createSsl(file_get_contents('roots.pem'));

  'update_metadata' => $auth->getUpdateMetadataFunc(),

];

$client = new helloworld\GreeterClient('greeter.googleapis.com', $opts);

 

Dart

无加密或认证

final channel = new ClientChannel('localhost',

      port: 50051,

      options: const ChannelOptions(

          credentials: const ChannelCredentials.insecure()));

final stub = new GreeterClient(channel);

 

使用服务器认证 SSL/TLS

// 加载一个自定义的根文件。

final trustedRoot = new File('roots.pem').readAsBytesSync();

final channelCredentials =

    new ChannelCredentials.secure(certificates: trustedRoot);

final channelOptions = new ChannelOptions(credentials: channelCredentials);

final channel = new ClientChannel('myservice.example.com',

    options: channelOptions);

final client = new GreeterClient(channel);

 

使用谷歌认证

// 默认使用公开的信任根。

final channel = new ClientChannel('greeter.googleapis.com');

final serviceAccountJson =

     new File('service-account.json').readAsStringSync();

final credentials = new JwtServiceAccountAuthenticator(serviceAccountJson);

final client =

    new GreeterClient(channel, options: credentials.toCallOptions);

 

认证单个RPC调用

// 默认使用公开的信任根。

final channel = new ClientChannel('greeter.googleapis.com');

final client = new GreeterClient(channel);

...

final serviceAccountJson =

     new File('service-account.json').readAsStringSync();

final credentials = new JwtServiceAccountAuthenticator(serviceAccountJson);

final response =

    await client.sayHello(request, options: credentials.toCallOptions);

 

 

gRPC的应用场景】

gRPC非常适用于以下情况:

l  微服务--gRPC是为低延迟和高吞吐量通信而设计的。

l  点对点实时通信--gRPC对双向流的支持非常好,gRPC服务可以实时推送消息,无需轮询。

l  多语言环境--gRPC工具支持所有流行的开发语言,使gRPC成为多语言环境的最佳选择。

l  网络约束环境--gRPC消息采用Protobuf(一种轻量级消息格式)进行序列化。一个gRPC消息总是比同等的JSON消息小。

【应用现状】

许多公司都采用了gRPC,如SquareNetflixCoreOSDockerCockerCockroachDBCiscoJuniper Networks等。

 

开源项目u-bmc使用gRPC来取代IPMI201918日,Dropbox宣布,其SOA架构核心的RPC框架 "Courier "的下一个版本将迁移到基于gRPC的新架构上,主要原因是该框架与他们现有的定制的RPC框架可以很好地接轨。

 

小结

在我们的开发过程中,对于API技术的选取是一个重要的环节,相比HTTP API, 本文介绍了gRPC具有的独特优势,并从缓冲机制和认证两个重要方面对这门技术进行了学习,下面来看看它的缺点和对应的策略:

浏览器支持有限

在目前情况下,从浏览器中直接调用gRPC服务是不可能的,gRPC大量使用HTTP/2的功能,目前的浏览器不支持gRPC客户端所需要的网络请求控制能力。例如,浏览器不允许调用者使用HTTP/2,也不提供对底层HTTP/2帧的访问。

 

应对策略

gRPC-WebgRPC团队的一项附加支持技术,它在浏览器中提供有限的gRPC支持。

gRPC-Web由两部分组成:支持所有现代浏览器的JavaScript客户端和服务器上的gRPC-Web代理。通过客户端调用代理,代理再把gRPC请求转发到gRPC服务器上。

 

gRPC-Web并不支持gRPC的所有功能,比如不支持客户端流处理和双向流处理,对服务器流处理的支持也很有限。

 

传输内容人类不可读

HTTP API请求以文本形式发送,人类可以读取。

 

gRPC消息默认使用Protobuf进行编码。虽然Protobuf的发送和接收效率很高,但它的二进制格式并不是人类可以读取的。

 

Protobuf需要在.proto文件中指定消息的接口描述来正确地解序列化。需要额外的工具来分析Protobuf的线上有效载荷和手工编写请求。

 

应对策略

诸如服务器反射和gRPC命令行工具等功能可以帮助处理二进制Protobuf消息。此外,Protobuf消息支持与JSON格式的转换。内置的JSON转换,可以将Protobuf消息转换为人类可读的形式,这在调试时非常有用。

 


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。