欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Dubbo配置_2

程序员文章站 2022-03-26 18:24:29
配置的官方网址http://dubbo.apache.org/zh-cn/docs/user/configuration/xml.html1、配置原则1 .properties加载顺序1-1dubbo.properties 加载顺序 优先1,其次2 ,最后3上面图中的顺序对应下面的3中情况1.JVM 启动 -D 参数优先,这样可以使用户在部署和启动时进行参数重写,比如在启动时需改变协议的端口。2.XML 次之,如果在 XML 中有配置,则 dubbo.properties 中的....

配置的官方网址http://dubbo.apache.org/zh-cn/docs/user/configuration/xml.html

1、配置原则

1 .properties加载顺序

Dubbo配置_2

1-1dubbo.properties 加载顺序 优先1,其次2 ,最后3 

上面图中的顺序对应下面的3中情况

1.JVM 启动 -D 参数优先,这样可以使用户在部署和启动时进行参数重写,比如在启动时需改变协议的端口。

2.XML 次之,如果在 XML 中有配置,则 dubbo.properties 中的相应配置项无效。相当于和spring整合项目里的provider.xml,与springboot整合的application.properties文件

3.Properties 最后,相当于缺省值,只有 XML 没有配置时,dubbo.properties 的相应配置项才会生效,通常用于共享公共配置,比如应用名

为了便于测试效果,我们在boot-user-service-provider项目中创建一个dubbo.properties文件

Dubbo配置_2

我们只修改对应的端口号,便于区分

1.虚拟机参数 -Ddubbo.protocol.port=20880

Dubbo配置_2

2.application.properties文件中的修改 

Dubbo配置_2

3.dubbo.properties文件中的配置 只需配置一行端口号

dubbo.protocol.port=20882

运行启动程序 开后台日志信息

1.设计虚拟机参数 ,对应的两个配置文件也配置好了,优先加载的20880 虚拟机参数是优先

Dubbo配置_2

2. 删除虚拟机参数,看另外两个的顺序,先加载application.properties 文件

Dubbo配置_2

3.注释掉application.properties文件中的配置 ,最后加载的是dubbo.properties文件

Dubbo配置_2

2、启动时检查

      Dubbo 缺省会在启动时检查依赖的服务是否可用,不可用时会抛出异常,阻止 Spring 初始化完成,以便上线时,能及早发现问题,默认 check="true"

可以通过 check="false" 关闭检查,调用的时候才回去检查调用的服务是否启动,比如,测试时,有些服务不关心,或者出现了循环依赖,必须有一方先启动。

另外,如果你的 Spring 容器是懒加载的,或者通过 API 编程延迟引用服务,请关闭 check,否则服务临时不可用时,会抛出异常,拿到 null 引用,如果 check="false",总是会返回引用,当服务恢复时,能自动连上。

Dubbo配置_2

如图即使我们注释掉了user-service-consumer 项目中的条用的代码,依然是报错的

当我们修改配置comsumer.xml文件中 增加check="false" 这个配置再看控制台的消息

    <!-- 调用的服务 -->
    <dubbo:reference id="userService" interface="com.atguigu.gmail.service.UserService"
    check="false"/>

Dubbo配置_2

可以看到增加一段配置后控制台没有报错了

这个只是一个消费服务这的服务不检查,如果实际的项目的服务消费者比较多,我们一一的配置比较麻烦,还有一个中同一配置消费服务不检查的配置还是在consumer.xml文件中 增加,效果和上面的是一样

<!-- 配置当前消费者同一规则:所有的服务都不检查 -->
    <dubbo:consumer check="false"></dubbo:consumer>

3、超时时间

由于网络或服务端不可靠,会导致调用出现一种不确定的中间状态(超时)。为了避免超时导致客户端资源(线程)挂起耗尽,必须设置超时时间。timeout 设置超时时间

我们以user-serivce-provider 和user-service-consumer项目为测试时案例

consumer.xml文件中设置超时时间为 假设第一次没有设置超时时间

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
		http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd
		http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
   
    <context:component-scan base-package="com.atguigu.gmail.service.impl"></context:component-scan>
	<!-- 服务名称 -->
    <dubbo:application name="order-service-consumer"/>
    
    <!--  注册中心地址 -->
    <dubbo:registry address="zookeeper://10.5.96.48:2181"/>
    
    <!-- 调用的服务 -->
    <!-- timeout="0" 超时  默认是1000豪秒-->
    <dubbo:reference  interface="com.atguigu.gmail.service.UserService"
    id="userService"/>
    
    <!-- 配置当前消费者同一规则:所有的服务都不检查 -->
    <dubbo:consumer check="false"></dubbo:consumer>

   <!-- 配置监控中心 -->
	<!--  下面的两种都可以 -->
	<!--  ① 是默认配置自动发现 -->
	<!--  ② 直连监控中心-->
	<!--  <dubbo:monitor protocol="registry"></dubbo:monitor> -->
	<dubbo:monitor address="127.0.0.1:7070"></dubbo:monitor>
</beans>

我们让服务提供者睡4秒

package com.atguigu.gmail.service.impl;

import java.util.Arrays;

import java.util.List;

import com.atguigu.gmail.bean.UserAddress;
import com.atguigu.gmail.service.UserService;

public class UserServiceImpl implements UserService {

	public List<UserAddress> getUserAddressList(String userId) {
		UserAddress address1 = new UserAddress(1,"东长安街89号","1","李老师","13278977","1");
		UserAddress address2 = new UserAddress(2,"西长安街89号","1","李老师","13278977","1");
		try {
			Thread.sleep(4000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return Arrays.asList(address1,address2);
	}

}

运运行服务的提供者,先注册到注册中心,在运行服务的消费者,代码前面都写过就不贴了,

Dubbo配置_2

报错,我们并没有设置超时时间,可是依然报超时1000ms ,这是因为timeout的超时时间默认是1000豪秒

第二次我们设置超时时间是5000ms

 <!-- 调用的服务 -->
    <!-- timeout="0" 超时 -->
    <dubbo:reference  interface="com.atguigu.gmail.service.UserService"
    id="userService" timeout="5000"/>

看运行结果,这次就补贴图了,可以自己验证,可以调用成功

超时的优先级别图,有上到下优先级别,先方法①,后接口②,全局最后③  ,每个级别都是对应的消费方优先

Dubbo配置_2

服务消费者还可以这样配置超时时间,指定方法名,和方法的超时时间 ,和全局的配置

 <!-- 调用的服务 -->
    <!-- timeout="0" 超时 -->
    <dubbo:reference  interface="com.atguigu.gmail.service.UserService"
    id="userService" timeout="5000">
        <!-- 可以指定方法名,也可以指定超时时间 -->
    	<dubbo:method name="getUserAddressList" timeout="1000"></dubbo:method>
    </dubbo:reference>
    
    <!-- 配置当前消费者同一规则:所有的服务都不检查 -->
    <dubbo:consumer check="false" timeout="5000"></dubbo:consumer>

服务提供者也可以设置超时时间

<!-- 4 暴露服务 ref 指向服务的真正实现对象  -->
	<dubbo:service interface="com.atguigu.gmail.service.UserService"
	 ref="userServiceImpl" timeout="1000"></dubbo:service>

超时规则

1.精确优先(方法级优先,接口次之,全局配置再次之)

2.消费者设置优先(如果级别一样,则消费方优先,提供方次之)

案例 :如果我们在提供方配置设置方法级别的超时时间2000ms,服务消费方接口设置超时时间4000ms ,这样的配置依然会报超时错误,因为优先的级别是按照上面的图,先方法级别,接口级别的生效方式

4、重试次数

失败自动切换,当出现失败,重试其它服务器,但重试会带来更长延迟。可通过 retries="3" 来设置重试次数(不含第一次)一共就是4次。一般配合的是timeout使用

 <!-- 调用的服务 -->
    <!-- timeout="0" 超时 -->
    <!-- retires=“” 重试次数,不包含第一次 -->
    <dubbo:reference  interface="com.atguigu.gmail.service.UserService"
    id="userService" timeout="5000" retries="3">
    </dubbo:reference>

这里有一个说明 就是幂等操作和非幂等操作

1.幂等操作(设置重置次数)【查询、修改、删除】 这些操作的结果是相同的

2.非幂等操作(不能设置重置次数)【新增】因为有可能在超时时间内,这一次操作已经发送给数据库,只不过还没有执行完成,重试后可能插入相同的数据很多次

 5、版本号

当一个接口实现,出现不兼容升级时,可以用版本号过渡,版本号不同的服务相互间不引用。

可以按照以下的步骤进行版本迁移:

0.在低压力时间段,先升级一半提供者为新版本

1.再将所有消费者升级为新版本

2.然后将剩下的一半提供者升级为新版本

代码实现

我们创建两个版本的UserServiceImple 一个是如图

Dubbo配置_2

UserServiceImpl.java代码  这个是旧版本代码


public class UserServiceImpl implements UserService {
	public List<UserAddress> getUserAddressList(String userId) {
		System.out.println("UserServiceImpl...old");
		UserAddress address1 = new UserAddress(1,"东长安街89号","1","李老师","13278977","1");
		UserAddress address2 = new UserAddress(2,"西长安街89号","1","李老师","13278977","1");
		
		return Arrays.asList(address1,address2);
	}
}

UserServiceImpl2.java代码 这个是新版本代码

public class UserServiceImpl2 implements UserService {

	public List<UserAddress> getUserAddressList(String userId) {
		System.out.println("UserServiceImpl...new");
		UserAddress address1 = new UserAddress(1,"东长安街89号","1","李老师","13278977","1");
		UserAddress address2 = new UserAddress(2,"西长安街89号","1","李老师","13278977","1");
		
		return Arrays.asList(address1,address2);
	}
}

我们在provider.xml文件中进行配置版本  其他的代码不动,只增加了dubbo对外暴露的服务和实例bean

<!-- 4 暴露服务 ref 指向服务的真正实现对象  -->
	<dubbo:service interface="com.atguigu.gmail.service.UserService" 
	ref="userServiceImpl01" version="1.0.0"></dubbo:service>
	
	<bean class="com.atguigu.gmail.service.impl.UserServiceImpl" 
	id="userServiceImpl01" ></bean>
	
	<dubbo:service interface="com.atguigu.gmail.service.UserService" 
	ref="userServiceImpl02" version="2.0.0"></dubbo:service>
	
	<bean class="com.atguigu.gmail.service.impl.UserServiceImpl2"
	id="userServiceImpl02"></bean>

我们在消费者服务的配置之中增加对应的调用的服务consumer.xml 在<dubbo:reference > 标签中增加了version="1.0.0" 

①启动服务提供者主启动类ProviderMainApplication,然后在启动消费者主启动类ConsumerMainApplication

②修改consumer.xml 在<dubbo:reference > 标签中增加了version="2.0.0",然后在启动消费者主启动类ConsumerMainApplication

  <!-- 调用的服务 -->
    <!-- timeout="0" 超时 -->
    <dubbo:reference  interface="com.atguigu.gmail.service.UserService"
    id="userService" timeout="5000" retries="3" version="1.0.0">
        <!-- 可以指定方法名,也可以指定超时时间 -->
    	<dubbo:method name="getUserAddressList" timeout="1000"></dubbo:method>
    </dubbo:reference>

两次操作截图

Dubbo配置_2

我们可以看到ProviderMainApplication控制台的两次调用的日志,第一次对应的是旧版本的服务,第二次是新版本的服务,这样就可以控制我们调用服务对于版本的控制了。如果我们在consumer.xml 中配置version="*"调用的版本就是随机的

6、本地存根

远程服务后,客户端通常只剩下接口,而实现全在服务器端,但提供方有些时候想在客户端也执行部分逻辑,比如:做 ThreadLocal 缓存,提前验证参数,调用失败后伪造容错数据等等,此时就需要在 API 中带上 Stub,客户端生成 Proxy 实例,会把 Proxy 通过构造函数传给 Stub [1],然后把 Stub 暴露给用户,Stub 可以决定要不要去调 Proxy。

Dubbo配置_2

consumer.xml代码 增加一个本地存个属性

 <!-- 调用的服务 -->
    <!-- timeout="0" 超时 -->
    <dubbo:reference  interface="com.atguigu.gmail.service.UserService"
    id="userService" timeout="5000" retries="3" version="1.0.0"
    stub="com.atguigu.gmail.service.impl.UserServiceStub">

创建一个本地存根的实现类UserServiceIStub.java

Dubbo配置_2

构造方法传入的远程服务的代理对象,实现接口的方法中可以增加一些验证,缓存或是其他的代码,通过就可以通过代理对象调用远程的服务,否则不调用了。 

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("UserServiceStub...");
		//在这个验证之前我们可以实现一些需要的业务验证
		if(StringUtils.isEmpty(userId)){
			//此时代理对象调用远程服务的
			return userService.getUserAddressList(userId);
		}
		return null;
	}
}

 7Dubbo与SpringBoot 整合的三种方法

      1)导入dubbo-starter,在application.properties配置属性,使用@Service【暴露服务】使用@Reference【应用服务】这种方式一定要在SpringBootApplication 上增加@EnableDubbo 开启基于注解的配置

      2)导入dubbo-starter,保留dubbo.xml配置文件

             将application.properties文件中的配置都注释掉,也就是相当于provider.xml文件放入到resource资源目录下,暴露服务上面@Service注解也可以去掉了

Dubbo配置_2

3)使用注解API的方式

            将每一个组件创建到容器中 项目结构如图

 Dubbo配置_2

写一个配置类MyDubboConfig.java 对应的Bean 也就是provider.xml 的配置

@Configuration
public class MyDubboConfig {
	
	/**
	 * <dubbo:application name="boot-user-service-provider">
	 * </dubbo:application>	
	 * 对应下面的代码
	 * @return
	 */
	@Bean
	public ApplicationConfig applicationConfig(){
		ApplicationConfig applicationConfig = new ApplicationConfig();
		applicationConfig.setName("boot-user-service-provider");
		return applicationConfig;	
	}
	
	/**
	 * <dubbo:registry protocol="zookeeper" address="10.5.96.48:2181">
	 * </dubbo:registry>
	 * @return
	 */
	@Bean
	public RegistryConfig registryConfig(){
		RegistryConfig registryConfig = new RegistryConfig();
		registryConfig.setProtocol("zookeeper");
		registryConfig.setAddress("10.5.96.48:2181");
		return registryConfig;
	}
	
	/**
	 * <!-- 3 指定通信规则  通信协议,通信端口-->
	<dubbo:protocol name="dubbo" port="20880"></dubbo:protocol>
	 * @return
	 */
	@Bean
	public ProtocolConfig protocolConfig(){
		ProtocolConfig protocolConfig = new ProtocolConfig();
		protocolConfig.setName("dubbo");
		protocolConfig.setPort(20882);
		return protocolConfig;
	}
	
	/**
	 * <dubbo:service interface="com.atguigu.gmail.service.UserService" 
	ref="userServiceImpl01" version="1.0.0">
	<dubbo:method name="getUserAddressList" timeout="3000"></dubbo:method>
	</dubbo:service>
	 */
	public ServiceConfig<UserService> userServiceConfig(UserService userService){
		ServiceConfig<UserService> serviceConfig = new ServiceConfig();
		serviceConfig.setInterface(UserService.class);
		serviceConfig.setRef(userService);
		serviceConfig.setVersion("1.0.0");
		
		//配置每一个method的信息
		MethodConfig methodConfig = new MethodConfig();
		methodConfig.setName("getUserAddressList");
		methodConfig.setTimeout(1000);
		
		//将method 的设置关联到service 配置中
		List<MethodConfig> methods = new ArrayList<>();
		methods.add(methodConfig);
		serviceConfig.setMethods(methods);
		return serviceConfig;
		
	}

}

 

本文地址:https://blog.csdn.net/Be_nurturing/article/details/107316105

相关标签: Dubble