REST与gRPC在Golang中的性能差异对比

REST与gRPC在Golang中的性能差异对比 标准 REST 服务器相对简单易懂且易于部署运行,但实现相同功能的 gRPC 服务器在与网页和 PostgreSQL 通信时却显得复杂且充满障碍。关于 gRPC 的知识似乎也很有限,至少缺乏简明易懂的指导资料。

我试图理解各个组件如何协同工作,但至今仍未完全掌握。这样的理解正确吗?

grpc

我的问题是:

  1. 花费时间用 gRPC 替换标准 REST 是否值得?
  2. 是否存在像这样的实时对比:https://imagekit.io/demo/http2-vs-http1
  3. 目前使用 gRPC 的人多吗?
  4. gRPC 还有哪些其他优势?

更多关于REST与gRPC在Golang中的性能差异对比的实战教程也可以访问 https://www.itying.com/category-94-b0.html

19 回复

那么要从网站访问Postgresql,你推荐使用标准的REST吗?

更多关于REST与gRPC在Golang中的性能差异对比的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


gRPC 和一般的 RPC 架构为微服务提供了更精细的访问控制,使服务能够直接通信,而不是通过 JSON 或类似方式。通常,您会将其用于不向第三方公开的内部服务通信。而 REST 服务通常面向第三方开发者的公共使用。

Dave_Courtois:

我认为Globular正是你需要的

使用gRPC会有性能提升吗?有人这么告诉我,但在使用JSON和网页方面没有"证据"。

许多人声称可以通过使用gRPC网关将JSON转换为protobuf来使用gRPC,从而加快通信速度。但我想知道有多少人在Web开发中结合使用gRPC与SQL数据库进行通信?您的动机是什么?这样做有什么好处?

Sibert:

我在谷歌上搜索了好几周,但很少找到使用gRPC实现Web到SQL的真实案例。

嘿Sibert,能否详细说明一下你的问题?如果我的理解正确,gRPC要求所有通信方都使用协议缓冲区。我之前不知道可以在数据库中定义/使用protobuf!

性能提升将仅限于应用程序的数据传输部分。我认为大部分优化可以在查询优化层面实现。例如避免使用字符串作为键,优先使用整型。同时尽量避免使用LIKE操作符。还要避免动态查询生成,这类查询无法被数据库系统优化。创建视图来代替复杂的查询(包含大量JOIN和CONDITION),这样数据库系统就能优化您的查询。您的用户是需要一次性获取所有数据,还是只需要前1000条记录呢…

Dave_Courtois:

获取数据的方式(SQL查询)可能是影响性能的一个因素……序列化/反序列化过程非常消耗资源!请尽可能避免这些操作。如果使用SQL作为JSON对象的后端存储,可以考虑切换到MongoDB,它在这方面有很好的优化……

我们正在使用Postgresql且没有其他选择。使用Postgresql和gRPC能带来多少性能提升?

ouanixi:

Sibert,能否详细说明一下你的问题?如果我没理解错的话,gRPC要求所有通信方都使用协议缓冲区。我之前不知道可以在数据库中定义/使用protobuf!

我也在寻找相关的工作原理说明,所以才提出这个问题。在我看来,目前使用gRPC替代REST服务器的人并不多。即便有人这么做,他们也无法用简单易懂的方式向我解释清楚。

我认为Globular正是您需要的 https://github.com/davecourtois/Globular。它能让你轻松使用gRpc-web,提供Linux和Windows平台的二进制文件,并且已提供经过测试的SQL、LDAP、SMTP、持久化(MongoDB)、存储(levelDB、BigCache)等服务。我在工作中使用它,运行效果非常出色!

我鼓励大家都来使用并分享新的服务!-)

回到我之前提到的内容,如果应用程序扩展并引入多个服务,gRPC 和 Protocol Buffers 将成为内部服务通信的理想选择,但这仍取决于具体使用场景。

如果涉及两个服务之间的二进制通信,毫无疑问我应该使用 gRPC。这似乎非常明显,而且我觉得它相当简单。

但我的问题是关于从 Web 到 PostgreSQL 的通信。在实际应用中,有多少人使用过 gRPC 来处理这种情况,并能分享你们的经验?

我在谷歌上搜索了好几周,但很少找到使用 gRPC 实现 Web 到 SQL 通信的实际案例。

allurefx:

现在它拥有一个使用 TypeScript 代码的 Angular 客户端,可以向 Envoy 反向代理发送 gRPC-Web 请求,该代理将请求传递给 gRPC Python 服务器和 Redis 数据库。

嗯,我尝试安装 Envoy,但需要 Docker。基本上你需要四个(4)服务器:Web 服务器、Envoy 服务器、gRPC 服务器,最后是 Postgresql 服务器。你注意到这种设置带来了显著的速度提升吗?

除此之外,从 gRPC 服务器到 Postgresql 服务器是否存在“模拟”通信?

我最近将我的婚恋交友网站 https://matchtowed.com 从 REST 架构切换到了 gRPC。现在该网站使用 Angular 客户端,通过 TypeScript 代码发送 gRPC-Web 请求到 Envoy 反向代理,该代理将请求转发至 gRPC Python 服务器和 Redis 数据库。你无需发送需要在服务端进行映射的 JSON 数据,而是实现了从客户端到服务端的全程 protobuf 传输,因此可能不存在你所说的开销问题。目前我正在用 Flutter/Dart 客户端和 Go 服务端进行重写,而切换到 gRPC 也是一个过渡步骤。虽然这个过程不如 REST 那么简单便捷,但我认为在我的应用场景下这样的投入是值得的。

是的,你会面临许多新的动态组件、配置文件的超级挑剔等等,因此从简单的REST客户端/服务器设置过渡可能会相当令人沮丧。但是,一旦你设置完成,实际上会感到解放,因为一切变得模块化,易于分部分开发/修复/发布等等。你知道,我们正在讨论微服务设置的优缺点。例如,我现在正在将GRPC服务器从Python改为Go,而不担心其余设置,并且我计划仅将机器学习部分(TensorFlow)运行在单独的Python服务中等等。也就是说,整个系统变得非常灵活,正如我所说,解放了。

关于性能,我的客户端和服务器之间的消息很小,因此我不确定是否有明显的性能提升,尽管客户端确实感觉更敏捷。一个额外的好处(我非常喜欢)是,使用GRPC,你无法在浏览器的开发者控制台中理解网络请求/响应,而使用REST,一切通常都是明文可见的。

Dave_Courtois:

我认为大部分性能提升可以通过查询优化来实现。

我对查询优化有所了解。这不是我的问题。

我的问题是使用gRPC的优势在何时以及如何体现? 是Web与API之间的通信——还是API与Postgresql之间的通信?

具体来说,在从网页访问Postgresql服务器获取数据时,使用gRPC的优势体现在哪里?最终的性能提升是否值得?

Dave_Courtois:

性能提升只会体现在应用程序的数据传输部分。

能否进一步解释这一点?具体是什么数据在什么之间传输?

gRpc使用protobuffer进行序列化,而REST使用JSON。JSON简单、易读、易解析且应用广泛。但在性能方面,它远远落后于protobuffer。protobuffer通过使用二进制格式进行了大量优化,从而占用更少空间。这里有一个关于JSON与Protobuf对比的链接: https://auth0.com/blog/beating-json-performance-with-protobuf

获取数据的方式(SQL查询)也可能是影响性能的一个因素…序列化/反序列化循环非常消耗资源!请尽量避免它们。如果您使用SQL作为JSON对象的后端,可以考虑切换到MongoDB,它非常适用于这种用途…

如果您感兴趣,可以尝试使用Globular,那里已经有一个SQL服务和一个示例…

// The service configuration 
globularConfig.IP = "127.0.0.1" // remove it when the site is publish.

// The global service object.
var globular = new Globular()

/**
 * The main entry point.
 */
function main() {
    // testEcho("Hello globular!");

    // Sql test.
    //  testCreateSqlConnection();

    // testSelectQuery()

    // testGetFileInfo()

    // testCreatePersistenceConnection()

此文件已被截断。显示原文

如果我查看页面顶部的架构图,我推测您希望让Web应用程序能够访问SQL数据。无论是JSON/REST还是gRPC方案,您都需要通过TCP/IP连接将服务器与PostgreSQL相连。

在REST API方案中,服务器将是Web服务器(nginx、IIS、Apache) [PostgreSQL] <----- (TCP/IP) ---- [Web服务器] <---- (REST/JSON) ----- [浏览器]

在gRPC-Web方案中,服务器是用您选择的语言编写的微服务。以下是关于代理层的更多信息。(https://github.com/improbable-eng/grpc-web/tree/master/go/grpcwebproxy)

[PostgreSQL] <----- (TCP/IP) ---- [微服务] <---- (gRPC-Web) <----- [代理] <----- [浏览器]

此处的优势在于浏览器与微服务之间的传输环节。

嗯,某种程度上是这样。

正如@CurtGreen所说,RPC在内部服务通信中很有用,而REST更常用于客户端与服务之间的通信。

举个例子,假设有一个基本的微服务架构,包含两个服务:注册服务和邮件发送服务。

客户端(网站)会向注册服务的REST端点发送包含邮箱和密码的请求,注册服务会尝试创建用户。如果成功,注册服务可以通过RPC通知邮件服务向注册用户发送邮件。

我最近注意到一些较新的Google SDK似乎使用RPC与Google服务进行通信。

以下是一些可能对你有用的资源。

图片

grpc.io

图片

gRPC动机与设计原则

一个高性能、开源、通用的RPC框架,优先考虑移动设备和HTTP/2。

图片

Google Cloud Blog

图片

REST与RPC:你试图通过API解决什么问题?| Google…

仙女环是在林地或草原上自然形成的蘑菇圈。在民间传说中,仙女环具有魔法属性。

许多人声称可以通过gRPC网关将JSON转换为protobuf来使用gRPC,从而使通信更快。但我想知道有多少人在结合Web使用gRPC与SQL数据库进行通信?您的动机是什么?有哪些好处?

我认为这就像任何技术一样。大多数技术都相当不错,并且能很好地完成它们的工作,一切都取决于使用场景。

您需要根据您的使用场景权衡利弊。例如,如果您的应用程序只需要能够读写SQL数据库的端点,那么简单的JSON REST API可能就完全足够,无需增加RPC层的复杂性。

回到我之前提到的,如果您的应用程序扩展并且需要引入多个服务,那么gRPC和Protocol Buffers将是内部服务通信的绝佳选择,但这仍然取决于使用场景。

与JSON相比,Protocol Buffers具有一些非常引人注目的优势,特别是在类型和序列化速度方面。但我预计RPC网关(请不要引用我的话)在任何情况下都会将JSON反序列化,然后序列化为Protocol Buffer,这可能会给您的应用程序带来不必要的额外开销。

有许多公司在大规模使用gRPC,例如谷歌和Netflix。如果您四处看看,会发现一些有趣的文章,详细介绍了公司如何在其服务中使用gRPC。

https://www.cncf.io/netflix-case-study/

Medium

负载下的性能

Netflix的自适应并发限制

阅读时间:5分钟

BugSnag

博客

模板中的内容

在Golang中,REST和gRPC的性能差异主要源于协议和序列化方式。以下是针对你问题的技术分析:

  1. 性能基准对比: gRPC使用HTTP/2和Protocol Buffers,在数据传输效率和并发处理上优于基于HTTP/1.1和JSON的REST。测试显示,gRPC的吞吐量通常比REST高30-50%,延迟降低20-40%。

示例代码:

// gRPC服务端
type server struct{ pb.UnimplementedGreeterServer }

func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
    return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil
}

// REST服务端
func helloHandler(w http.ResponseWriter, r *http.Request) {
    json.NewEncoder(w).Encode(map[string]string{"message": "Hello World"})
}
  1. 实时性能对比: 虽然没有完全相同的实时演示,但可以通过基准测试展示差异:
// gRPC基准测试
func BenchmarkGRPC(b *testing.B) {
    conn, _ := grpc.Dial("localhost:50051", grpc.WithInsecure())
    client := pb.NewGreeterClient(conn)
    for i := 0; i < b.N; i++ {
        client.SayHello(context.Background(), &pb.HelloRequest{Name: "test"})
    }
}

// REST基准测试
func BenchmarkREST(b *testing.B) {
    for i := 0; i < b.N; i++ {
        http.Get("http://localhost:8080/hello")
    }
}
  1. 采用情况: gRPC在微服务架构和云原生应用中广泛使用,Google、Netflix等公司大量使用gRPC进行服务间通信。

  2. 额外优势

  • 双向流式通信:
// gRPC流式示例
func (s *server) StreamData(stream pb.DataService_StreamDataServer) error {
    for {
        data, err := stream.Recv()
        if err == io.EOF { return stream.SendAndClose(&pb.Response{}) }
        // 处理数据
    }
}
  • 自动生成客户端代码
  • 强类型接口定义
  • 多语言支持

在需要高性能、低延迟的内部服务通信场景中,gRPC的复杂度投入是值得的。对于对外API或简单CRUD操作,REST可能更合适。

回到顶部