微服务8:通信之RPC实践篇(附源码)

简介: 微服务8:通信之RPC实践篇(附源码)

1 说明

上一节我们我们详细学习了RPC的概念和原理,以及它能够提供的能力。也对目前业内主流的RPC的框架有了一定的了解。接下来以Dobbo为例子,来学习下怎么使用RPC框架来进行服务之间的通信。

2 Dubbo框架功能介绍

Apache Dubbo 是一款分布式微服务开发框架,它提供了 RPC通信 与 微服务治理 两大关键能力。这意味着,使用 Dubbo 开发的微服务,将具备相互之间的远程发现与通信能力, 同时利用 Dubbo 提供的丰富服务治理能力,可以实现诸如服务发现、负载均衡、流量调度等服务治理诉求。同时 Dubbo 是高度可扩展的,用户几乎可以在任意功能点去定制自己的实现,以改变框架的默认行为来满足自己的业务需求。

2.1 服务发现

服务发现,即消费端自动发现服务地址列表的能力,是微服务框架需要具备的关键能力,借助于自动化的服务发现,微服务之间可以在无需感知对端部署位置与 IP 地址的情况下实现通信。

实现服务发现的方式有很多种,Dubbo 提供的是一种 Client-Based 的服务发现机制,通常还需要部署额外的第三方注册中心组件来协调服务发现过程,如常用的 Nacos、Consul、Zookeeper 等,Dubbo 自身也提供了对多种注册中心组件的对接,用户可以灵活选择。

Dubbo 基于消费端的自动服务发现能力,其基本工作原理如下图:

image.png

2.2 RPC通信

Dubbo3 提供了 Triple(Dubbo3)、Dubbo2 协议,这是 Dubbo 框架的原生协议。除此之外,Dubbo3 也对众多第三方协议进行了集成,并将它们纳入 Dubbo 的编程与服务治理体系, 包括 gRPC、Thrift、JsonRPC、Hessian2、REST 等。

2.3 服务流量管理

通过 Dubbo 定义的路由规则,实现对流量分布的控制,可以实现 A/B测试、金丝雀发布、蓝绿发布等能力。

2.4 配置管理

描述 Dubbo 支持的配置,Dubbo 的动态配置能力,包含几大类: 启动阶段配置项、服务治理规则、动态配置项。

2.5 部署架构(注册、配置、元数据中心)

作为一个微服务框架,Dubbo sdk 跟随着微服务组件被部署在分布式集群各个位置,为了在分布式环境下实现各个微服务组件间的协作, Dubbo 定义了一些中心化组件,这包括:

  • 注册中心。协调 Consumer 与 Provider 之间的地址注册与发现
  • 配置中心。
  • 存储 Dubbo 启动阶段的全局配置,保证配置的跨环境共享与全局一致性
  • 负责服务治理规则(路由规则、动态配置等)的存储与推送。
  • 元数据中心。
  • 接收 Provider 上报的服务接口元数据,为 Admin 等控制台提供运维能力(如服务测试、接口文档等)
  • 作为服务发现机制的补充,提供额外的接口/方法级别配置信息的同步能力,相当于注册中心的额外扩展。

2.6 高可扩展性

Dubbo 通过 SPI 机制提供了非常灵活的可扩展性

3 Dubbo实现简易的RPC通信

3.1 框架依赖

image.png

  • Protocol, Proxy, Service, Container, Registry, Monitor 代表层或模块,蓝色的表示与业务的交互,绿色表示 Dubbo 内部的交互。
  • 主模块 RPC Consumer,RPC Provider, Registry, Monitor 代表部署逻辑拓扑节点。
  • 蓝色虚线为init初始化时调用,红色虚线为async运行时异步调用,红色实线为sync运行时同步调用。
  • Remoting 过程整体都隐含在 Protocol 中。

3.2 核心角色说明

  • Provider 暴露服务的服务提供方
  • Consumer 调用远程服务的服务消费方(负载均衡)
  • Registry 服务注册与发现的注册中心(监控、心跳、踢出、重入)
  • Monitor 服务消费者和提供者在内存中累计调用次数和调用时间,主动定时每分钟发送一次统计数据到监控中心。
  • Service 服务:执行远程调用、数据序列化

3.3 在 SpringBoot 中实践

3.3.1 父项目中引入依赖

首先引入 Zookeeper 和 Dubbo的依赖,Zookeeper的作用是注册与发现,Dubbo的作用是引入RPC通信核心能力

       <!-- 包含了Zookeeper和Dubbo依赖 -->         <dependency>             <groupId>com.alibaba.boot</groupId>             <artifactId>dubbo-spring-boot-starter</artifactId>             <version>0.2.0</version>         </dependency>

3.3.2 创建module

父项目下面创建三个Module,一个通用模块,一个服务提供者模块,一个服务消费者模块

  • RpcCommon
  • RpcProvider
  • RpcConsume

3.3.3 通用库 RpcCommon

提供了公用的实体和接口,比如这边包含了一个用户信息的实体类和用户信息接口,后面的服务提供者和消费这都可以引用:

/**  * @author brand  * @Description: 用户信息实体  * @Copyright: Copyright (c) 2022  * @Company: Helenlyn, Inc. All Rights Reserved.  * @date 2022/3/5 下午3:59  * @Update Time:  * @Updater:  * @Update Comments:  */ @Getter @Setter public class UserInfo implements Serializable {     private Integer userId;     private String userName;     private Integer age;     private String sex; }

/**  * @author brand  * @Description: 用户信息接口  * @Copyright: Copyright (c) 2022  * @Company: Helenlyn, Inc. All Rights Reserved.  * @date 2022/3/5 下午5:29  * @Update Time:  * @Updater:  * @Update Comments:  */ public interface UserInfoService {     UserInfo getUserInfo (int userId) ;     String getHello (int userId) ; }

3.3.3 服务提供者 RpcProvider

yml文件中的配置信息如下,可以看到我配置的zookeeper地址是127.0.0.1:2181,这是我本地部署到Zookeeper服务,大家可以对应修改下。

scan属性指的是暴露服务的位置,对应位置下的类,只要声明 Service 注解,就会被扫描并暴露出去。

# Dubbo Provider 配置 dubbo:   application:     name: rpc-provider # 发布的dubbo服务名称   registry:     address: 127.0.0.1:2181  # 使用Zookeeper注册中心提供的服务地址,这边可以配置多个,逗号隔开     protocol: zookeeper   protocol:     name: dubbo     port: 20882  # 用dubbo协议在20882端口暴露服务   scan: # 使用注解方式暴露接口,扫描的位置     base-packages: rpcprovider.modules.service

然后编写需要暴露出去的接口的实现,这边需要注意类上引入的注解为com.alibaba.dubbo.config.annotation的Service,

而不是springframework包中的service,这样Service服务才能被注册到dubbo中:

package rpcprovider.modules.service; import com.alibaba.dubbo.config.annotation.Service; import rpccommon.dto.UserInfo; import rpccommon.service.UserInfoService; /**  * @author brand  * @Description:  * @Copyright: Copyright (c) 2022  * @Company: Helenlyn, Inc. All Rights Reserved.  * @date 2022/3/5 下午5:43  * @Update Time:  * @Updater:  * @Update Comments:  */ @Service public class UserInfoServiceImpl implements UserInfoService {     @Override     public UserInfo getUserInfo(int userId) {         UserInfo userInfo = new UserInfo();         userInfo.setUserId(userId);         userInfo.setAge(18);         userInfo.setSex("男");         userInfo.setUserName("Brand");         return userInfo;     }     @Override     public String getHello(int userId) {         return " Hello, " + userId;     } }

启动起来看看Zookeeper的效果,是不是被注册到Dubbo中,这边可以用看到,Provider中已经有注册节点了。

[zk: 127.0.0.1:2181(CONNECTED) 68] ls / [dubbo, zookeeper] [zk: 127.0.0.1:2181(CONNECTED) 69] ls /dubbo [rpccommon.service.UserInfoService] [zk: 127.0.0.1:2181(CONNECTED) 70] ls /dubbo/rpccommon.service.UserInfoService [configurators, consumers, providers, routers] [zk: 127.0.0.1:2181(CONNECTED) 71] ls /dubbo/rpccommon.service.UserInfoService/providers [dubbo%3A%2F%2F172.21.213.159%3A20882%2Frpccommon.service.UserInfoService%3Fanyhost%3Dtrue%26application%3Drpc-provider%26dubbo%3D2.6.2%26generic%3Dfalse%26interface%3Drpccommon.service.UserInfoService%26methods%3DgetHello%2CgetUserInfo%26pid%3D60138%26side%3Dprovider%26timestamp%3D1646535565910] [zk: 127.0.0.1:2181(CONNECTED) 72]

3.3.4 消费者 RpcConsume

yml文件中的配置信息如下:

# Dubbo Consumer 配置文件 dubbo:   application:     name: rpc-consumer   registry:     address: 127.0.0.1:2181 # 使用Zookeeper注册中心提供的服务地址来获取服务,这边可以多个逗号隔开     protocol: zookeeper

消费者使用注解方式进行RPC调用,这边注意,通过@Reference注解, dubbo会在扫描的时候自动帮我们代理接口,然后通过rpc调用远程服务。如下:

package rpcconsume.modules.service; import com.alibaba.dubbo.config.annotation.Reference; import org.springframework.stereotype.Service; import rpccommon.dto.UserInfo; import rpccommon.service.UserInfoService; /**  * @author brand  * @Description: 消费者使用注解方式进行RPC调用  * @Copyright: Copyright (c) 2022  * @Company: Helenlyn, Inc. All Rights Reserved.  * @date 2022/3/5 下午6:49  * @Update Time:  * @Updater:  * @Update Comments:  */ @Service public class UserInfoConsumer implements UserInfoService {     @Reference     private UserInfoService userInfoService ;     @Override     public UserInfo getUserInfo(int userId) {         return userInfoService.getUserInfo(userId);     }     @Override     public String getHello(int userId) {         return userInfoService.getHello(userId);     } }

写一个Controller,通过外部调用,来测试效果

package rpcconsume.modules.controller; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import rpccommon.dto.UserInfo; import rpcconsume.modules.service.UserInfoConsumer; /**  * @author brand  * @Description: 测试消费者效果  * @Copyright: Copyright (c) 2022  * @Company: Helenlyn, Inc. All Rights Reserved.  * @date 2022/3/5 下午6:48  * @Update Time:  * @Updater:  * @Update Comments:  */ @RestController @Slf4j @RequestMapping("/v1.0/consumer") public class ConsumerController {     @Autowired     private UserInfoConsumer userInfoConsumer ;     /**      * 获取用户信息      * @return      */     @RequestMapping(value = "/userinfo/{user_id}", method = RequestMethod.GET)     public UserInfo getUserInfo(@PathVariable("user_id") int userId) {         return userInfoConsumer.getUserInfo(userId);     }     /**      * 获取问候信息      * @return      */     @RequestMapping(value = "/hello/{user_id}", method = RequestMethod.GET)     public String getHello(@PathVariable("user_id") int userId) {         return userInfoConsumer.getHello(userId);     } }

查一下Zookeeper 上的消费者信息:

[zk: 127.0.0.1:2181(CONNECTED) 73] ls /dubbo/rpccommon.service.UserInfoService/consumers [consumer%3A%2F%2F172.21.213.159%2Frpccommon.service.UserInfoService%3Fapplication%3Drpc-consumer%26category%3Dconsumers%26check%3Dfalse%26dubbo%3D2.6.2%26interface%3Drpccommon.service.UserInfoService%26methods%3DgetHello%2CgetUserInfo%26pid%3D60884%26side%3Dconsumer%26timestamp%3D1646536367371]

调用效果:

image.png

3.3.5 源代码参考

GitHub地址:https://github.com/WengZhiHua/Helenlyn.Grocery/tree/master/parent

4 总结

RPC通信只是 Dubbo 功能的一部分,像上面介绍的那样,除了RPC通信之外,还有服务注册与发现、配置管理、服务流量治理等,基本能达到一个微服务的基本能力要求。

另外我们还看到,除了Dubbo之外,百度的brpc和Google的gRPC也有很大的受众,也是不错的选择,我们上一章有对主流RPC框架做了对比和分析,可以根据自身的业务特性进行技术选型。

相关文章
|
7月前
|
弹性计算 关系型数据库 微服务
基于 Docker 与 Kubernetes(K3s)的微服务:阿里云生产环境扩容实践
在微服务架构中,如何实现“稳定扩容”与“成本可控”是企业面临的核心挑战。本文结合 Python FastAPI 微服务实战,详解如何基于阿里云基础设施,利用 Docker 封装服务、K3s 实现容器编排,构建生产级微服务架构。内容涵盖容器构建、集群部署、自动扩缩容、可观测性等关键环节,适配阿里云资源特性与服务生态,助力企业打造低成本、高可靠、易扩展的微服务解决方案。
2208 10
|
8月前
|
JSON 自然语言处理 API
gRPC凭什么成为微服务通信首选?深度解析RPC进化史
本文深入解析了分布式系统中服务通信的核心机制,重点介绍了 RPC 与 gRPC 的原理、优势及使用场景,并详解 gRPC 所依赖的序列化协议 Protocol Buffers(Protobuf)。内容涵盖 RPC 概念、gRPC 特性、Protobuf 语法及服务定义,适合微服务架构设计与维护人员阅读,助你构建高性能、低耦合的服务通信体系。
990 73
gRPC凭什么成为微服务通信首选?深度解析RPC进化史
|
人工智能 安全 Java
智慧工地源码,Java语言开发,微服务架构,支持分布式和集群部署,多端覆盖
智慧工地是“互联网+建筑工地”的创新模式,基于物联网、移动互联网、BIM、大数据、人工智能等技术,实现对施工现场人员、设备、材料、安全等环节的智能化管理。其解决方案涵盖数据大屏、移动APP和PC管理端,采用高性能Java微服务架构,支持分布式与集群部署,结合Redis、消息队列等技术确保系统稳定高效。通过大数据驱动决策、物联网实时监测预警及AI智能视频监控,消除数据孤岛,提升项目可控性与安全性。智慧工地提供专家级远程管理服务,助力施工质量和安全管理升级,同时依托可扩展平台、多端应用和丰富设备接口,满足多样化需求,推动建筑行业数字化转型。
400 5
|
7月前
|
编解码 网络协议 Java
RPC的三大问题:跨语言、跨平台通信的终极解决方案是如何炼成的?
本文深入解析现代RPC体系的核心挑战与解决方案,涵盖数据表示、传输机制与调用约定,探讨gRPC、HTTP/2、ProtoBuf等技术如何实现高效可靠的跨服务通信,并分析自研RPC协议的设计思路与未来发展路径。
291 8
|
Cloud Native Serverless 流计算
云原生时代的应用架构演进:从微服务到 Serverless 的阿里云实践
云原生技术正重塑企业数字化转型路径。阿里云作为亚太领先云服务商,提供完整云原生产品矩阵:容器服务ACK优化启动速度与镜像分发效率;MSE微服务引擎保障高可用性;ASM服务网格降低资源消耗;函数计算FC突破冷启动瓶颈;SAE重新定义PaaS边界;PolarDB数据库实现存储计算分离;DataWorks简化数据湖构建;Flink实时计算助力风控系统。这些技术已在多行业落地,推动效率提升与商业模式创新,助力企业在数字化浪潮中占据先机。
629 12
|
监控 Kubernetes Cloud Native
基于阿里云容器服务Kubernetes版(ACK)的微服务架构设计与实践
本文介绍了如何基于阿里云容器服务Kubernetes版(ACK)设计和实现微服务架构。首先概述了微服务架构的优势与挑战,如模块化、可扩展性及技术多样性。接着详细描述了ACK的核心功能,包括集群管理、应用管理、网络与安全、监控与日志等。在设计基于ACK的微服务架构时,需考虑服务拆分、通信、发现与负载均衡、配置管理、监控与日志以及CI/CD等方面。通过一个电商应用案例,展示了用户服务、商品服务、订单服务和支付服务的具体部署步骤。最后总结了ACK为微服务架构提供的强大支持,帮助应对各种挑战,构建高效可靠的云原生应用。
|
搜索推荐 NoSQL Java
微服务架构设计与实践:用Spring Cloud实现抖音的推荐系统
本文基于Spring Cloud实现了一个简化的抖音推荐系统,涵盖用户行为管理、视频资源管理、个性化推荐和实时数据处理四大核心功能。通过Eureka进行服务注册与发现,使用Feign实现服务间调用,并借助Redis缓存用户画像,Kafka传递用户行为数据。文章详细介绍了项目搭建、服务创建及配置过程,包括用户服务、视频服务、推荐服务和数据处理服务的开发步骤。最后,通过业务测试验证了系统的功能,并引入Resilience4j实现服务降级,确保系统在部分服务故障时仍能正常运行。此示例旨在帮助读者理解微服务架构的设计思路与实践方法。
892 17
|
消息中间件 运维 安全
后端开发中的微服务架构实践与挑战####
在数字化转型的浪潮中,微服务架构凭借其高度的灵活性和可扩展性,成为众多企业重构后端系统的首选方案。本文将深入探讨微服务的核心概念、设计原则、关键技术选型及在实际项目实施过程中面临的挑战与解决方案,旨在为开发者提供一套实用的微服务架构落地指南。我们将从理论框架出发,逐步深入至技术细节,最终通过案例分析,揭示如何在复杂业务场景下有效应用微服务,提升系统的整体性能与稳定性。 ####
321 32
|
运维 监控 Java
后端开发中的微服务架构实践与挑战####
在数字化转型加速的今天,微服务架构凭借其高度的灵活性、可扩展性和可维护性,成为众多企业后端系统构建的首选方案。本文深入探讨了微服务架构的核心概念、实施步骤、关键技术考量以及面临的主要挑战,旨在为开发者提供一份实用的实践指南。通过案例分析,揭示微服务在实际项目中的应用效果,并针对常见问题提出解决策略,帮助读者更好地理解和应对微服务架构带来的复杂性与机遇。 ####
|
监控 JavaScript 数据可视化
建筑施工一体化信息管理平台源码,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
智慧工地云平台是专为建筑施工领域打造的一体化信息管理平台,利用大数据、云计算、物联网等技术,实现施工区域各系统数据汇总与可视化管理。平台涵盖人员、设备、物料、环境等关键因素的实时监控与数据分析,提供远程指挥、决策支持等功能,提升工作效率,促进产业信息化发展。系统由PC端、APP移动端及项目、监管、数据屏三大平台组成,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
600 7
下一篇
开通oss服务