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

专业搭建网站公司凡客诚品网站

专业搭建网站公司,凡客诚品网站,法与家国建设征文网站,个人网站建设维护在本文中#xff0c;您将学习如何实现通过 gRPC 通信的 Spring Boot 应用程序。gRPC 是一个现代开源远程过程调用 (RPC) 框架#xff0c;可以在任何环境中运行。默认情况下#xff0c;它使用 Google 的 Protocol Buffer 来序列化和反序列化结构化数据。当然#xff0c;我们…在本文中您将学习如何实现通过 gRPC 通信的 Spring Boot 应用程序。gRPC 是一个现代开源远程过程调用 (RPC) 框架可以在任何环境中运行。默认情况下它使用 Google 的 Protocol Buffer 来序列化和反序列化结构化数据。当然我们也可以切换为其他数据格式例如JSON。为了简化我们对 gRPC 和 Spring Boot 的探索我们将为此使用专用的启动器gRPC Spring Boot starter。 由于 gRPC 和 Spring Boot 之间的集成没有官方支持的启动器因此我们将选择最流行的第三方项目。它在GitHub上有大约 3100 颗星。您可以在此处找到有关其功能的详细文档。 源代码 如果您想自己尝试一下可以随时查看我的源代码。为此您需要克隆我的 GitHub 存储库。它包含四个应用程序。其中两个account-service与customer-service我之前的文章相关该文章介绍了 Java 中的 Protocol Buffers。当前文章请参考另外两个appaccount-service-grpc和customer-service-grpc。它们与相应的应用程序非常相似但使用我们的第三方 Spring Boot 和 gRPC 通信而不是 REST。另外他们需要使用 Spring Boot 2因为我们的第三方启动器仍然不支持 Spring Boot 3。无论如何一旦您克隆了存储库只需按照我的说明操作即可! 为 gRPC 生成模型类和服务 第一步我们将使用.proto清单生成模型类和 gRPC 服务。我们需要包含一些额外的 Protobuf 模式才能使用google.protobuf.*包**(1)。我们的 gRPC 服务将提供使用各种条件搜索帐户的方法以及添加新帐户的单一方法(2)。这些方法将使用文件google.protobuf.*中定义的包和模型类中的原.proto语作为消息。定义了两条消息。该Account消息代表单个模型类。它包含三个字段id、number和customer_id (3)。该消息包含对象Accounts列表(4)**。Account syntax proto3;package model;option java_package pl.piomin.services.grpc.account.model; option java_outer_classname AccountProto;// (1) import empty.proto; import wrappers.proto;// (2) service AccountsService {rpc FindByNumber(google.protobuf.StringValue) returns (Account) {}rpc FindByCustomer(google.protobuf.Int32Value) returns (Accounts) {}rpc FindAll(google.protobuf.Empty) returns (Accounts) {}rpc AddAccount(Account) returns (Account) {} }// (3) message Account {int32 id 1;string number 2;int32 customer_id 3; }// (4) message Accounts {repeated Account account 1; }您可能还记得有两个示例 Spring Boot 应用程序。让我们看一下.proto第二个应用程序的架构customer-service-grpc。它比之前的定义稍微复杂一些。我们的 gRPC 服务还将提供多种用于搜索对象的方法和一种用于添加新客户的方法**(1)。正在customer-service-grpc与应用程序通信account-service-grpc因此我们需要生成Account消息Accounts( 2)。当然您可以使用生成的 Protobuf 类创建一个额外的接口模块并在我们的两个示例应用程序之间共享它。最后我们必须定义我们的模型类。该类Customer包含三个原始字段id, pesel, name, 枚举type以及分配给特定客户的帐户列表(3)**。还有Customers包含对象列表Customer(4) 的消息。 syntax proto3;package model;option java_package pl.piomin.services.grpc.customer.model; option java_outer_classname CustomerProto;import empty.proto; import wrappers.proto;// (1) service CustomersService {rpc FindByPesel(google.protobuf.StringValue) returns (Customer) {}rpc FindById(google.protobuf.Int32Value) returns (Customer) {}rpc FindAll(google.protobuf.Empty) returns (Customers) {}rpc AddCustomer(Customer) returns (Customer) {} }// (2) message Account {int32 id 1;string number 2;int32 customer_id 3; }message Accounts {repeated Account account 1; }// (3) message Customer {int32 id 1;string pesel 2;string name 3;CustomerType type 4;repeated Account accounts 5;enum CustomerType {INDIVIDUAL 0;COMPANY 1;} }// (4) message Customers {repeated Customer customers 1; }为了从.proto模式生成 Java 类我们将使用 Maven 插件。您可以使用一些可用的插件来实现这一点。我的选择落在了protoc-jar-maven-plugin插件上。在配置中我们需要将 .proto 架构的默认位置覆盖为src/main/proto. 我们还需要.proto使用includeDirectories标签包含在清单中使用的其他 Protobuf 模式。这些清单位于src/main/proto-imports目录内。输出目标目录为src/main/generated. 默认情况下该插件不生成 gRPC 服务。为了启用它我们需要在类型outputTarget中包含grpc-java。为了生成类我们将使用该protoc-gen-grpc-java库。 plugingroupIdcom.github.os72/groupIdartifactIdprotoc-jar-maven-plugin/artifactIdversion3.11.4/versionexecutionsexecutionphasegenerate-sources/phasegoalsgoalrun/goal/goalsconfigurationaddProtoSourcesall/addProtoSourcesincludeMavenTypesdirect/includeMavenTypesoutputDirectorysrc/main/generated/outputDirectoryinputDirectoriesincludesrc/main/proto/include/inputDirectoriesincludeDirectoriesincludesrc/main/proto-imports/include/includeDirectoriesoutputTargetsoutputTargettypejava/typeoutputDirectorysrc/main/generated/outputDirectory/outputTargetoutputTargettypegrpc-java/typepluginArtifactio.grpc:protoc-gen-grpc-java:1.57.2/pluginArtifact outputDirectorysrc/main/generated/outputDirectory/outputTarget/outputTargets/configuration/execution/executions /plugin我们还将src/main/generated使用 Maven 插件将生成的 Java 代码附加到源目录下build-helper-maven-plugin。 plugingroupIdorg.codehaus.mojo/groupIdartifactIdbuild-helper-maven-plugin/artifactIdexecutionsexecutionidadd-source/idphasegenerate-sources/phasegoalsgoaladd-source/goal/goalsconfigurationsourcessourcesrc/main/generated/source/sources/configuration/execution/executions /plugin一旦执行mvn clean package命令Maven 将生成所需的 Java 类。account-service-grpc这是生成 Java 类后应用程序中的最终目录结构。 $ tree . ├── pom.xml └── src├── main│ ├── generated│ │ └── pl│ │ └── piomin│ │ └── services│ │ └── grpc│ │ └── account│ │ └── model│ │ ├── AccountProto.java│ │ └── AccountsServiceGrpc.java│ ├── java│ │ └── pl│ │ └── piomin│ │ └── services│ │ └── grpc│ │ └── account│ │ ├── AccountApplication.java│ │ ├── repository│ │ │ └── AccountRepository.java│ │ └── service│ │ └── AccountsService.java│ ├── proto│ │ └── account.proto│ ├── proto-imports│ │ ├── empty.proto│ │ └── wrappers.proto│ └── resources└── test└── java└── pl└── piomin└── services└── grpc└── account└── AccountServicesTests.java使用 gRPC Spring Boot 启动器 一旦我们生成了所需的 Protobuf 模型类和 gRPC 存根我们就可以继续实施。第一步我们需要包含以下 Spring Boot 启动器 dependencygroupIdnet.devh/groupIdartifactIdgrpc-server-spring-boot-starter/artifactIdversion2.14.0.RELEASE/version /dependency然后我们必须创建gRPC服务实现类。AccountsServiceImplBase它需要根据声明扩展生成.proto。GrpcService 我们还需要用(1)注释整个类。之后我们将重写通过 gRPC 公开的所有方法。我们的服务使用一个简单的内存存储库(2)。每个方法都提供一个参数对象和io.grpc.stub.StreamObserver用于以反应方式返回响应的类**(3)** (4)。 GrpcService // (1) public class AccountsService extends AccountsServiceGrpc.AccountsServiceImplBase {AutowiredAccountRepository repository; // (2)Overridepublic void findByNumber(StringValue request, StreamObserverAccountProto.Account responseObserver) { // (3)AccountProto.Account a repository.findByNumber(request.getValue());responseObserver.onNext(a); # (4)responseObserver.onCompleted();}Overridepublic void findByCustomer(Int32Value request, StreamObserverAccountProto.Accounts responseObserver) {ListAccountProto.Account accounts repository.findByCustomer(request.getValue());AccountProto.Accounts a AccountProto.Accounts.newBuilder().addAllAccount(accounts).build();responseObserver.onNext(a);responseObserver.onCompleted();}Overridepublic void findAll(Empty request, StreamObserverAccountProto.Accounts responseObserver) {ListAccountProto.Account accounts repository.findAll();AccountProto.Accounts a AccountProto.Accounts.newBuilder().addAllAccount(accounts).build();responseObserver.onNext(a);responseObserver.onCompleted();}Overridepublic void addAccount(AccountProto.Account request, StreamObserverAccountProto.Account responseObserver) {AccountProto.Account a repository.add(request.getCustomerId(), request.getNumber());responseObserver.onNext(a);responseObserver.onCompleted();} }这是AccountRepository实现 public class AccountRepository {ListAccountProto.Account accounts;AtomicInteger id;public AccountRepository(ListAccountProto.Account accounts) {this.accounts accounts;this.id new AtomicInteger();this.id.set(accounts.size());}public ListAccountProto.Account findAll() {return accounts;}public ListAccountProto.Account findByCustomer(int customerId) {return accounts.stream().filter(it - it.getCustomerId() customerId).toList();}public AccountProto.Account findByNumber(String number) {return accounts.stream().filter(it - it.getNumber().equals(number)).findFirst().orElseThrow();}public AccountProto.Account add(int customerId, String number) {AccountProto.Account a AccountProto.Account.newBuilder().setId(id.incrementAndGet()).setCustomerId(customerId).setNumber(number).build();return a;}}我们在启动时添加一些测试数据。这是我们的应用程序主类 SpringBootApplication public class AccountApplication {public static void main(String[] args) {SpringApplication.run(AccountApplication.class, args);}BeanAccountRepository repository() {ListAccountProto.Account accounts new ArrayList();accounts.add(AccountProto.Account.newBuilder().setId(1).setCustomerId(1).setNumber(111111).build());accounts.add(AccountProto.Account.newBuilder().setId(2).setCustomerId(2).setNumber(222222).build());accounts.add(AccountProto.Account.newBuilder().setId(3).setCustomerId(3).setNumber(333333).build());accounts.add(AccountProto.Account.newBuilder().setId(4).setCustomerId(4).setNumber(444444).build());accounts.add(AccountProto.Account.newBuilder().setId(5).setCustomerId(1).setNumber(555555).build());accounts.add(AccountProto.Account.newBuilder().setId(6).setCustomerId(2).setNumber(666666).build());accounts.add(AccountProto.Account.newBuilder().setId(7).setCustomerId(2).setNumber(777777).build());return new AccountRepository(accounts);} }在启动应用程序之前我们还将包含 Spring Boot Actuator 以公开一些与 gRPC 相关的指标。我们将在与 gRPC 服务不同的端口下公开因此我们还需要包含 Spring Boot Web starter dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId /dependency dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-actuator/artifactId /dependency在application.yml文件中我们应该启用metrics端点 spring.application.name: account-service-grpcmanagement.endpoints.web.exposure.include: metrics management.endpoint.metrics.enabled: true默认情况下gRPC服务在该端口下可用9090。我们可以使用该grpc.server.port属性覆盖该数字。将端口设置为 0 使用空闲的随机端口。让我们开始我们的示例应用程序 调用gRPC服务 我们可以使用grpcurlCLI 工具来调用示例应用程序公开的 gRPC 服务。9090 默认情况下gRPC 服务器将在端口使用 模式下启动 PLAINTEXT 。为了打印可用服务的列表我们需要执行以下命令 $ grpcurl --plaintext localhost:9090 list grpc.health.v1.Health grpc.reflection.v1alpha.ServerReflection model.AccountsService然后让我们打印 所公开的方法列表model.AccountService $ grpcurl --plaintext localhost:9090 list model.AccountsService model.AccountsService.AddAccount model.AccountsService.FindAll model.AccountsService.FindByCustomer model.AccountsService.FindByNumber我们还可以使用describe命令中的关键字打印有关每个方法的详细信息 $ grpcurl --plaintext localhost:9090 describe model.AccountsService.FindByNumber model.AccountsService.FindByNumber is a method: rpc FindByNumber ( .google.protobuf.StringValue ) returns ( .model.Account );现在让我们调用上面可见的命令所描述的端点。我们的方法的名称是model.AccountsService.FindByNumber。我们还使用111111值设置输入字符串参数。 $ grpcurl --plaintext -d 111111 localhost:9090 model.AccountsService.FindByNumber {id: 1,number: 111111,customer_id: 1 }之后我们就可以看一下model.AccountsService.FindByNumbergRPC方法了。它接受一个整数作为输入参数并返回一个对象列表。 $ grpcurl --plaintext -d 1 localhost:9090 model.AccountsService.FindByCustomer {account: [{id: 1,number: 111111,customer_id: 1},{id: 5,number: 555555,customer_id: 1}] }最后我们就可以调用添加新账户的方法了。它以 JSON 对象作为输入参数。然后它将返回一个新创建的Account带有增量id字段的对象。 $ grpcurl --plaintext -d {customer_id: 6, number: 888888} localhost:9090 model.AccountsService.AddAccount {id: 8,number: 888888,customer_id: 6 }gRPC Spring Boot 启动器向执行器添加了三个附加指标。 我们可以显示每个 gRPC 方法的请求数量。这是该方法的请求和响应FindByNumber。 我们还可以显示每种方法的平均处理时间如下所示。 测试 gRPC 服务 在上一节中我们使用 CLI 工具手动运行应用程序并测试 gRPC 服务grpcurl。不过我们也可以基于Spring Boot Test模块来实现单元或集成测试。我们将为我们的应用程序与 gRPC 客户端创建集成测试。为此我们需要在 Maven 中包含以下三个依赖项pom.xml dependencygroupIdio.grpc/groupIdartifactIdgrpc-testing/artifactIdversion1.51.0/versionscopetest/scope /dependency dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scope /dependency dependencygroupIdnet.devh/groupIdartifactIdgrpc-client-spring-boot-starter/artifactIdversion2.14.0.RELEASE/versionscopetest/scope /dependency在下面可见的测试实现中我们需要启用“进程内”服务器**(1)并禁用外部服务器(2)**。然后我们必须配置客户端连接到“进程内服务器” (3)。我们将使用 Maven 构建期间已生成的 gRPC 客户端。它可以作为AccountsServiceBlockingStub类使用。我们只需使用GrpcClient (4)对其进行正确注入和注释。之后我们可以使用客户端存根来调用我们的 gRPC 服务(5)。 SpringBootTest(properties {grpc.server.inProcessNametest, // (1)grpc.server.port-1, // (2)grpc.client.inProcess.addressin-process:test // (3) }) DirtiesContext public class AccountServicesTests {GrpcClient(inProcess) // (4)AccountsServiceGrpc.AccountsServiceBlockingStub service;Testvoid shouldFindAll() {AccountProto.Accounts a service.findAll(Empty.newBuilder().build()); // (5)assertNotNull(a);assertFalse(a.getAccountList().isEmpty());}Testvoid shouldFindByCustomer() {AccountProto.Accounts a service.findByCustomer(Int32Value.newBuilder().setValue(1).build());assertNotNull(a);assertFalse(a.getAccountList().isEmpty());}Testvoid shouldFindByNumber() {AccountProto.Account a service.findByNumber(StringValue.newBuilder().setValue(111111).build());assertNotNull(a);assertNotEquals(0, a.getId());}Testvoid shouldAddAccount() {AccountProto.Account a AccountProto.Account.newBuilder().setNumber(123456).setCustomerId(10).build();a service.addAccount(a);assertNotNull(a);assertNotEquals(0, a.getId());}}以下是我们的测试结果 gRPC 微服务之间的通信 在本节中我们将切换到customer-service-grpc应用程序。与之前的应用程序相同我们需要使用 Maven 命令生成类和 gRPC 服务存根mvn clean package。服务实现也与account-service-grpc. 不过这一次我们使用客户端来调用外部 gRPC 方法。下面是 的实现GrpcService。如您所见我们注入AccountClientbean然后使用它来调用account-service-grpc应用程序**(1)公开的 gRPC 方法。然后我们使用客户端 bean 查找分配给特定客户的帐户(2)**。 GrpcService public class CustomersService extends CustomersServiceGrpc.CustomersServiceImplBase {AutowiredCustomerRepository repository;AutowiredAccountClient accountClient; // (1)Overridepublic void findById(Int32Value request, StreamObserverCustomerProto.Customer responseObserver) {CustomerProto.Customer c repository.findById(request.getValue());CustomerProto.Accounts a accountClient.getAccountsByCustomerId(c.getId()); // (2)ListCustomerProto.Account l a.getAccountList();c CustomerProto.Customer.newBuilder(c).addAllAccounts(l).build();responseObserver.onNext(c);responseObserver.onCompleted();}Overridepublic void findByPesel(StringValue request, StreamObserverCustomerProto.Customer responseObserver) {CustomerProto.Customer c repository.findByPesel(request.getValue());responseObserver.onNext(c);responseObserver.onCompleted();}Overridepublic void findAll(Empty request, StreamObserverCustomerProto.Customers responseObserver) {ListCustomerProto.Customer customerList repository.findAll();CustomerProto.Customers c CustomerProto.Customers.newBuilder().addAllCustomers(customerList).build();responseObserver.onNext(c);responseObserver.onCompleted();}Overridepublic void addCustomer(CustomerProto.Customer request, StreamObserverCustomerProto.Customer responseObserver) {CustomerProto.Customer c repository.add(request.getType(), request.getName(), request.getPesel());responseObserver.onNext(c);responseObserver.onCompleted();} }现在我们来看看该类的实现AccountClient。我们使用生成的客户端存根来调用外部 gRPC 方法**(1)**。请注意注释内的值。这是我们客户的名字。 Service public class AccountClient {private static final Logger LOG LoggerFactory.getLogger(AccountClient.class);GrpcClient(account-service-grpc) // (1)AccountsServiceGrpc.AccountsServiceBlockingStub stub;public CustomerProto.Accounts getAccountsByCustomerId(int customerId) {try {return stub.findByCustomer(Int32Value.newBuilder().setValue(customerId).build());} catch (final StatusRuntimeException e) {LOG.error(Error in communication, e);return null;}} }我们需要做的最后一件事是提供目标服务的地址。幸运的是gRPC Spring Boot 支持使用 Spring Cloud 进行服务发现。我们将使用 Eureka 作为发现服务器。因此我们的两个示例应用程序都需要包含 Spring Cloud Eureka 客户端。 dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-netflix-eureka-client/artifactId /dependency我们还需要添加包含我们使用的 Spring Cloud 版本的dependencyManagement部分。pom.xml dependencyManagementdependenciesdependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-dependencies/artifactIdversion2021.0.8/versiontypepom/typescopeimport/scope/dependency/dependencies /dependencyManagement为了避免与端口冲突account-service-grpc我们将覆盖默认的 gRPC 和 HTTP执行器端口。我们还需要为GrpcClient. 首先我们应该与类GrpcClient中注释中设置的名称相同AccountClient。客户端通过明文协议进行通信并根据字段中设置的名称从发现服务器读取目标服务的地址discovery:///。 server.port: 8081 grpc.server.port: 9091grpc:client:account-service-grpc:address: discovery:///account-service-grpcenableKeepAlive: truekeepAliveWithoutCalls: truenegotiationType: plaintext最后我们可以运行发现服务器和两个示例微服务。Eureka 服务器可在我们的存储库中的 discovery-server 目录中找到。运行后您可以转到http://localhost:8761地址下可用的 UI 仪表板。 然后运行我们的两个示例 Spring Boot gRPC 微服务。您可以使用以下 Maven 命令运行所有应用程序 $ mvn spring-boot:run最后我们来调用customer-service-grpc与 通信的方法account-service-grpc。grpcurl我们再次使用该工具。正如您所看到的它返回对象内的帐户列表Customer 最后的想法 gRPC Spring Boot Starter 提供了一些有用的功能来简化开发人员的工作。我们可以轻松地使用 来创建服务GrpcService使用 来创建客户端GrpcClient或者将 gRPC 与 Spring Boot Actuator 指标和 Spring Cloud 发现集成。然而也存在一些缺点。该库的开发不是很积极。每年大概有2-3个版本发布目前还没有对Spring Boot 3的支持。 更多Spring Boot 3文章https://www.jdon.com/tag-34038/
http://www.dnsts.com.cn/news/218127.html

相关文章:

  • 苏州网站建设方案外包常宁网站
  • 网站域名备案变更wordpress纯文本
  • 做网站维护的是什么公司中天建设集团有限公司西南分公司
  • 钓鱼网站链接怎么做网站如何做软文推广
  • 谈谈对电子商务网站建设与管理室内设计图制作软件
  • 余姚做网站公司购物网站排名榜
  • 网站 百度地图太原seo按天计费
  • 扬州哪里做网站店铺位置怎么免费注册定位
  • 河北建站公司北京建设厅网站
  • 农家乐网站 建设哪些人不适合学平面设计
  • 重庆排名优化整站优化免费seo在线工具
  • 网站建设 统一质量标准wordpress放谷歌代码
  • 公司网站推广计划书怎么做python语言入门
  • 葫芦岛市住房和城乡建设局网站制作自己的网站教程
  • 网站备案换ipwordpress 分类全文
  • 网上做代销上哪个网站莱芜新闻主持人名单
  • 池州商城网站开发郑州seo优化顾问阿亮
  • 单位建设网站硬件安徽省建设质量安全协会网站
  • 网站开发的一般过程小程序开发教程
  • 广州市建设工程定额管理网站wordpress 敏感词过滤
  • 欧美平面设计网站网络服务的服务提供者包括( )
  • 石岩网站建设手机在线logo免费设计
  • 知名高端网站建设报价阿里云网站域名证书
  • 个人音乐网站开发新手怎么样学做网站
  • 淄博网站建设推广优化如何衡量一个网站的价值
  • 企业为什么选择网站建设网站举报多久有结果
  • 微信微网站统计怎么做类似淘宝一样的网站吗
  • 做盗版电影网站赚钱龙岗网站建设公司怎么样
  • 重庆企业网站的推广西部数码网站助手4.0
  • 网站建设谈单思路手机网页代码