Dubbo 学习笔记总结

Posted IT_Holmes

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Dubbo 学习笔记总结相关的知识,希望对你有一定的参考价值。

文章目录

1. Dubbo与SpringBoot整合

1.1 整合Dubbo和SpringBoot的环境依赖


创建两个springboot项目,分别对应consumer服务消费者和provider服务提供者。

同样将原来公共项目部分进行打包依赖,导入两个springboot项目中。

1、导入依赖

  • 1)、导入dubbo-starter,同样要注意有严格的版本对应springboot项目版本,dubbo版本,dubbo-spring-boot-starter版本等等都要注意。
  • 2)、导入dubbo的其他依赖。

    按要求导入dubbo-spring-boot-starter依赖:
  • 3)、这样我们就可以直接在application.properties或者yaml里面直接配置属性了。

1.2 配置SpringBoot 服务提供者相关配置


1. 先配置服务提供者provider的springboot项目:

  • 直接配置application.properties文件或者yaml文件,都一样都是配置属性,其实和之前xml文件都一致!
# 1.指定当前服务(也就是应用的名字)(同样的服务名字相同,不要和别的服务同名)
dubbo.application.name=user-service-provider

# 2.指定注册中心的位置,官方有两种写法
#dubbo.registry.address=zookeeper://127.0.0.1:2181
dubbo.registry.protocol=zookeeper
dubbo.registry.address=127.0.0.1:2181

# 3.指定通信规则(指定通信协议和通信端口) 协议有很多可以去官方协议手册查看,目前使用dubbo协议。
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880

# 4.有两种方式连接监控中心:
#	    指定protocol="registry",表示从注册中心发现监控中心地址,否则直连监控中心。
#	    address="127.0.0.1:7070 ,直连dubbo-monitor地址,端口号是dubbo-monitor通信端口号。
#dubbo.monitor.address=127.0.0.1:7070
dubbo.monitor.protocol=registry

2. 对于暴露服务(暴露接口和指定接口实现类)。对于Springboot有专门的注解来操作。

  • 首先,在springboot主程序添加@EnableDubbo注解,该注解作用:开启基于注解的dubbo功能。
  • 之后,使用dubbo依赖包下面的@Service注解来暴露服务!
package com.itholmes.gmall.service.impl;

import java.util.Arrays;
import java.util.List;
import com.itholmes.gmall.bean.UserAddress;
import com.itholmes.gmall.service.UserService;
import org.springframework.stereotype.Component;

import com.alibaba.dubbo.config.annotation.Service;

/**
 *	这里的注解是dubbo依赖包下面的注解!!!
 *		该注解作用就是暴露服务,暴露当前接口实现类。
 */
@Service
@Component//扫描包
public class UserServiceImpl implements UserService

	public List<UserAddress> getUserAddressList(String userId) 
		//模拟返回收获地址数据
		UserAddress address1 = new UserAddress(1,"北京XXXX","1","李四","1283095748","Y");
		UserAddress address2 = new UserAddress(2,"德州XXXX","2","张三","1283095123123","N");
		return Arrays.asList(address1,address2);
	
	

3. 启动Springboot项目,查看dubbo-admin控制台和monitor相关信息就可以了。


1.3 配置SpringBoot 服务消费者相关配置


同样先导入依赖,然后配置application.properties文件:

# 1.指定当前服务(也就是应用的名字)(同样的服务名字相同,不要和别的服务同名)
dubbo.application.name=order-service-consumer

# 2.指定注册中心zookeeper的位置,官方有两种写法
dubbo.registry.address=zookeeper://127.0.0.1:2181

# 3. 有两种方式连接监控中心:
#		指定protocol="registry",表示从注册中心发现监控中心地址,否则直连监控中心。
#		address="127.0.0.1:7070 ,直连dubbo-monitor地址,端口号是dubbo-monitor通信端口号。
dubbo.monitor.protocol=registry

也是同样使用注解来声明需要调用的远程服务接口(生成远程服务代理):

  • 使用@Reference注解来远程应用服务。
package com.itholmes.gmall.service.impl;

import java.util.List;
import com.itholmes.gmall.bean.UserAddress;
import com.itholmes.gmall.service.OrderService;
import com.itholmes.gmall.service.UserService;

import org.springframework.stereotype.Service;
import com.alibaba.dubbo.config.annotation.Reference;

@Service//这里使用spring的Service,不用dubbo的Service。
public class OrderServiceImpl implements OrderService 

	/**
	 * 这里就不使用@Autowired注解,而是使用dubbo的@Reference注解
	 * 		该@Reference注解作用:远程应用服务
	 */
	@Reference
	UserService userService;
	
	public List<UserAddress> initOrder(String userId) 
		// TODO Auto-generated method stub
		System.out.println("用户ID:"+userId);
		//1.查询用户的收货地址,也就是调用user-service-provider项目中的查询收货地址的功能
		List<UserAddress> list = userService.getUserAddressList(userId);
		for(UserAddress user:list) 
			System.out.println(user);
		
		return list;
	
	

这样在启动消费者服务Springboot项目,就可以在admin和monitor查看到了:

可以通过写一个Controller层接口,两个SpringBoot项目之前能否调用就行了。

2. dubbo的覆盖策略


3. dubbo 配置 check启动时检查



启动时检查:

  • 当消费者启动时,检查该消费者需要的提供者服务是否已经注册到注册中心里面了。

  • check=“true”,开启检查也是默认;如果开始启动没有就会报错。

  • check=“false”,关闭检查;当调用去注册中心查找时,才会报错。

xml文件:可以在dubbo:reference要调用的远程类上面添加check="false"的属性。

也可以使用dubbo:consumer进行统一配置:

<dubbo:reference 
	interface="com.itholmes.gmall.service.UserService" 
	id="userService"
></dubbo:reference>

<dubbo:reference 
	interface="com.itholmes.gmall.service.UserService2" 
	id="userService2"
></dubbo:reference>

<!-- 配置当前消费者的统一规则(服务消费者的缺省配置) -->
<dubbo:consumer check="false"></dubbo:consumer>


总体可以配三个check的启动时检查:

4. dubbo 配置 timeout超时和配置覆盖关系


timeout属性:

<!-- 
	timeout="1000" 设置超时,远程服务调用超时时间(毫秒),作用就是性能优化,防止阻塞时间太久。
	默认是dubbo:consumer缺省的timeout(1000毫秒)。
-->
<dubbo:reference 
	interface="com.itholmes.gmall.service.UserService" 
	id="userService"
	check="false"
	timeout="3000"
></dubbo:reference>

还可以明确配置哪个方法的超时时间:

<dubbo:reference 
	interface="com.itholmes.gmall.service.UserService" 
	id="userService"
	check="false"
	timeout="3000"
>
	<!-- 明确指定哪个方法的超时时间。 -->
	<dubbo:method name="getUserAddressList" timeout="4000"></dubbo:method>
</dubbo:reference>

对于这种优先级级别官方给出如下:

从官方给出的优先级:

  • 消费者dubbo:reference method > 提供者dubbo:service method > 消费者dubbo:reference > 提供者dubbo:service > 消费者dubbo:consumer > 提供者dubbo:provider

5. dubbo 配置 retries重试次数


retries=“” 指定重试次数,不包含第一次调用。

  • 例如:下面是设置了retries=“3” ,这样相当于最多调用了4次,因此第一次不包含。
<!-- retries="" 指定重试次数,不包含第一次调用。 -->
<dubbo:reference 
	interface="com.itholmes.gmall.service.UserService" 
	id="userService"
	check="false"
	timeout="3000"
	retries="3"
>
	<!-- 明确指定哪个方法的超时时间。 -->
	<dubbo:method name="getUserAddressList" timeout="4000"></dubbo:method>
</dubbo:reference>

retries重试次数,在重试的时候也会重试其他相同的提供服务者。


什么情况下,设置重试次数?

  • 幂等情况下,设置重试次数。
  • 非幂等情况下,不能设置重试次数。retries="0"就是设置了非幂等。

幂等就是执行多次,产生的效果都是一样的!

  • 幂等案例:查询一些数据,删除某个固定数据,修改一些东西;重复多次,想要的结果也是一样的,这种的就是幂等的。
  • 非幂等案例:数据库数据的新增,如果新增重复了,那就有可能一下子添加多个数据,这就不符合我们想要的结果。

6. dubbo 配置 version多版本


出现不兼容升级的情况,可以用版本号过渡:

  • 也就是灰度发布。

服务消费者配置:

<!-- 
	version版本号:
		对于一些升级,在相同接口,可以使用不同版本号,来调用。
		version="*"代表可以调用任意版本。
-->
<dubbo:reference 
	interface="com.itholmes.gmall.service.UserService" 
	id="userService"
	check="false"
	timeout="3000"
	retries="3"
	version="2.0.0"
>

服务提供者配置:

<!--配置两个相同接口,但是不同版本的实现类。这样服务消费者就可以通过version来决定使用哪个。-->
<dubbo:service 
	interface="com.itholmes.gmall.service.UserService" 
	ref="userServiceImpl01"
	timeout="5000"
	version="1.0.0"
></dubbo:service>

<dubbo:service 
	interface="com.itholmes.gmall.service.UserService" 
	ref="userServiceImpl02"
	timeout="5000"
	version="2.0.0"
></dubbo:service>

<bean id="userServiceImpl01" class="com.itholmes.gmall.service.impl.UserServiceImpl"></bean>
<bean id="userServiceImpl02" class="com.itholmes.gmall.service.impl.UserServiceImpl2"></bean>

7. dubbo 配置 本地存根stub


本地存根可以做缓存,提前验证一些参数啥的。其实就是执行前远程代理类前,执行一些代码操作啥的。

先创建一个远程类对应的实现类和对应构造方法如下:

  • 因为,直接传入的是远程实现类的代理对象。
package com.itholmes.gmall.service.impl;

import java.util.List;
import org.springframework.util.StringUtils;
import com.itholmes.gmall.bean.UserAddress;
import com.itholmes.gmall.service.UserService;

public class UserServiceStub implements UserService

	private final UserService userService;
	/**
	 *	这里必须要有一个远程对应的实现类和对应构造方法
	 *		这里传入的是userService远程的代理对象
	 * @param userService
	 */
	public UserServiceStub(UserService userService) 
		super();
		this.userService = userService;
	

	public List<UserAddress> getUserAddressList(String userId) 
		System.out.println("经过Stub。");
		// StringUtils是spring框架的utils类里面的一个工具类
		if(StringUtils.isEmpty(userId)) 
			return userService.getUserAddressList(userId);
		
		return null;
	


可以设置在服务消费者,也可以设置在服务提供者:

<!--可以在服务消费者进行设置stub-->
<dubbo:reference 
	interface="com.itholmes.gmall.service.UserService" 
	id="userService"
	check="false"
	timeout="3000"
	stub="com.itholmes.gmall.service.impl.UserServiceStub"
>
	<!-- 明确指定哪个方法的超时时间。 -->
	<dubbo:method name="getUserAddressList" timeout="4000"></dubbo:method>
</dubbo:reference>

<!--还可以在服务提供者进行设置stub-->
<dubbo:service 
	interface="com.itholmes.gmall.service.UserService" 
	ref="userServiceImpl02"
	timeout="5000"
	version="2.0.0"
	stub="com.itholmes.gmall.service.impl.UserServiceStub"
></dubbo:service>

这样在调用时就会先走stub存根,之后会正常返回代码。

8. dubbo 配置 整合SpringBoob

8.1 dubbo 相关配置 整合SpringBoob


对于服务提供者的springboot项目,相关配置可以直接通过dubbo的@Service直接配置:

  • 服务提供者dubbo的@Service注解配置:

  • 服务消费者@Reference注解配置:

8.2 SpringBoot与dubbo整合的三种方式


方式一: 导入dubbo-starter,在application.properties配置属性,使用@Service【暴露服务】 ,使用@Reference注解【引用服务】。

  • 不要忘记@EnableDubbo注解的使用:

  • 还可以不使用@EnableDubbo注解来Dubbo相关注解,直接在application.properties配置:

#配置了扫描,就可以不使用@EnableDubbo,主要是能够让dubbo扫描到就可以。
dubbo.scan.base-packages=com.itholmes.gmall

方式二:保留dubbo xml配置文件。

  • 就是使用xml文件方式,不使用properties文件和@EnableDubbo注解(直接在xml文件中配置了各种类,也不需要在用注解或者注解扫描了)来配置了。

  • 唯一注意的是,因为是xml文件方式,所以我们需要将xml文件中的各种配置,导入到springboot的ioc容器中,使用@ImportResource(locations = “xxx”)来将dubbo的配置文件导入:

@ImportResource(locations = "classpath:consumer.xml")
@ImportResource(locations = "classpath:provider.xml")

//就像下面直接在springboot主程序上面配置就可以
package com.itholmes.gmall;

import com.alibaba.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;

@ImportResource(locations = "classpath:provider.xml")
@SpringBootApplication
public class BootUserServiceProviderApplication 

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




方式三:使用注解API的方式

  • 将每一个组件通过@Bean的方式手动创建到容器中。

可以直接使用注册来定义配置类:

  • 例如:对服务提供者进行配置类。
package com.itholmes.gmall.config;

import com.alibaba.dubbo.config.*;
import com.itholmes.gmall.service.UserService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.ArrayList;

@Configuration
public class MyDubboConfig 

    //下面相当于<dubbo:application name="user-service-provider"></dubbo:application>
    @Bean
    public ApplicationConfig applicationConfig()
        ApplicationConfig applicationConfig = new ApplicationConfig();
        //1.指定当前服务(也就是应用的名字)(同样的服务名字相同,不要和别的服务同名)
        applicationConfig.setName("user-service-provider");
        return applicationConfig;
    

    //下面相当于<dubbo:registry protocol="zookeeper" address="127.0.0.1:2181" />
    @Bean
    public RegistryConfig registryConfig()
        //2.指定注册中心的位置,官方有两种写法
        RegistryConfig registryConfig = new RegistryConfig();
        registryConfig.setProtocol("zookeeper");
        registryConfig.setAddress("127.0.0.1:2181");
        return registryConfig;
    

    //下面相当于<dubbo:protocol name="dubbo" port="20880"></dubbo:protocol>
    @Bean
    public ProtocolConfig protocolConfig() 
        //3.指定通信规则(指定通信协议和通信端口) 协议有很多可以去官方协议手册查看,目前使用dubbo协议。
        ProtocolConfig protocolConfig = new ProtocolConfig();
        protocolConfig.setName("dubbo");
        protocolConfig.setPort(20880);
        return protocolConfig;
    

    /**
     *  下面相当于:
     * 	<dubbo:service
     * 		interface="com.itholmes.gmall.service.UserService"
     * 		ref="userServiceImpl01"
     * 		timeout="5000"
     * 		version="1.0.0"
     * 	>
     * 		<dubbo:method name="getUserAddressList" timeout="1000"></dubbo:method>
     * 	</dubbo:service>
     */
    @Bean
    public ServiceConfig<UserService> serviceConfig(UserService userService)

        //4.配置dubbo的service
        ServiceConfig<UserService> serviceConfig = new ServiceConfig<>();
        serviceConfig.setInterface(UserService.class);
        serviceConfig.setRef(userService);
        serviceConfig.setTimeout(5000);

        //配置每一个method的信息
        //<dubbo:method name="getUserAddressList" timeout="1000"></dubbo:method>
        MethodConfig methodConfig = new MethodConfig();
        methodConfig.setName("getUserAddressList"Dubbo 学习笔记总结

dubbo的本地存根(Stub)

Dubbo本地存根是什么,Dubbo本地伪装又是什么?

dubbo之本地存根

10.Dubbo配置-重试,超时(集群容错),启动检查,多版本,本地存根

dubbo源码阅读-ProxyFactory之StubProxyFactoryWrapper本地存根