当前位置: 首页 > wzjs >正文

网站 标签导航怎么制作微信小程序

网站 标签导航,怎么制作微信小程序,做动态的网站,重庆未来科技网站建设在前几篇文章中,我们已经掌握了 Protobuf 的基础语法、高级特性和序列化反序列化操作。本篇文章将深入讲解 gRPC 与 Protobuf 的集成,重点介绍如何通过 .proto 文件定义服务接口,并在 Go 和 Java 中实现 gRPC 服务与客户端的完整交互流程。我…

在前几篇文章中,我们已经掌握了 Protobuf 的基础语法、高级特性和序列化反序列化操作。本篇文章将深入讲解 gRPC 与 Protobuf 的集成,重点介绍如何通过 .proto 文件定义服务接口,并在 Go 和 Java 中实现 gRPC 服务与客户端的完整交互流程。我们将通过详细代码示例分步解析,帮助你彻底掌握微服务架构中的通信设计。


一、gRPC 简介与核心概念

1. 什么是 gRPC?

gRPC 是一个高性能、开源的远程过程调用(RPC)框架,基于 HTTP/2 协议Protobuf 数据格式 构建。它支持多种语言,并提供了同步/异步调用流式通信等特性。

2. gRPC 的核心优势

特性描述
高效通信基于二进制协议(Protobuf),比 JSON 更快、更小
多语言支持支持 Go、Java、Python、C++、Rust 等
双向流式通信支持客户端/服务端流式数据传输
自动代码生成通过 .proto 文件自动生成客户端和服务端代码
强大的工具链提供调试工具(如 grpcurl)、插件系统

二、通过 .proto 定义 gRPC 服务

1. 示例 .proto 文件

syntax = "proto3";package user;//新版本有了下面的option go_package 这里的pacage就可以去掉了(当然留着也不影响)
option go_package = "/user;user"; // 指定生成的 Go 包路径(生成源码的路径和包名,前面是路径后面是包名,可以自己定义)
//option go_package = ".;user"; //这个可以生成在当前目录下// 定义服务接口
service UserService {// 1. 单向调用(Unary RPC)rpc GetUser (GetUserRequest) returns (UserResponse);// 2. 服务端流式调用(Server Streaming)rpc ListUsers (ListUsersRequest) returns (stream UserResponse);// 3. 客户端流式调用(Client Streaming)rpc CreateUsers (stream CreateUserRequest) returns (CreateUsersResponse);// 4. 双向流式调用(Bidirectional Streaming)rpc UpdateUsers (stream UpdateUserRequest) returns (stream UserResponse);
}// 消息定义
message GetUserRequest {int32 id = 1;
}message UserResponse {int32 id = 1;string name = 2;string email = 3;
}message ListUsersRequest {string filter = 1;
}message CreateUserRequest {string name = 1;string email = 2;
}message CreateUsersResponse {int32 count = 1;
}message UpdateUserRequest {int32 id = 1;string name = 2;
}

要注意下面这里有了变化(以后会讲解为什么要用option go_package): 

package user;//新版本有了下面的option go_package 这里的pacage就可以去掉了(当然留着也不影响)

option go_package = "/user;user"; // 指定生成的 Go 包路径(生成源码的路径和包名,前面是路径后面是包名,可以自己定义)
//option go_package = ".;user"; //这个可以生成在当前目录下
 


三、生成 gRPC 代码

1. 安装 gRPC 工具

go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
Java
protoc --java_out=. \--grpc-java_out=. \--plugin=protoc-gen-grpc-java=protoc-gen-grpc-java \user.proto

2. 生成代码命令

Go
protoc --go_out=. --go-grpc_out=. user.proto
Java
protoc --java_out=. --grpc-java_out=. user.proto

四、Go 实现 gRPC 服务端与客户端

1. 服务端代码详解

package mainimport ("context""fmt""log""net"pb "./user_go_proto""google.golang.org/grpc"
)type userService struct {pb.UnimplementedUserServiceServer
}// 单向调用
func (s *userService) GetUser(ctx context.Context, req *pb.GetUserRequest) (*pb.UserResponse, error) {return &pb.UserResponse{Id:    req.Id,Name:  "Alice",Email: "alice@example.com",}, nil
}// 服务端流式调用
func (s *userService) ListUsers(req *pb.ListUsersRequest, stream pb.UserService_ListUsersServer) error {users := []*pb.UserResponse{{Id: 1, Name: "Alice", Email: "alice@example.com"},{Id: 2, Name: "Bob", Email: "bob@example.com"},}for _, user := range users {if err := stream.Send(user); err != nil {return err}}return nil
}// 客户端流式调用
func (s *userService) CreateUsers(stream pb.UserService_CreateUsersServer) error {count := 0for {req, err := stream.Recv()if err == io.EOF {break}if err != nil {return err}count++}return stream.SendAndClose(&pb.CreateUsersResponse{Count: int32(count)})
}// 双向流式调用
func (s *userService) UpdateUsers(stream pb.UserService_UpdateUsersServer) error {for {req, err := stream.Recv()if err == io.EOF {break}if err != nil {return err}resp := &pb.UserResponse{Id:   req.Id,Name: req.Name,}if err := stream.Send(resp); err != nil {return err}}return nil
}func main() {lis, err := net.Listen("tcp", ":50051")if err != nil {log.Fatalf("failed to listen: %v", err)}s := grpc.NewServer()pb.RegisterUserServiceServer(s, &userService{})log.Printf("Server listening at %v", lis.Addr())if err := s.Serve(lis); err != nil {log.Fatalf("failed to serve: %v", err)}
}
代码解析
  • 服务端实现:通过 pb.RegisterUserServiceServer 注册服务。
  • 流式处理:通过 stream 接口处理双向通信。
  • 错误处理:捕获 io.EOF 结束流式调用。

2. 客户端代码详解

package mainimport ("context""fmt""log"pb "./user_go_proto""google.golang.org/grpc"
)func main() {conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure())if err != nil {log.Fatalf("did not connect: %v", err)}defer conn.Close()client := pb.NewUserServiceClient(conn)// 单向调用resp, err := client.GetUser(context.Background(), &pb.GetUserRequest{Id: 1})if err != nil {log.Fatalf("could not get user: %v", err)}fmt.Printf("User: %v\n", resp)// 服务端流式调用stream, err := client.ListUsers(context.Background(), &pb.ListUsersRequest{Filter: "IT"})if err != nil {log.Fatalf("could not list users: %v", err)}for {user, err := stream.Recv()if err == io.EOF {break}if err != nil {log.Fatalf("error receiving user: %v", err)}fmt.Printf("Received: %v\n", user)}// 客户端流式调用stream2, err := client.CreateUsers(context.Background())if err != nil {log.Fatalf("could not create users: %v", err)}for i := 0; i < 3; i++ {if err := stream2.Send(&pb.CreateUserRequest{Name:  fmt.Sprintf("User %d", i),Email: fmt.Sprintf("user%d@example.com", i),}); err != nil {log.Fatalf("error sending user: %v", err)}}resp2, err := stream2.CloseAndRecv()if err != nil {log.Fatalf("error closing stream: %v", err)}fmt.Printf("Created %d users\n", resp2.Count)// 双向流式调用stream3, err := client.UpdateUsers(context.Background())if err != nil {log.Fatalf("could not update users: %v", err)}for i := 0; i < 3; i++ {if err := stream3.Send(&pb.UpdateUserRequest{Id:   int32(i),Name: fmt.Sprintf("Updated User %d", i),}); err != nil {log.Fatalf("error sending update: %v", err)}resp3, err := stream3.Recv()if err != nil {log.Fatalf("error receiving update: %v", err)}fmt.Printf("Updated: %v\n", resp3)}
}
代码解析
  • 连接建立:通过 grpc.Dial 连接服务端。
  • 流式调用:通过 stream.Send() 和 stream.Recv() 实现双向通信。
  • 错误处理:捕获 io.EOF 结束流式调用。

五、Java 实现 gRPC 服务端与客户端

1. 服务端代码详解

import user.UserServiceGrpc;
import user.GetUserRequest;
import user.UserResponse;
import user.ListUsersRequest;
import user.CreateUserRequest;
import user.CreateUsersResponse;
import user.UpdateUserRequest;import io.grpc.Server;
import io.grpc.ServerBuilder;
import io.grpc.stub.StreamObserver;import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;public class UserServiceServer {public static void main(String[] args) throws IOException, InterruptedException {final Server server = ServerBuilder.forPort(50051).addService(new UserServiceImpl()).build();server.start();System.out.println("Server started at port 50051");final CountDownLatch latch = new CountDownLatch(1);server.awaitTermination();}static class UserServiceImpl extends UserServiceGrpc.UserServiceImplBase {// 单向调用@Overridepublic void getUser(GetUserRequest request, StreamObserver<UserResponse> responseObserver) {UserResponse response = UserResponse.newBuilder().setId(request.getId()).setName("Alice").setEmail("alice@example.com").build();responseObserver.onNext(response);responseObserver.onCompleted();}// 服务端流式调用@Overridepublic void listUsers(ListUsersRequest request, StreamObserver<UserResponse> responseObserver) {UserResponse user1 = UserResponse.newBuilder().setId(1).setName("Alice").setEmail("alice@example.com").build();UserResponse user2 = UserResponse.newBuilder().setId(2).setName("Bob").setEmail("bob@example.com").build();responseObserver.onNext(user1);responseObserver.onNext(user2);responseObserver.onCompleted();}// 客户端流式调用@Overridepublic StreamObserver<CreateUserRequest> createUsers(StreamObserver<CreateUsersResponse> responseObserver) {return new StreamObserver<>() {int count = 0;@Overridepublic void onNext(CreateUserRequest request) {count++;}@Overridepublic void onError(Throwable throwable) {throwable.printStackTrace();}@Overridepublic void onCompleted() {CreateUsersResponse response = CreateUsersResponse.newBuilder().setCount(count).build();responseObserver.onNext(response);responseObserver.onCompleted();}};}// 双向流式调用@Overridepublic StreamObserver<UpdateUserRequest> updateUsers(StreamObserver<UserResponse> responseObserver) {return new StreamObserver<>() {@Overridepublic void onNext(UpdateUserRequest request) {UserResponse response = UserResponse.newBuilder().setId(request.getId()).setName(request.getName()).build();responseObserver.onNext(response);}@Overridepublic void onError(Throwable throwable) {throwable.printStackTrace();}@Overridepublic void onCompleted() {responseObserver.onCompleted();}};}}
}
代码解析
  • 服务端实现:通过继承 UserServiceGrpc.UserServiceImplBase 实现接口。
  • 流式处理:通过 StreamObserver 处理双向通信。
  • 错误处理:通过 onError 捕获异常。

2. 客户端代码详解

import user.UserServiceGrpc;
import user.GetUserRequest;
import user.UserResponse;
import user.ListUsersRequest;
import user.CreateUserRequest;
import user.CreateUsersResponse;
import user.UpdateUserRequest;import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.StatusRuntimeException;import java.util.concurrent.TimeUnit;public class UserServiceClient {public static void main(String[] args) {ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 50051).usePlaintext().build();UserServiceGrpc.UserServiceBlockingStub blockingStub = UserServiceGrpc.newBlockingStub(channel);// 单向调用GetUserRequest request = GetUserRequest.newBuilder().setId(1).build();try {UserResponse response = blockingStub.getUser(request);System.out.println("User: " + response.getName());} catch (StatusRuntimeException e) {e.printStackTrace();}// 服务端流式调用ListUsersRequest listRequest = ListUsersRequest.newBuilder().setFilter("IT").build();UserServiceGrpc.UserServiceStub asyncStub = UserServiceGrpc.newStub(channel);asyncStub.listUsers(listRequest, new StreamObserver<>() {@Overridepublic void onNext(UserResponse user) {System.out.println("Received: " + user.getName());}@Overridepublic void onError(Throwable throwable) {throwable.printStackTrace();}@Overridepublic void onCompleted() {System.out.println("Stream completed.");}});// 客户端流式调用UserServiceGrpc.UserServiceStub createStub = UserServiceGrpc.newStub(channel);createStub.createUsers(new StreamObserver<>() {@Overridepublic void onNext(CreateUsersResponse response) {System.out.println("Created " + response.getCount() + " users");}@Overridepublic void onError(Throwable throwable) {throwable.printStackTrace();}@Overridepublic void onCompleted() {System.out.println("Create stream completed.");}}).forEachRemaining(user -> {if (user != null) {System.out.println("Sending: " + user.getName());}});// 双向流式调用UserServiceGrpc.UserServiceStub updateStub = UserServiceGrpc.newStub(channel);StreamObserver<UpdateUserRequest> requestStream = updateStub.updateUsers(new StreamObserver<>() {@Overridepublic void onNext(UserResponse response) {System.out.println("Updated: " + response.getName());}@Overridepublic void onError(Throwable throwable) {throwable.printStackTrace();}@Overridepublic void onCompleted() {System.out.println("Update stream completed.");}});for (int i = 0; i < 3; i++) {UpdateUserRequest updateRequest = UpdateUserRequest.newBuilder().setId(i).setName("Updated User " + i).build();requestStream.onNext(updateRequest);}requestStream.onCompleted();try {channel.shutdownNow().awaitTermination(5, TimeUnit.SECONDS);} catch (InterruptedException e) {e.printStackTrace();}}
}
代码解析
  • 连接建立:通过 ManagedChannelBuilder 连接服务端。
  • 流式调用:通过 StreamObserver 实现双向通信。
  • 错误处理:通过 onError 捕获异常。

六、多语言交互的最佳实践

1. 保持 .proto 文件统一

  • 所有语言共享同一个 .proto 文件,确保接口定义一致。
  • 使用 protoc 生成对应语言的代码。

2. 版本控制

  • 在 .proto 文件中添加版本注释:
    // Version 1.0.0
    message User {string name = 1;
    }

3. 依赖管理

  • 使用 go mod 或 Maven 管理依赖,确保不同语言的代码版本一致。

注意:

这篇文章中使用的Go和Java 实现 gRPC 服务端与客户端的例子是二者分开用的,而不是混合语言,其实在这里我更想做的是Go和Java放在一起使用,比如Go做服务端,Java做客户端。原因是我觉得Go更适合grpc,所以大家着重看Go的讲解即可。如果要混合的话也是以Go为主,Java为辅。

这次没有使用多语言的原因是,突然混合在一起的话怕大家不好理解,我在其他文章中也有讲解跨语言使用的例子,大家有兴趣的可以去看看。


七、总结

在本文中,我们详细讲解了 gRPC 与 Protobuf 的深度集成,包括:

  1. 通过 .proto 文件定义服务接口
  2. 在 Go 和 Java 中实现服务端与客户端
  3. 单向、流式通信的完整代码示例
  4. 多语言交互的最佳实践

通过这些内容,你已经能够构建高性能、可扩展的微服务系统,并在不同语言之间实现无缝通信。gRPC 与 Protobuf 的结合是现代分布式系统的基石,希望这篇文章能帮助你更自信地在项目中应用这些技术。

http://www.dtcms.com/wzjs/194554.html

相关文章:

  • ps软件下载免费win7优化配置的方法
  • 张家港 网站制作广州seo工资
  • 免费的网站后台管理系统广州广告公司
  • 做网站建设业务员怎么样网站建设的推广渠道
  • 重庆网站seo建设百度贴吧的互动社区
  • 英文网站建设知识公众号运营
  • 社交网站开发教程搜索引擎大全全搜网
  • 廊坊seo管理河南网站优化排名
  • 中国东凤网站制作武汉搜索推广
  • php网站建设系统深圳竞价托管
  • 做公司网站费用线下推广方式都有哪些
  • 凡科网做网站株洲seo快速排名
  • 静态网站开发 内容黄页引流推广网站入口
  • 有没有做兼职的网站吗软件排名工具
  • 布吉做棋牌网站建设哪家公司便宜深圳产品网络推广
  • 河北建设厅录入业绩的网站国外媒体报道
  • 客户在我这做的网站被罚百度推广和优化有什么区别
  • wordpress 下载远程图片大小国外seo大神
  • 长沙市建设发展集团有限公司网站今日短新闻20条
  • wordpress如何删除主题seo怎么发文章 seo发布工具
  • java + jsp 如何做门户网站北京seo优化推广
  • 酒店网站建设研究小程序开发工具
  • 做网站建设与推广企业网站快速排名案例
  • 运用vs2010c 做网站整站seo排名要多少钱
  • 外贸建站有哪些公司能让手机流畅到爆的软件
  • 单位如何做网站宣传浏览器老是出现站长工具
  • 崇信县网站留言西安网是科技发展有限公司
  • 用dw做的网站怎么发到网上电商网络推广
  • 什么网站能看男女做暧广告推广免费
  • 苏州网站seo公司百度一下首页登录入口