政府网站新媒体建设自己怎么开网站
文章目录
- 概念整理
- 基本概念
- 概念助记
- 前提
- Rpc与HTTP类比
- RPC接口类的一些理解
- 项目代码
- 接口类定义
- 实现提供者
- 项目POM文件
- 项目代码文件
- 项目配置文件
- 运行项目
- 补充说明
- 实现消费者
- 项目POM文件
- 项目代码文件
- 项目配置文件
- 运行项目
- 补充说明
- 本文参考自SpringCloud+Dubbo+Nacos整合实现RPC调用一文,只是补充了一些概念理解,作为学习整理之用
- 项目源码:项目源码
概念整理
基本概念
- RPC可以理解为一种网络服务调用形式,具有服务提供方,服务调用方,调用功能,请求参数和响应参数的类似概念
- RPC有多种实现途径或组合框架,Nacos + Dubbo只是一种比较简单的实现方式
- 相比于HTTP请求
- RPC更适合在微服务节点之间进行高效的信息传输。原因之一是,在OSI模型中HTTP在第七层,RPC在第五层,所以RPC实现更加底层,处理过程更加简单,通讯效率更高。
- RPC必须要有【服务注册中心】这个组成部分,对提供者和消费者之间提供通讯桥梁,即提供者和消费者之间没有直连关系:
- 提供者:提供RPC服务并注册到服务中心
- 消费者:访问服务中心调用其中的RPC服务
概念助记
以下概念不是官方解释,仅为了方便第一次接触RPC时,方便理解RPC的相关概念
前提
- 对于普通Spring Boot项目在后台传输信息时,服务调用方(下称消费者)可以直接访通过服务提供方(下称提供者)提供的公开URL在java后台用Fegin、RestTemplate或者HttpClient工具发起形如
get http:\\目标节点IP:端口\functionUrl?param = xxxx
这样的请求 - 在Spring Cloud项目里,引入了【服务中心】,各节点都注册到中心里,所以调用URL变成了
get http:\\目标服务在服务中心的名字\functionUrl?param = xxxx
- 可以简单理解HTTP请求操作的中心就是URL,而RPC使用接口Interface(就是java原生的那个interface类型)替换对URL的操作
Rpc与HTTP类比
RPC | HTTP | |
---|---|---|
提供者 | Spring Cloud节点 | Spring Cloud或Spring Boot节点 |
消费者 | Spring Cloud节点 | Spring Cloud或Spring Boot节点 |
服务发现中心 | 必选 | 可选 |
调用目标名 | 服务中心注册名 | 服务中心注册名或目标IP+端口 |
调用URL的PathURL | 接口类的方法名 | PathURL |
请求参数 | 接口方法入参 | path或者body参数 |
响应结果 | 接口方法返回值 | 请求Response的body |
请求包含其他内容 | 无 | header,状态参数等 |
RPC接口类的一些理解
- RPC接口从代码层面定义一个节点功能的名称,入参、返回值等结果,相当于定义HTTP请求的RequestMap的路径和Controller的参数和返回值
- RPC接口对提供者和调用者同时可见
- RPC接口在提供者内部实现具体的业务逻辑,即存在Imp类,完成具体的业务功能
- RPC接口在调用者内部没有实现类,但可以像Mybatis的Mapper接口一样,注入并调用接口方法实现接口功能,可以理解为在Dubbo和Nacos的支持下(其他框架也可以),调用者内部的接口,生成了一个动态代理实例,这个实例的内部逻辑就是发起RPC网络请求,去执行提供者实现的接口类逻辑。使用起来可以类比Mybatis的Mapper接口,只定义Mapper接口,但这个接口使用时可以被注入,调用方法时也有具体的实现逻辑。
项目代码
以下所有代码文件,搬运且修改自SpringCloud+Dubbo+Nacos整合实现RPC调用,狗头保命
接口类定义
- 创建一个普通的Maven项目,创建一个接口类,为了描述,记该项目为apidemo,
package com.apidemo;
//普通的java接口,不需要额外受到任何注解修饰
public interface IHelloService {//实际就是定义网络接口的规范String provider(String content);
}
- 将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>
特别注意
- 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 {@Overridepublic 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 开始)#因为项目中存在多个服务提供端比如商品服务、会员服务等,这里为了方便设置为了-1protocol:name: dubboport: -1#Dubbo服务注册中心的配置地址,它的值spring-cloud://localhost表示挂载到Spring Cloud注册中心,不配置的话会提示没有配置注册中心的错误。registry:address: spring-cloud://localhost
运行项目
- 在确保目标Nacos已经正常启动后,启动当Service1节点
- 若运行正常,则可以看到当前节点已经注册到服务中心
补充说明
- 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【动态代理的关键】@DubboReferenceprivate IHelloService helloService;@Testpublic void RPCTest(){//显然对于消费者而言,helloService就像个普通接口,甚至感觉不到发起了网络请求,和Mybatis的Mapper有类似的感觉String result = helloService.provider("Lily");System.out.println("运行结果: " + result);}
}
项目配置文件
#服务名称
spring:application:name: dubbo-consumercloud:discovery: #禁止该服务注册到Nacos服务列表中register-enabled: falsenacos:discovery:server-addr: localhost:8848
server:port: 8882dubbo:cloud:subscribed-services: dubbo-sample-provider #表示要订阅服务的服务名,可以配置'*'代表订阅所有服务(不推荐使用)。若需订阅多应用,使用","分割。protocol:name: dubboport: 20881 # 同一台物理机既要启动提供者又要启动消费者时,必须指定dubbo端口号,如果用默认端口则会冲突
运行项目
补充说明
- Service2服务必须在Service1服务启动并注册成功之后才能启动,否则会发生@DubboReference的注入异常