场景:提供provider,consumer,通过RPC远程调用使得consumer能够调用provider中的服务。
实现:创建三个模块:apache-dubbo-provider-api, apache-dubbo-provider-sample, apache-dubbo-consumer-sample
其中apache-dubbo-provider-api描述了对外提供的服务,需要provider进行实现,consumer进行订阅;
不使用注册中心的方式进行调用
使用原生spring XML文件形式进行配置,Maven项目导入dubbo依赖:
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>2.7.16</version>
</dependency>
#apache-dubbo-provider-api
public interface ProviderService {
String login(String username, String password);
String sayHello(String username);
}
#apache-dubbo-provider-sample 具体方法实现
public class ProviderServiceImpl implements ProviderService{
@Override
public String login(String username, String password) {
if ("admin".equals(username) && "admin".equals(password)) {
return sayHello(username);
}
return "登录失败";
}
@Override
public String sayHello(String username) {
return username + " 您好!";
}
}
编写application.xml文件,方便启动时加载,将文件放到 resources/META-INF 目录下
<dubbo:protocol name="dubbo" port="20880"/>
<dubbo:application name="dubbo-provider"/>
<dubbo:registry address="N/A"/>
<dubbo:service interface="com.righteye.service.ProviderService" ref="provider-login"/>
<bean id="provider-login" class="com.righteye.service.ProviderServiceImpl"/>
可以使用dubbo中提供的启动类启动项目:
import org.apache.dubbo.container.Main;
public class ProviderApplication {
public static void main(String[] args) {
Main.main(args);
}
}
项目启动后:
#apache-dubbo-provider-consumer
编写application.xml文件
<dubbo:application name="dubbo-consumer"/>
<dubbo:registry address="N/A"/>
<dubbo:reference id="serviceLogin" interface="com.righteye.service.ProviderService"
url="dubbo://192.168.220.1:20880/com.righteye.service.ProviderService"/>
这里的url写provier运行成功后的日志内容
测试内容:
@Test
public void testDubboRemoteCall() {
ProviderService providerService = null;
String config = "classpath:application.xml";
ApplicationContext ac = new ClassPathXmlApplicationContext(config);
providerService = (ProviderService) ac.getBean("serviceLogin");
String res = providerService.login("admin", "admin");
System.out.println(res);
}
Dubbo可支持多种注册中心,如 Zookeeper, Eureka, Nacos
通过注册中心,provider将服务进行注册而consumer进行订阅,灵活性更高
引入Nacos依赖
<dependency>
<groupId>com.alibaba.nacosgroupId>
<artifactId>nacos-clientartifactId>
<version>1.4.2version>
dependency>
修改provider和consumer的配置文件
#apache-dubbo-provider-sample
<dubbo:protocol name="dubbo" port="20880"/>
<dubbo:application name="dubbo-provider"/>
<dubbo:registry address="nacos://192.168.189.130:8848"/>
<dubbo:service interface="com.righteye.service.ProviderService" ref="provider-login"/>
<bean id="provider-login" class="com.righteye.service.ProviderServiceImpl"/>
#apache-dubbo-consumer-sample
<dubbo:application name="dubbo-consumer"/>
<dubbo:registry address="nacos://192.168.189.130:8848"/>
<dubbo:reference id="serviceLogin" interface="com.righteye.service.ProviderService"/>
除上述外其他代码不需要改变
Nacos中注册内容:
dubbo 重新更新后与SpringCloud结合的产物,继承了SpringCloud微服务环境的优势。
传统的SpringCloud中使用远程调用的组件时Feign,该组件基于Http,默认每次调用采用短链接,因此每一次请求都需要重新建立TCP,导致效率低下。而RPC是基于TCP,作用于传输层。
使用SpringCloud Dubbo的理想状态是对外采用RestFul(HTTP),内部远程调用使用RPC,提高性能。
场景:搭建微服务环境 dubbo-cloud-provider-api, dubbo-cloud-provider-sample, dubbo-cloud-consumser-sample
环境: 微服务 - springboot 2.4.3 spring-cloud 2020.0.1 spring-cloud-alibaba 2021.0.1
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.4.2version>
<relativePath/>
parent>
<packaging>pompackaging>
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<java.version>1.8java.version>
<spring.cloud.version>2020.0.1spring.cloud.version>
<spring.cloud.alibaba.version>2021.1spring.cloud.alibaba.version>
properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-dependenciesartifactId>
<version>${spring.cloud.version}version>
<scope>importscope>
<type>pomtype>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-alibaba-dependenciesartifactId>
<version>${spring.cloud.alibaba.version}version>
<scope>importscope>
<type>pomtype>
dependency>
dependencies>
dependencyManagement>
#dubbo-cloud-provider-api
同样作为接口工厂,用来约束暴露/订阅的内容;同时管理maven项目中的依赖
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-dubboartifactId>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
dependency>
<dependency>
<groupId>org.apache.commonsgroupId>
<artifactId>commons-lang3artifactId>
<version>3.12.0version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-ribbonartifactId>
<version>2.2.5.RELEASEversion>
dependency>
dependencies>
#dubbo-cloud-provider-sample
pom.xml
<dependency>
<groupId>com.righteyegroupId>
<artifactId>dubbo-cloud-provider-apiartifactId>
<version>1.0-SNAPSHOTversion>
dependency>
接口实现类:
@DubboService
public class DubboCloudServiceImpl implements DubboCloudService{
@Override
public String sayHello() {
return "hello dubbo-spring-cloud";
}
}
配置文件 application.yaml
server:
port: 10056
dubbo:
# 服务名称
application:
name: dubbo-cloud-provider
# 协议和端口
protocol:
port: 20880
name: dubbo
# 注册中心
registry:
address: spring-cloud://${righteye.addr}:8848
# 需要扫描的基准包
scan:
base-packages: com.righteye.service
spring:
application:
name: dubbo-cloud-provider
cloud:
nacos:
discovery:
server-addr: ${righteye.addr}:8848
righteye:
addr: 192.168.189.xxx
#dubbo-cloud-provider-sample
配置文件application.yaml
server:
port: 10057
spring:
application:
name: dubbo-cloud-consumer
cloud:
nacos:
discovery:
server-addr: ${righteye.addr}:8848
dubbo:
application:
name: ${spring.application.name}
registry:
address: spring-cloud://${spring.cloud.nacos.discovery.server-addr}
protocol:
name: dubbo
port: -1
righteye:
addr: 192.168.189.xxx
测试类:
@RestController
public class TestController {
@DubboReference
private DubboCloudService dubboCloudService;
@GetMapping("/hello")
public String testSayHello() {
return dubboCloudService.sayHello();
}
}
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
启动带有内置tomcat容器的springboot项目,不添加该依赖后续即使启动成功也不存在web容器。
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-dubboartifactId>
dependency>
dubbo-spring-cloud的启动器,含spring-cloud与dubbo整合的相关依赖
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
dependency>
Nacos服务注册中心
<dependency>
<groupId>org.apache.commonsgroupId>
<artifactId>commons-lang3artifactId>
<version>3.12.0version>
dependency>
如果不引入commons-lang3的话会报错: java.lang.ClassNotFoundException: org.apache.commons.lang3.StringUtils。但是在2018年的时候就提示已经移除了commons-lang3,详见[dubbo-1920] remove commons-lang3 dependency by beiwei30 · Pull Request #1921 · apache/dubbo · GitHub
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-ribbonartifactId>
<version>2.2.5.RELEASEversion>
dependency>
处理异常:Failed to instantiate [feign.jaxrs2.JAXRS2Contract]: Constructor threw exception; nested exception is java.lang.NoClassDefFoundError: javax/ws/rs/Path
dubbo文档:
dubbo3.x Java JDK入门
https://github.com/apache/dubbo-spring-boot-project
解决方案:
SpringCloudAlibaba版本升级遇到的问题