dubbo总结

8 篇文章 0 订阅

集群模式下的容错模式

集群模式下,调用服务失败时的容错机制
1、默认是failover,重试机制,默认是两次。通常可用于读操作
2、failfast,快速失败模式,当调用失败时候就报错,通常用于写操作
3、failsafe,失败安全模式,当调用失败时直接忽略。通常用于写入日志等操作。
默认情况下,是failover模式,这时候可以只配retries="0"或者“2”等,来实现是重试几次还是重试0次(这个时候就是failfast模式)

负载均衡

1、随机策略。根据权重设置随机概率,这是默认策略
2、轮询策略。这会导致机子慢的服务器积累请求的问题
3、最小活跃调用数,使慢的机子收到更少的请求
4、hash一致性,相同的请求总是会调用同一台机子的服务器。一般默认是第一个参数的hash值

##线程模型
如果事件处理的逻辑能够在io线程中迅速处理完,就在io线程中处理,否则放到线程池中。
dispatcher:
all :所有的消息都派发到线程池,包括请求、响应,连上事件、断开事件,心跳等;
direct:直接在io线程上处理;
message:请求响应消息派发到线程池,其他的断开连接事件,心跳等在io上处理;
execution:只有请求消息派发到线程池
connection:在io线程上,将连接断开事件放入队列,有序逐个执行,其他的消息派发到线程池
threadpool:
fixed: 固定大小线程池,启动时建立线程,不关闭,一直持有,通过threads设置数量
cached:缓存线程池,空闲一分钟自动删除;
limited:可伸缩线程池,值增加不收缩
如果使用了direct,而发现一个请求长时间等待,其他的请求也因此阻塞时,应该考虑在消费端设置connections的数量或者服务端的accepts的数量。io线程的大小默认是cpu数量+1。大概就是这三个原因

inux 用户线程数限制导致的 java.lang.OutOfMemoryError: unable to create new native thread异常

系统默认最大的线程数为1024个

[root@edu-provider-01 ~]# cat /etc/security/limits.d/90-nproc.conf
Default limit for number of user’s processes to prevent
accidental fork bombs.
See rhbz #432903 for reasoning.

  •      soft    nproc     1024
    

root soft nproc unlimited

[root@edu-provider-01 ~]# vi /etc/security/limits.d/90-nproc.conf
调整时要注意:

1、 尽量不要使用 root 用户来部署应用程序,避免资源耗尽后无法登录操作系统。

因为root用户默认没有限制线程数,如果线程过多,会使资源占用很多,导致不能关机,只能硬关机

2、 普通用户的线程数限制值要看可用物理内存容量来配置

[root@edu-provider-01 ~]# cat /proc/meminfo |grep MemTotal
MemTotal: 2941144 kB
[root@edu-provider-01 ~]# echo “2941144/128”|bc
22977
[root@edu-provider-01 ~]# ulimit -u
1024
[1]+ Stopped vi /etc/security/limits.d/90-nproc.conf
[root@edu-provider-01 ~]# vi /etc/security/limits.d/90-nproc.conf
[root@edu-provider-01 ~]# cat /etc/security/limits.d/90-nproc.conf
Default limit for number of user’s processes to prevent
accidental fork bombs.
See rhbz #432903 for reasoning.

  •      soft    nproc     12000
    

root soft nproc unlimited
[root@edu-provider-01 ~]#

计算方式:

default_nproc = total_memory/128K;

$ cat /proc/meminfo |grep MemTotal

$ echo “2941144/128”|bc

$ ulimit -u

ulimit -a # 显示目前资源限制的设定

ulimit -u # 用户最多可开启的程序数目

重启,使之生效:# reboot

dubbo直连服务

在消费端<dubbo:reference retries=“0” interface=“cn.andy.dubbo.DataService” id=“dataService” check=“false” connections=“1” url=“dubbo://192.168.86.1:20880”/>进行配置,可以不通过注册中心直连服务。此时在dubbo-admin控制台将服务禁用后,还是能连上服务。

dubbo的参数回调

回调的定义

客户端调用服务端的摸个方法A,然后在服务端的方法中又反过来调用客户端的某个方法B,对于客户端来说,这个B就叫回调函数。这样,服务端就有机会调用客户端的方法,以便可以实现客户端的定制逻辑。比如我们的按钮事件,我们在按钮事件的回调方法里实现我们定制的逻辑(按钮事件触发后需要完成什么工作),然后按钮事件触发后,就会实现我们的定制逻辑。

本地回调的实现:

步骤:
1、定义接口,作为服务端的一个变量存在。(或者这个接口将作为参数传递到服务端的方法中)

    public interface EcgViewInterface {

    void onError(Exception e);
    void onShowMessage(String t,int i);
}
    ```
    2、在服务端定义接口参数(或者方法中的参数),在服务端方法中调用此接口的方法。
    ```
     public void AutoResize()
    {
        if (n_aStep == 1)
        {
            //波形的幅度小于画布高度,并且波形幅度的2倍大于画布高度,说明波形幅度合适,此时只要调整基线
            if ((y_max - y_min) * 2 >= by && (y_max - y_min) <= by)
                n_aStep = 2;
            else
            {
                if (y_max - y_min >= by)       //表示波形范围超过画布高度
                {
                    change_nV = change_nV*2;
                    listener.onShowMessage(change_nV+"",1);  //在这里进行接口回调

                }
                else if ((y_max - y_min) * 2 <= by)   //如果波形幅度的两倍都小于画布高度,说明波形幅度过小,需要波形像素调整放大
                {
                    change_nV = change_nV/2;
                    listener.onShowMessage(change_nV+"",1);

                }

                y_max = -3*by;
                y_min =3*by;
                return;
            }
        }

        if (n_aStep == 2)
        {
            n_top = (by - (y_max + y_min)) / 2;
            this.change_y += n_top * change_nV/ change_50n;
        }
            b_autoResize = false;
    }

3、在客户端实现回调接口的实现,并将此接口传入服务端

  private EcgViewInterface ecgViewListener=new EcgViewInterface() {
      @Override
      public void onError(Exception e) {

      }

      @Override
      public void onShowMessage(String t, int i) {
            Log.i("tag", "心电接口回调--》" + t);
            if (i==0){
                tv_ecg_cell_time.setText("时间:"+t+"ms/格");
            }else if (i==1){
                tv_ecg_cell_voltage.setText("电压:"+t+"mv/格");
            }
      }
  };

然后传给服务器端

ecgWaveView1.setListener(ecgViewListener);

dubbo中的参数回调

dubbo的参数回调,只需在在spring的配置文件中声明哪个参数是callback类型的即可。
1、先定义回调的接口

/**
 * @author sks
 *这个listener就是回调的接口。里面的方法就是客户端来实现的。
 */
public interface CallbackListener2 {
	
	void onShowMessage(String t, int i);

}

2、定义服务端和客户端公用的接口,在接口中定义如何传入回调接口。

public interface CallbackService2 {
	
	//在这里考虑如何传入listener。作为方法传入或者作为一个参数传入
	
	//先考虑作为方法的参数传入
	
	void addListener(CallbackListener2 listener2);

}

3、服务端实现CallbackService2接口。同时定义一个会调用回调接口的方法。这里为了简单,直接在构造方法中,定义一个每过5s都会调用回调接口的逻辑。

@Service
public class CallbackService2Impl implements CallbackService2 {
	
	/**
	 * 
	 */
	public CallbackService2Impl() {
		super();
		new Thread(new Runnable() {
			
			@Override
			public void run() {
				// TODO Auto-generated method stub
				while (true) {
					if (listener2!=null) {
						listener2.onShowMessage("服务端回调客户端的方法", 0);
					}
					
					try {
						Thread.sleep(5000);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					
				}
				
				
			}
		}).start();
	}

	private CallbackListener2 listener2;
	
	//在服务端某个方法中会用到回调接口。这里为了简单,直接在构造方法中实现
	
	

	/* (non-Javadoc)
	 * @see cn.andy.dubbo.CallbackService2#addListener(cn.andy.dubbo.CallbackListener2)
	 * 服务端提供方法用户客户端传入回调接口
	 */
	@Override
	public void addListener(CallbackListener2 listener2) {
		// TODO Auto-generated method stub
		this.listener2=listener2;
	}

}

4、在xml配置文件中,对有回调接口参数的方法进行配置

<dubbo:service retries="0" interface="cn.andy.dubbo.CallbackService2" ref="callbackService2Impl" timeout="60000" >
		<dubbo:method name="addListener">
		<!--addListener的第0个参数是回调接口  -->
			<dubbo:argument index="0" callback="true"/>
		</dubbo:method>	
	</dubbo:service>
		

5、在客户端的工程中,在java代码中

	/*
	 * 客户端传递回调接口给服务端
	 */
	@RequestMapping("/user/getData4")
	@ResponseBody
	private String getData4(HttpServletRequest request){
		
		callbackService2.addListener(new CallbackListener2() {
			
			@Override
			public void onShowMessage(String t, int i) {
				// TODO Auto-generated method stub
				System.out.println(t);
			}
		});
	    
	      
		return "success2-->";
	}

}

6、客户端的dubboxml文件正常配置callbackService2

<dubbo:reference retries="0" interface="cn.andy.dubbo.CallbackService2" id="callbackService2" check="false"   >	

7、结果

服务端回调客户端的方法
服务端回调客户端的方法
服务端回调客户端的方法
服务端回调客户端的方法

dubbo的事件通知

dubbo的事件通知:在调用之前、之后或者异常时会触发 oninvoke、onreturn和onthrow三个时间。这个和spring的aop功能比较类似。
在消费端:定义通知接口和实现类

public interface Notify {
	

	
	public void onthrow(Throwable e,Object... args);

	/**
	 * @param res
	 * @param args
	 */
	void onreturn(Object res, Object[] args);

}
@Component
public class NotifyImpl implements Notify {

	/* (non-Javadoc)
	 * @see cn.andy.callback.Notify#onreturn()
	 */
	@Override
	public void onreturn(Object res, Object... args) {
		// TODO Auto-generated method stub
		 System.out.println("返回值:"+res);
	        for (Object object : args) {
	            System.out.println("参数:"+object);
	        }
	}

	/* (non-Javadoc)
	 * @see cn.andy.callback.Notify#onthrow(java.lang.Throwable)
	 */
	@Override
	public void onthrow(Throwable e,Object... args) {
		// TODO Auto-generated method stub
		 System.out.println("异常:"+e.getMessage());
	        for (Object object : args) {
	            System.out.println("异常参数:"+object);
	        }
	}

}

在配置文件中进行配置

<!--通知类必须手动的在xml文件进行实例化  -->
<bean id="notify" class="cn.andy.callback.NotifyImpl"></bean>
	
	 
	 <!-- 引用dubbo服务 -->
	<dubbo:application name="dubboTest-test-web"/>
	
	<dubbo:registry protocol="zookeeper" address="192.168.25.128:2181"/>
	<!--通过retries=0或者2来决定重试次数。 默认是配了cluster="failover"  -->
	<dubbo:reference retries="0" interface="cn.andy.dubbo.DataService" id="dataService" check="false" connections="5"  >
	<!--在调用dubboTest方法时,结果返回会自动调用onreturn方法,异常会调用nothrow方法-->
			<dubbo:method name="dubboTest" async="true" onreturn="notify.onreturn" onthrow="notify.onthrow">
				
			</dubbo:method>
	</dubbo:reference>
	
	<dubbo:reference retries="0" interface="cn.andy.dubbo.CallbackService" id="callbackService" check="false"   />
	
	<dubbo:reference retries="0" interface="cn.andy.dubbo.CallbackService2" id="callbackService2" check="false"   >	
	</dubbo:reference>

事件通知有一个注意点是:通知类必须在xml文件中手动实例化,而自动扫描的方式会报找不到notify’这个类实例的错误。

Dubbo 本地伪装

dubbo本地伪装用于当服务down之后,客户端不抛出异常,而是转而调用mock实现的逻辑。其中,mock类的实现要和接口放在一起!

public interface DataService {
	
	int dubboTest(String id);
	
	int dubboTest2(String id);
	
	String getStringData();

}

然后是基于DataService实现的mock类,其命名是接口+Mock

public class DataServiceMock implements DataService{

	/* (non-Javadoc)
	 * @see cn.andy.dubbo.DataService#dubboTest(java.lang.String)
	 */
	@Override
	public int dubboTest(String id) {
		// TODO Auto-generated method stub
		return 10086;
	}

	/* (non-Javadoc)
	 * @see cn.andy.dubbo.DataService#dubboTest2(java.lang.String)
	 */
	@Override
	public int dubboTest2(String id) {
		// TODO Auto-generated method stub
		return 10086;
	}

	/* (non-Javadoc)
	 * @see cn.andy.dubbo.DataService#getStringData()
	 */
	@Override
	public String getStringData() {
		// TODO Auto-generated method stub
		return "mock result";
	}

}

在服务端的dubbo的xml中进行mock配置

	<dubbo:service retries="0" interface="cn.andy.dubbo.DataService" ref="dataServiceImpl" timeout="60000" mock="true"/>

当服务端程序down了之后,客户端调用

	@RequestMapping("/user/getStringData")
	@ResponseBody
	private String getStringData(HttpServletRequest request){

	      String data = dataservice.getStringData();
	        
			return "success2-->"+data;
	}

结果是success2–>mock result。说明没有抛出异常,转而调用其mock的逻辑。

dubbo令牌验证

令牌验证是用来放在消费端避开注册中心通过直连方式连接消费端。通过在服务端设置token,如果消费程序没有通过token验证,就不能直连服务端。

1、在服务端,设置token。

	<dubbo:service retries="0" interface="cn.andy.dubbo.DataService" ref="dataServiceImpl" timeout="60000" mock="true"  token="1234567" />

2、在dubbo管控台,将此服务禁用。
3、在消费端调用服务端的程序前,先通过隐式传参,将token的值传进去,完成调用

       RpcContext.getContext().setAttachment("token", "1234567");
	     String data = dataservice.getStringData();

如果没有 RpcContext.getContext().setAttachment(“token”, “1234567”);,那么会报错。显示invalied token。

dubbo的自定义标签

https://my.oschina.net/lenglingx/blog/889662

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值