Nacos + Dubbo 实现微服务的Rpc调用

news/2025/2/26 8:15:18

文章目录

  • 概念整理
    • 基本概念
    • 概念助记
      • 前提
      • Rpc与HTTP类比
      • RPC接口类的一些理解
  • 项目代码
    • 接口类定义
    • 实现提供者
      • 项目POM文件
      • 项目代码文件
      • 项目配置文件
      • 运行项目
      • 补充说明
    • 实现消费者
      • 项目POM文件
      • 项目代码文件
      • 项目配置文件
      • 运行项目
      • 补充说明

  1. 本文参考自SpringCloud+Dubbo+Nacos整合实现RPC调用一文,只是补充了一些概念理解,作为学习整理之用
  2. 项目源码:项目源码

概念整理

基本概念

  1. RPC可以理解为一种网络服务调用形式,具有服务提供方,服务调用方,调用功能,请求参数和响应参数的类似概念
  2. RPC有多种实现途径或组合框架,Nacos + Dubbo只是一种比较简单的实现方式
  3. 相比于HTTP请求
    1. RPC更适合在微服务节点之间进行高效的信息传输。原因之一是,在OSI模型中HTTP在第七层,RPC在第五层,所以RPC实现更加底层,处理过程更加简单,通讯效率更高。
    2. RPC必须要有【服务注册中心】这个组成部分,对提供者和消费者之间提供通讯桥梁,即提供者和消费者之间没有直连关系:
      1. 提供者:提供RPC服务并注册到服务中心
      2. 消费者:访问服务中心调用其中的RPC服务

概念助记

以下概念不是官方解释,仅为了方便第一次接触RPC时,方便理解RPC的相关概念

前提

  1. 对于普通Spring Boot项目在后台传输信息时,服务调用方(下称消费者)可以直接访通过服务提供方(下称提供者)提供的公开URL在java后台用Fegin、RestTemplate或者HttpClient工具发起形如get http:\\目标节点IP:端口\functionUrl?param = xxxx这样的请求
  2. 在Spring Cloud项目里,引入了【服务中心】,各节点都注册到中心里,所以调用URL变成了get http:\\目标服务在服务中心的名字\functionUrl?param = xxxx
  3. 可以简单理解HTTP请求操作的中心就是URL,而RPC使用接口Interface(就是java原生的那个interface类型)替换对URL的操作

Rpc与HTTP类比

RPCHTTP
提供者Spring Cloud节点Spring Cloud或Spring Boot节点
消费者Spring Cloud节点Spring Cloud或Spring Boot节点
服务发现中心必选可选
调用目标名服务中心注册名服务中心注册名或目标IP+端口
调用URL的PathURL接口类的方法名PathURL
请求参数接口方法入参path或者body参数
响应结果接口方法返回值请求Response的body
请求包含其他内容header,状态参数等

RPC接口类的一些理解

  1. RPC接口从代码层面定义一个节点功能的名称,入参、返回值等结果,相当于定义HTTP请求的RequestMap的路径和Controller的参数和返回值
  2. RPC接口对提供者和调用者同时可见
  3. RPC接口在提供者内部实现具体的业务逻辑,即存在Imp类,完成具体的业务功能
  4. RPC接口在调用者内部没有实现类,但可以像Mybatis的Mapper接口一样,注入并调用接口方法实现接口功能,可以理解为在Dubbo和Nacos的支持下(其他框架也可以),调用者内部的接口,生成了一个动态代理实例,这个实例的内部逻辑就是发起RPC网络请求,去执行提供者实现的接口类逻辑。使用起来可以类比Mybatis的Mapper接口,只定义Mapper接口,但这个接口使用时可以被注入,调用方法时也有具体的实现逻辑。

项目代码

以下所有代码文件,搬运且修改自SpringCloud+Dubbo+Nacos整合实现RPC调用,狗头保命

接口类定义

  1. 创建一个普通的Maven项目,创建一个接口类,为了描述,记该项目为apidemo,
package com.apidemo;
//普通的java接口,不需要额外受到任何注解修饰
public interface IHelloService {
	//实际就是定义网络接口的规范
    String provider(String content);
}
  1. 将apidemo项目打包成jar包或者作为一个IDEA中的一个module嵌入到父工程中

实现提供者

创建一个Spring Cloud项目,为了描述,记该项目为Service1
1. 集成Dubbo插件
2. 集成Nacos服务发现插件
3. 集成apidemo包并实现 IHelloService 接口
4. 配置项目属性文件,使得该节点可以被Nacos发现并向Nacos注入服务

项目POM文件

<?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">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com</groupId>
    <artifactId>service1</artifactId>
    <version>1.0</version>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.7.RELEASE</version>
        <relativePath/>
    </parent>
    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.SR10</spring-cloud.version>
        <spring-cloud-alibaba.version>2.2.5.RELEASE</spring-cloud-alibaba.version>
    </properties>
    <dependencyManagement>
        <dependencies>
            <!-- spring-cloud -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- spring-cloud-alibaba -->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <!-- spring boot -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- 热部署 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>
        <!-- Nacos Discovery -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!-- Dubbo -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-dubbo</artifactId>
        </dependency>
        <!-- 健康监控,必须包含spring-boot-starter-actuator包,不然启动会报错 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!-- 引入公用接口类包 -->
        <dependency>
            <groupId>com</groupId>
            <artifactId>apidemo</artifactId>
            <version>0.0.1-SNAPSHOT</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>
</project>

特别注意

  1. Nacos版本、SpringCloud版本以及Dubbo版本之间有一定关联要求,如果版本不匹配编译会报错,本文POM中插件的版本支持Java8 + Nacos 2.5.0 版本

项目代码文件

package com.service1;

import com.apidemo.IHelloService;
import org.apache.dubbo.config.annotation.DubboService;

@DubboService //该注解说明当前实现类为RPC服务类,不需要套接Controller也可以注册到Nacos
public class Service1Imp implements IHelloService {
    @Override
    public String provider(String content) {
    	//正常实现接口即可,无特殊限制要求
        System.out.println("into Service1Imp");
        return "服务提供者-" + content;
    }
}
package com.service1;

import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;


@EnableDiscoveryClient //开启服务发现
@EnableDubbo //支持Dubbo注入
@SpringBootApplication
public class Service1Application {

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

}

项目配置文件

# Spring应用名称,用于SpringCloud服务注册和发现。
# 该值在Dubbo Spring Cloud加持下被视作dubbo.application.name,因此,无需再显示地配置dubbo.application.name。
spring:
  application:
    name: dubbo-sample-provider
server:
  port: 8881
cloud:
  nacos:
    discovery: # 定义Nacos服务发现与注册配置,其中子属性server-addr指定Nacos服务器主机和端口。
      server-addr: localhost:8848
  
  #Dubbo服务实现类的扫描基准包路径
dubbo:
  scan:
    base-packages: com.service1 # 让dubbo扫描指定包,以发现RPC服务实现类(类似于MyBatis)
  #Dubbo服务暴露的协议配置,其中子属性name为协议名称,port为协议端口(-1 表示自增端口,从 20880 开始)
  #因为项目中存在多个服务提供端比如商品服务、会员服务等,这里为了方便设置为了-1
  protocol:
    name: dubbo
    port: -1
  #Dubbo服务注册中心的配置地址,它的值spring-cloud://localhost表示挂载到Spring Cloud注册中心,不配置的话会提示没有配置注册中心的错误。
  registry:
    address: spring-cloud://localhost

运行项目

  1. 在确保目标Nacos已经正常启动后,启动当Service1节点
  2. 若运行正常,则可以看到当前节点已经注册到服务中心
    在这里插入图片描述

补充说明

  1. Service1项目里没有Controller层套接,因此不能对Service1发起HTTP请求执行Service1Imp类的业务逻辑

实现消费者

创建一个Spring Cloud项目,为了描述,记该项目为Service1
1. 集成Dubbo插件
2. 集成Nacos服务发现插件
3. 集成apidemo包并实现 IHelloService 接口
4. 配置项目属性文件,使得该节点可以调用Nacos中的服务
5. 当前节点不用注入到Nacos中

项目POM文件

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com</groupId>
    <artifactId>service2</artifactId>
    <version>1.0</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.7.RELEASE</version>
        <relativePath/>
    </parent>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.SR10</spring-cloud.version>
        <spring-cloud-alibaba.version>2.2.5.RELEASE</spring-cloud-alibaba.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <!-- spring-cloud -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- spring-cloud-alibaba -->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <!-- spring boot -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- 热部署 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>
        <!-- web项目 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- Nacos Discovery -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!-- Dubbo -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-dubbo</artifactId>
        </dependency>
        <!-- 健康监控,必须包含spring-boot-starter-actuator包,不然启动会报错 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!-- 引入公用接口类包 -->
        <dependency>
            <groupId>com</groupId>
            <artifactId>apidemo</artifactId>
            <version>0.0.1-SNAPSHOT</version>
            <scope>compile</scope>
        </dependency>


    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

项目代码文件

@SpringBootApplication
public class Service2Application {
	//启动程序不要任何注解修饰
    public static void main(String[] args) {
        SpringApplication.run(Service2Application.class, args);
    }

}

这里使用JunitTest来启动模拟端点与端点之间的后台传入

package com.service2;

import com.apidemo.IHelloService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class HelloTest {

	//注意这里的注解,就是实现RPC【动态代理的关键】
    @DubboReference
    private IHelloService helloService;

    @Test
    public void RPCTest(){
    	//显然对于消费者而言,helloService就像个普通接口,甚至感觉不到发起了网络请求,和Mybatis的Mapper有类似的感觉
        String result = helloService.provider("Lily");
        System.out.println("运行结果: " + result);
    }
}

项目配置文件

#服务名称
spring:
  application:
    name: dubbo-consumer
  cloud:
    discovery: #禁止该服务注册到Nacos服务列表中
      register-enabled: false
  nacos:
    discovery:
      server-addr: localhost:8848
server:
  port: 8882

dubbo:
  cloud:
    subscribed-services: dubbo-sample-provider #表示要订阅服务的服务名,可以配置'*'代表订阅所有服务(不推荐使用)。若需订阅多应用,使用","分割。
  protocol:
    name: dubbo
    port: 20881 # 同一台物理机既要启动提供者又要启动消费者时,必须指定dubbo端口号,如果用默认端口则会冲突

运行项目

在这里插入图片描述

补充说明

  1. Service2服务必须在Service1服务启动并注册成功之后才能启动,否则会发生@DubboReference的注入异常

http://www.niftyadmin.cn/n/5868364.html

相关文章

MySQL 和 Elasticsearch 之间的数据同步

MySQL 和 Elasticsearch 之间的数据同步是常见的需求&#xff0c;通常用于将结构化数据从关系型数据库同步到 Elasticsearch 以实现高效的全文搜索、聚合分析和实时查询。以下是几种常用的同步方案及其实现方法&#xff1a; 1. 应用层双写&#xff08;双写模式&#xff09; 原…

面试题——简述Vue 3的服务器端渲染(SSR)是如何工作的?

面试题——简述Vue3的服务器端渲染&#xff08;SSR&#xff09;是如何工作的&#xff1f; 服务器端渲染&#xff08;SSR&#xff09;已经成为了一个热门话题。Vue 3&#xff0c;作为一款流行的前端框架&#xff0c;也提供了强大的SSR支持。那么&#xff0c;Vue 3的SSR究竟是如…

muduo源码阅读:linux timefd定时器

⭐timerfd timerfd 是Linux一个定时器接口&#xff0c;它基于文件描述符工作&#xff0c;并通过该文件描述符的可读事件进行超时通知。可以方便地与select、poll和epoll等I/O多路复用机制集成&#xff0c;从而在没有处理事件时阻塞程序执行&#xff0c;实现高效的零轮询编程模…

对鸿蒙 中 对象的理解

鸿蒙中的对象概述 1. 对象的基本概念 在鸿蒙开发里&#xff0c;对象是类的实例。类是一种用户自定义的数据类型&#xff0c;它定义了对象的属性&#xff08;数据&#xff09;和方法&#xff08;行为&#xff09;。当创建一个类的实例时&#xff0c;就得到了一个对象。例如&…

中国旅游行业年度报告2024

过去的一年对中国旅游业是意义非凡的一年、是中国旅游行业复苏的关键一年&#xff0c;中国旅游市场多项关键指标同比大幅增长&#xff0c;接近或超越2019年同期水平&#xff0c;中国旅游行业在复苏与繁荣的征程中又向前迈进了一大步。2024年中国国内旅游人次56.15亿&#xff0c…

IDEA集成DeepSeek,通过离线安装解决无法安装Proxy AI插件问题

文章目录 引言一、安装Proxy AI1.1 在线安装Proxy AI1.2 离线安装Proxy AI 二、Proxy AI中配置DeepSeek2.1 配置本地部署的DeepSeek&#xff08;Ollama方式&#xff09;2.2 通过第三方服务商提供的API进行配置 三、效果测试 引言 许多开发者尝试通过安装Proxy AI等插件将AI能力…

在vscode中编译运行c语言文件,配置并运行OpenMP多线程并行程序设计

1.下载安装vscode Visual Studio Code - Code Editing. Redefined 2.安装vscode扩展 打开vscode,按ctrl+shift+x,打开扩展,搜索c/c++,下载相应的扩展 3.下载MinGW-w64 MinGW-w64 提供了 GNU 编译器集合,可以编译c/c++文件 这里下载见我的资源,可直接下载 把压缩包解压…

python学智能算法(五)|差分进化算法:原理认识和极小值分析

【1】引言 前序已经学习了模拟退火算法和遗传算法&#xff0c;相关文章链接为&#xff1a; python学智能算法&#xff08;一&#xff09;|模拟退火算法&#xff1a;原理解释和最小值求解_模拟退火算法python-CSDN博客 python学智能算法&#xff08;二&#xff09;|模拟退火算…