gRPC 介绍

gRPC(Google Remote Procedure Call)是一种高性能、跨语言的远程过程调用(RPC)框架,基于 HTTP/2 传输协议,使用 Protocol Buffers(Protobuf) 作为序列化协议,适用于微服务架构、高并发系统和跨语言调用场景。

核心特性

  1. 高性能
    • 使用 HTTP/2 作为底层协议,支持多路复用,减少网络延迟。
    • 采用 Protobuf 作为数据格式,比 JSON、XML 等更高效。
  2. 跨语言
    • 支持 Java、Go、Python、C++、C#、Node.js、Ruby、PHP、Dart 等多种编程语言
  3. 自动生成客户端/服务端代码
    • 通过 Protobuf 定义服务接口,自动生成 gRPC 客户端和服务端代码,提高开发效率。
  4. 支持双向流
    • 除了普通的请求-响应(Unary)调用,gRPC 还支持:
      • 服务器流式(Server Streaming)
      • 客户端流式(Client Streaming)
      • 双向流式(Bidirectional Streaming)
  5. 内置负载均衡和认证
    • gRPC 内置 负载均衡(可结合 Consul、Etcd、Kubernetes)。
    • 支持 TLS 加密,提供 身份验证OAuth 认证。
  6. 与 Kubernetes & 微服务生态集成
    • 天然支持 Kubernetes、Istio 等微服务架构。

基本开发流程

1. 定义 Protobuf 文件

.proto 文件定义服务和消息格式:

syntax = "proto3";

package example;

// 定义一个 gRPC 服务
service Greeter {
  // 定义一个 RPC 方法
  rpc SayHello (HelloRequest) returns (HelloReply);
}

// 请求消息
message HelloRequest {
  string name = 1;
}

// 响应消息
message HelloReply {
  string message = 1;
}

2. 生成 gRPC 代码

使用 protoc 命令生成对应语言的代码:

protoc --java_out=. --grpc-java_out=. example.proto

(根据不同语言配置相应的 protoc 插件)

3. 实现服务端

public class GreeterServiceImpl extends GreeterGrpc.GreeterImplBase {
    @Override
    public void sayHello(HelloRequest request, StreamObserver<HelloReply> responseObserver) {
        HelloReply reply = HelloReply.newBuilder()
                                     .setMessage("Hello, " + request.getName())
                                     .build();
        responseObserver.onNext(reply);
        responseObserver.onCompleted();
    }
}

4. 实现客户端

public class GreeterClient {
    public static void main(String[] args) {
        ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 50051)
                                                      .usePlaintext()
                                                      .build();
        GreeterGrpc.GreeterBlockingStub stub = GreeterGrpc.newBlockingStub(channel);

        HelloRequest request = HelloRequest.newBuilder().setName("gRPC User").build();
        HelloReply response = stub.sayHello(request);

        System.out.println(response.getMessage());
        channel.shutdown();
    }
}

调用类型

调用方式客户端请求服务器响应适用场景
Unary RPC1 个请求1 个响应标准请求-响应模式
Server Streaming RPC1 个请求多个响应服务器主动推送数据
Client Streaming RPC多个请求1 个响应需要批量提交数据
Bidirectional Streaming RPC多个请求多个响应双向实时交互

gRPC vs REST

对比项gRPCREST (HTTP/JSON)
传输协议HTTP/2HTTP/1.1
数据格式Protobuf(二进制)JSON(文本)
性能高效(小体积、低延迟)相对较慢(大数据包)
双向流支持不支持
浏览器兼容需要 gRPC-Web 代理原生支持

适用场景

微服务架构:适用于 Kubernetes、Istio 体系
实时通信:如 IM、游戏服务器、流媒体
跨语言系统:支持多种编程语言
高性能 API:比 REST 更高效,适合低延迟、高吞吐应用

不适用于:
❌ 需要直接在 Web 浏览器访问的场景(需要 gRPC-Web 代理)
❌ 对可读性要求高的 API(如开放 API,一般更适合 REST)

总结

gRPC 是一种高性能、跨语言的 RPC 框架,特别适用于微服务和高吞吐系统。如果你的业务场景对性能要求高,并且需要支持多语言交互,gRPC 是一个很好的选择。🚀

gRPC 搭配 nacos

演示如何将 gRPCNacos 结合在一起实现微服务的通信与服务注册发现,我们将创建一个简单的示例,包括:

  • 一个 gRPC 服务端,它会将自己的服务信息注册到 Nacos
  • 一个 gRPC 客户端,它会从 Nacos 获取服务地址并调用服务。

实现 gRPC 服务端

创建一个 HelloServiceImpl,实现 HelloService 的方法,并注册到 Nacos。
src/main/java/com/example/grpc/server/HelloServiceImpl.java

package com.example.grpc.server;

import hello.HelloRequest;
import hello.HelloResponse;
import hello.HelloServiceGrpc;
import io.grpc.stub.StreamObserver;
import org.springframework.stereotype.Service;

@Service
public class HelloServiceImpl extends HelloServiceGrpc.HelloServiceImplBase {

    @Override
    public void sayHello(HelloRequest request, StreamObserver<HelloResponse> responseObserver) {
        String name = request.getName();
        HelloResponse response = HelloResponse.newBuilder()
                .setMessage("Hello, " + name)
                .build();
        responseObserver.onNext(response);
        responseObserver.onCompleted();
    }
}

注册服务到 Nacos

服务端启动时,注册服务到 Nacos 注册中心。
src/main/java/com/example/grpc/server/GrpcServerApplication.java

package com.example.grpc.server;

import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.NamingFactory;
import io.grpc.Server;
import io.grpc.ServerBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class GrpcServerApplication implements CommandLineRunner {

    @Value("${nacos.server-addr}")
    private String nacosServerAddr;

    public static void main(String[] args) {
        SpringApplication.run(GrpcServerApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        // Start gRPC server
        Server server = ServerBuilder.forPort(50051)
                .addService(new HelloServiceImpl())
                .build();

        server.start();
        System.out.println("gRPC Server started on port 50051");

        // Register the service with Nacos
        NamingService namingService = NamingFactory.createNamingService(nacosServerAddr);
        namingService.registerInstance("HelloService", "127.0.0.1", 50051);

        server.awaitTermination();
    }
}

实现 gRPC 客户端

客户端会从 Nacos 获取服务地址并调用远程服务。
src/main/java/com/example/grpc/client/GrpcClientApplication.java

package com.example.grpc.client;

import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.NamingFactory;
import hello.HelloRequest;
import hello.HelloResponse;
import hello.HelloServiceGrpc;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.stub.StreamObserver;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class GrpcClientApplication implements CommandLineRunner {

    public static void main(String[] args) {
        SpringApplication.run(GrpcClientApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        // Get service instance address from Nacos
        NamingService namingService = NamingFactory.createNamingService("127.0.0.1:8848");
        String serviceAddr = namingService.getAllInstances("HelloService").get(0).getIp() + ":50051";

        // Create a gRPC channel
        ManagedChannel channel = ManagedChannelBuilder.forTarget(serviceAddr)
                .usePlaintext()
                .build();

        // Create a blocking stub
        HelloServiceGrpc.HelloServiceBlockingStub stub = HelloServiceGrpc.newBlockingStub(channel);

        // Call the service
        HelloRequest request = HelloRequest.newBuilder().setName("World").build();
        HelloResponse response = stub.sayHello(request);

        System.out.println("Received response: " + response.getMessage());

        channel.shutdown();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值