高性能微服务架构:Spring Boot 集成 gRPC 实现用户与订单服务即时交互

news2024/11/18 15:36:31

gRPC 是一种由 Google 开发的高性能、开源的远程过程调用(Remote Procedure Call, RPC)框架。它允许在不同的计算机系统或进程之间进行通信,使得分布式系统和微服务架构中的服务之间能够轻松地相互调用方法。gRPC 基于 HTTP/2 协议,并使用 Protocol Buffers(Protobuf)作为其接口定义语言和序列化格式。

gRPC 的主要特点和优点:

  1. 跨语言支持
    gRPC 支持多种编程语言,包括 C++, Java, Python, Go, C#, Node.js 等,因此不同语言编写的服务之间可以无缝通信。

  2. 高性能
    gRPC 使用 HTTP/2 协议,这意味着它支持双向流、多路复用和头部压缩,能更高效地利用网络资源,降低延迟。

  3. 协议定义
    gRPC 使用 Protocol Buffers 作为其接口定义语言(IDL)。开发者通过定义 .proto 文件,描述服务和消息结构,gRPC 工具可以自动生成对应语言的客户端和服务器端代码。

  4. 简单易用
    gRPC 提供了一套简洁的 API,开发者可以轻松创建和调用远程服务,就像调用本地方法一样。

  5. 双向流和流控
    gRPC 不仅支持传统的一次性请求-响应模型,还支持双向流,使得客户端和服务器之间可以发送多个消息,并且这些消息可以并行地传输和处理。

  6. 安全性
    gRPC 原生支持 SSL/TLS,可以很容易地实现安全的通信。

gRPC 的应用场景:

  1. 微服务架构
    在微服务架构中,服务之间需要进行大量的通信,gRPC 提供了高效、跨语言的解决方案,适用于需要低延迟和高吞吐量的应用。

  2. 分布式系统
    在分布式系统中,多个节点之间可能需要频繁通信,gRPC 的高性能和双向流支持非常适合这种场景。

  3. 实时通信
    gRPC 的双向流特性使其非常适合需要实时数据交换的应用,例如实时聊天、视频流、物联网(IoT)应用等。

  4. 跨平台服务
    由于 gRPC 支持多种语言和平台,它非常适合构建跨平台的分布式服务。

总结来说,gRPC 是一种高效、灵活的远程调用框架,特别适合需要跨语言、高性能通信的分布式系统和微服务架构。

一个常见的 gRPC 使用实例是在微服务架构中,尤其是像 Uber 这样的公司,它们拥有多个微服务,需要在不同的服务之间进行高效、低延迟的通信。

需求:用户服务和订单服务的通信

假设有一个电商平台,它的系统由多个微服务组成,其中包括:

  1. 用户服务(User Service):管理用户信息,如注册、登录、个人资料等。
  2. 订单服务(Order Service):处理用户的订单信息,如创建订单、查询订单状态等。
  3. grpc-api:将 gRPC 的 Protobuf 定义提取到一个独立的 grpc-api 模块中,其他微服务(如用户服务和订单服务)可以引用该模块,共享 gRPC 定义和生成的代码。

用户在下订单时,订单服务需要验证用户的身份,并获取用户的相关信息(如地址、支付方式等)。在这种情况下,订单服务需要调用用户服务来获取这些信息。

模块的目录结构

├─grpc-api
│  └─src
│      └─main
│          ├─java
│          │  └─com
│          │      └─song
│          │          └─api
│          ├─proto
│          └─resources
├─grpc-order
│  └─src
│      └─main
│          ├─java
│          │  └─com
│          │      └─song
│          │          ├─service
│          │          └─web
│          └─resources
└─grpc-user
    └─src
        └─main
            ├─java
            │  └─com
            │      └─song
            │          └─service
            └─resources

1. 创建 grpc-api 模块

创建一个 Maven 项目 grpc-api,用于存放 .proto 文件和生成的 gRPC Java 代码。这个模块将被其他服务(如用户服务和订单服务)依赖。

2. 在 grpc-api 模块中定义 .proto 文件

grpc-api 模块的 src/main/proto/ 目录下创建 .proto 文件,例如:

syntax = "proto3";

package com.song.api;
// 创建一个rpc 服务
service UserService {
  rpc GetUserInfo (GetUserInfoRequest) returns (GetUserInfoResponse);
}
//方法的入参请求对象与入参 。参数必须有唯一标识并还是有顺序的
message GetUserInfoRequest {
  string user_id = 1;
}
//方法的响应请求对象与响应参数 。参数必须有唯一标识并还是有顺序的
message GetUserInfoResponse {
  string name = 1;
  string email = 2;
  string address = 3;
}

3. 配置 grpc-api 模块的 pom.xml

grpc-api 模块的 pom.xml 中,配置 gRPC 和 Protobuf 相关的依赖和插件,以便自动生成 gRPC 代码。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>yqmm-grpc</artifactId>
        <groupId>com.song</groupId>
        <version>1.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>grpc-api</artifactId>
    <description>grpc公共api提取</description>
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <grpc-version>1.40.1</grpc-version>
        <protobuf-version>3.21.9</protobuf-version>
    </properties>

    <dependencies>
        <!-- gRPC 依赖 -->
        <dependency>
            <groupId>io.grpc</groupId>
            <artifactId>grpc-all</artifactId>
            <version>${grpc-version}</version>
        </dependency>

        <dependency>
            <groupId>com.google.protobuf</groupId>
            <artifactId>protobuf-java</artifactId>
            <version>${protobuf-version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.google.protobuf/protoc -->
        <dependency>
            <groupId>com.google.protobuf</groupId>
            <artifactId>protoc</artifactId>
            <version>${protobuf-version}</version>
            <type>pom</type>
        </dependency>
    </dependencies>

    <build>
        <extensions>
            <extension>
                <groupId>kr.motd.maven</groupId>
                <artifactId>os-maven-plugin</artifactId>
            </extension>
        </extensions>
        <plugins>
            <plugin>
                <groupId>org.xolstice.maven.plugins</groupId>
                <artifactId>protobuf-maven-plugin</artifactId>
                <version>0.6.1</version>
                <configuration>
                    <protocArtifact>com.google.protobuf:protoc:3.19.1:exe:${os.detected.classifier}</protocArtifact>
                    <pluginId>grpc-java</pluginId>
                    <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.50.2:exe:${os.detected.classifier}</pluginArtifact>
                    <!-- 设置输出目录 -->
                    <outputDirectory>${project.basedir}/src/main/java</outputDirectory>
                    <!-- 设置proto文件所在目录 -->
                    <protoSourceRoot>${project.basedir}/src/main/proto</protoSourceRoot>
                    <!-- 是否清除输出目录 -->
                    <clearOutputDirectory>false</clearOutputDirectory>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <goal>compile-custom</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <layout>NONE</layout>
                    <skip>true</skip>           <!--    自己打出的包也能用 ,就是打出的包不包含BOOT-INF目录        -->
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

4. 生成 gRPC 代码

grpc-api 模块根目录下运行以下命令来生成 gRPC 代码:

mvn compile

或者
在这里插入图片描述

编译后,Protobuf 文件会被编译成 Java 类,生成的 gRPC 类会存放在 target/generated-sources/protobuf 目录中,并打包到 grpc-api 的 jar 文件中。

5. 创建用户服务模块

创建一个新的 Maven 模块(如 grpc-user),该模块将实现 gRPC 服务端,使用 grpc-api 共享的 gRPC 定义。

用户服务模块的 pom.xml

grpc-user 模块的 pom.xml 中,添加对 grpc-api 的依赖以及 gRPC 相关的依赖:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>yqmm-grpc</artifactId>
        <groupId>com.song</groupId>
        <version>1.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>grpc-user</artifactId>
    <description>服务端</description>
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <grpc-service-version>2.14.0.RELEASE</grpc-service-version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.song</groupId>
            <artifactId>grpc-api</artifactId>
            <version>1.1-SNAPSHOT</version>
        </dependency>
<!--        服务端-->
        <dependency>
            <groupId>net.devh</groupId>
            <artifactId>grpc-server-spring-boot-starter</artifactId>
            <version>${grpc-service-version}</version>
        </dependency>
    </dependencies>
</project>
实现 gRPC 服务

grpc-user 模块中,基于 grpc-api 中的生成代码实现 gRPC 服务端:

/**
 * 自定义数据查询  提供给客户端数据
 */
@GrpcService
@Slf4j
public class UserService extends UserServiceGrpc.UserServiceImplBase{


    @Override
    public void getUserInfo(User.GetUserInfoRequest request,
                            StreamObserver<User.GetUserInfoResponse> responseObserver) {
        log.info("客户端发来的请求参数UserId>>>>>>>{}",request.getUserId());
        // todo 客户端发来的请求参数UserId 查询数据库db
        // todo 模拟db返回出来的用户数据
        User.GetUserInfoResponse response = User.GetUserInfoResponse.newBuilder()
                .setName("song-name")
                .setEmail("song.com")
                .setAddress("北京")
                .build();

        responseObserver.onNext(response);
        responseObserver.onCompleted();
    }
}

配置:application.yml

grpc:
  server:
    port: 9190  # 设置 gRPC 服务器端口
server:
  port: 10002

spring:
  application:
    name: grpc-user

启动类


@SpringBootApplication
public class UserApplication {

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

6. 创建订单服务模块

同样,创建订单服务模块(如 grpc-order),该模块将作为 gRPC 客户端调用用户服务。

订单服务模块的 pom.xml

grpc-order 模块的 pom.xml 中,添加对 grpc-api 模块的依赖以及 gRPC 相关的依赖:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>yqmm-grpc</artifactId>
        <groupId>com.song</groupId>
        <version>1.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>grpc-order</artifactId>
    <description>客户端</description>
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <grpc-client-version>2.14.0.RELEASE</grpc-client-version>
    </properties>

    <dependencies>
<!--        客户端-->
        <dependency>
            <groupId>net.devh</groupId>
            <artifactId>grpc-client-spring-boot-starter</artifactId>
            <version>${grpc-client-version}</version>
        </dependency>
<!--        grpc-api -->
        <dependency>
            <groupId>com.song</groupId>
            <artifactId>grpc-api</artifactId>
            <version>1.1-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>
调用 gRPC 客户端

grpc-order 中,通过 gRPC 客户端调用用户服务获取用户信息:

@Service
public class UserClient {

    @GrpcClient("grpc-user") // yml里面指定访问服务端地址
    private UserServiceGrpc.UserServiceBlockingStub userServiceBlockingStub;



    public User.GetUserInfoResponse getUserInfo(String userId) {
        User.GetUserInfoRequest request = User.GetUserInfoRequest.newBuilder()
                .setUserId(userId)
                .build();
        return userServiceBlockingStub.getUserInfo(request);
    }
}
订单服务控制调用层

在订单服务中,可以使用 UserServiceClient 来获取用户信息并处理订单:

@RestController
public class OrderController {

    private final UserClient userClient;

    public OrderController(UserClient userClient) {
        this.userClient = userClient;
    }

    @GetMapping("/order")
    public String createOrder(@RequestParam String userId) {
        // 远程调用
        User.GetUserInfoResponse userInfo = userClient.getUserInfo(userId);
        // 处理订单逻辑
        return "为用户创建的订单:" + userInfo.getName()+userInfo.getAddress()+userInfo.getEmail();
    }
}

配置:application.yml

server:
  port: 10001

grpc:
  client:
    grpc-user: # 自定义服务名
      address: 'static://127.0.0.1:9190' # 调用 gRPC 的地址
      negotiation-type: plaintext # 明文传输
spring:
  application:
    name: grpc-order

启动类

@SpringBootApplication
public class OrderApplication {

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

7. 启动和运行微服务

确保用户服务和订单服务的端口配置正确,启动两个服务:

  • 启动用户服务,它会在指定的 gRPC 端口监听(如 9190)。
  • 启动订单服务,通过 gRPC 客户端调用用户服务来获取用户信息并处理订单。
    调用地址
    http://localhost:10001/order?userId=123
    在这里插入图片描述
    执行信息
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2136462.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

django-admin自定义功能按钮样式

位置在原来的django-admin 栏中的上方【会因为屏幕大小而变换位置】 <!-- 这里是不会替换掉旧的 添加按钮 &#xff0c;而是添加多一个按钮【点击Crawl Data】--> <!-- /home/luichun/lc/Pyfile/Pywebback/app/paqu/templates/admin/yourmodel_changelist.html -->…

基于k8s手动部署rabbitmq集群(Manually Deploying RabbitMQ Cluster Based on k8s)

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:Linux运维老纪的首页…

安全基础设施如何形成统一生态标准?OASA 硬件安全合作计划启动 | 2024 龙蜥大会

近日&#xff0c;2024 龙蜥操作系统大会&#xff08;OpenAnolis Conference&#xff09;在北京盛大召开。 与此同时&#xff0c;由龙蜥社区运营委员会副主席、龙腾计划生态负责人金美琴&#xff0c;阿里云智能集团高级技术专家张天佳&#xff0c;海光信息技术生态技术总监李伟&…

系统架构设计师教程 第5章 5.2需求工程 笔记

5.2 需求工程 ★★★★★ 软件需求是指用户对系统在功能、行为、性能、设计约束等方面的期望。 软件需求包括3个不同的层次&#xff1a;业务需求、用户需求和功能需求(也包括非功能需求)。 (1)业务需求 (business requirement) 反映了组织机构或客户对系统、产品高层次的目标…

用SpringBoot进行阿里云大模型接口调用同步方法和异步方法

同步效果就不展示了,这里展示更常用的异步,多轮异步流式效果展示如下: 结果内容组合 1、同步版本环境准备以及代码 需要开通阿里大模型服务,如果没有开通服务,单独的去生成 key 是无效的。 阿里云登录 - 欢迎登录阿里云,安全稳定的云计算服务平台 生成你需要的 key 1、…

PHP智慧家政同城服务家政系统小程序源码

智慧家政&#xff0c;同城服务新篇章 —— 探索家政系统的无限可能 开篇&#xff1a;走进智慧家政时代 在这个快节奏的生活中&#xff0c;每一分每一秒都显得尤为珍贵。当忙碌成为常态&#xff0c;如何让家成为真正的避风港&#xff1f;答案或许就藏在“智慧家政同城服务家政…

【JavaScript】数据结构之链表

什么是链表&#xff1f; 多个元素存储的列表链表中的元素在内存中不是顺序存储的&#xff0c;而是通过“next”指针联系在一起的&#xff0c;这个“next”可以自定义。JS中的原型链原理就是链表结构&#xff0c;是通过__proto__指针联系在一起的。 链表和数组的区别 数组是…

c++207 运算重载

调入 op #include<iostream> using namespace std;class Complex { public:int a;int b; public:Complex(int a 0, int b 0){this->a a;this->b b;}void printfCom(){cout << a << "" << b << "i" << endl…

Django视图:构建动态Web页面的核心技术

Django&#xff0c;作为一个强大的Python Web框架&#xff0c;提供了一套完整的工具来构建这些动态页面。在Django的架构中&#xff0c;视图&#xff08;Views&#xff09;是处理用户请求并生成响应的关键组件。本文将深入探讨Django视图的工作原理&#xff0c;以及如何使用它们…

科技与艺术完美融合的LED异形创意圆形(饼/盘)显示屏横空出世

随着LED技术的飞速发展&#xff0c;这款集科技与艺术于一体的异形创意圆形&#xff08;饼/盘&#xff09;显示屏&#xff0c;不仅以其独特的形态打破了传统显示屏的界限&#xff0c;更在视觉呈现上开启了前所未有的新篇章。它不再仅仅是信息传递的载体&#xff0c;而是成为了空…

外观模式详解:如何为复杂系统构建简洁的接口

&#x1f3af; 设计模式专栏&#xff0c;持续更新中 欢迎订阅&#xff1a;JAVA实现设计模式 &#x1f6e0;️ 希望小伙伴们一键三连&#xff0c;有问题私信都会回复&#xff0c;或者在评论区直接发言 外观模式 外观模式&#xff08;Facade Pattern&#xff09;为子系统中的一组…

AI重塑视觉体验:将图像与视频转化为逼真可编辑的3D虚拟场景

在这个数字化飞速发展的时代&#xff0c;AI技术正以前所未有的方式重塑我们的视觉体验。特别是当AI能够轻松将普通的照片和视频转化为高度逼真、可交互的3D虚拟场景时&#xff0c;它不仅简化了3D内容创作的复杂性&#xff0c;还极大地拓宽了应用场景的边界。今天&#xff0c;我…

医学数据分析实训 项目二 数据预处理作业

文章目录 项目二 数据预处理一、实践目的二、实践平台三、实践内容任务一&#xff1a;合并数据集任务二&#xff1a;独热编码任务三&#xff1a;数据预处理任务四&#xff1a;针对“项目一 医学数据采集”中“3. 通过 UCI 机器学习库下载数据集”任务所下载的数据集进行预处理。…

如何判断硬盘是不是固态硬盘?介绍几种简单有效方法

随着科技的发展&#xff0c;固态硬盘&#xff08;SSD&#xff09;因其读写速度快、噪音小、抗震能力强等优点&#xff0c;逐渐取代了传统的机械硬盘&#xff08;HDD&#xff09;。然而&#xff0c;对于普通用户来说&#xff0c;如何判断自己的硬盘是否为固态硬盘可能是一个难题…

10分钟在网站上增加一个AI助手

只需 10 分钟&#xff0c;为您的网站添加一个 AI 助手&#xff0c;以便全天候&#xff08;7x24&#xff09;回应客户咨询&#xff0c;提升用户体验、增强业务竞争力。 方案概览 在网站中引入一个 AI 助手&#xff0c;只需 4 步&#xff1a; 创建大模型问答应用&#xff1a;我们…

prometheus监控k8s1.24以上版本pod实时数据指标

8s组件本身提供组件自身运行的监控指标以及容器相关的监控指标。通过cAdvisor 是一个开源的分析容器资源使用率和性能特性的代理工具&#xff0c;集成到 Kubelet中&#xff0c;当Kubelet启动时会同时启动cAdvisor&#xff0c;且一个cAdvisor只监控一个Node节点的信息。cAdvisor…

Transformer学习记录(6):Vision Transformer

背景 Transformer模型最初是使用在NLP中&#xff0c;但近几年Transformer模型在图像上的使用越来越频繁&#xff0c;最新的模型也出现了很多基于Transfomer的&#xff0c;而其中经典的是Vision Transformer(ViT)&#xff0c;它是用于图像分类的&#xff0c;这里就以ViT-B/16这…

【已解决】SpringBoot3项目整合Druid依赖:Druid监控页面404报错

文章标题 问题描述原因分析解决方案参考资料 问题描述 最近&#xff0c;笔者在SpringBoot3项目中整合Druid连接池时&#xff0c;偶然翻到一条介绍Druid监控的短视频&#xff0c;兴致盎然之下尝试设置了一下Druid监控。 But&#xff0c;按照视频中提供的yml参数对照设置&#x…

试用过这么多ERP管理系统,还是这几款值得推荐!

已经考虑引入ERP系统却担心面临以下问题&#xff1f;ERP系统流程僵化难以调整&#xff1f;流程与实际业务脱节&#xff1f;培训不到位、技术支持不及时导致难以实现全员使用、共创&#xff1f;市面上的ERP系统众多不知道如何选择&#xff1f; 今天就根据2024最新市场动态&…

C++开发基础之理解 CUDA 编译配置:`compute_XX` 和 `sm_XX` 的作用

前言 在 CUDA 编程中&#xff0c;确保代码能够在不同的 NVIDIA GPU 上高效运行是非常重要的。为了实现这一点&#xff0c;CUDA 编译器 (nvcc) 提供了多种配置选项&#xff0c;其中 compute_XX 和 sm_XX 是两个关键的编译选项。本文将深入探讨这两个选项的作用及其配置顺序&…