dubbo使用总结

集群模式下的容错模式

集群模式下,调用服务失败时的容错机制
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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,367评论 6 512
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,959评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,750评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,226评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,252评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,975评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,592评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,497评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,027评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,147评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,274评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,953评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,623评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,143评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,260评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,607评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,271评论 2 358

推荐阅读更多精彩内容

  • dubbo.xsd 文件说明 当我们要使用Dubbo进行 配置时,需要像下面那样引入dubbo.xsd这个文件. ...
    Mis_Gtw阅读 1,104评论 0 1
  • Java继承关系初始化顺序 父类的静态变量-->父类的静态代码块-->子类的静态变量-->子类的静态代码快-->父...
    第六象限阅读 2,159评论 0 9
  • 昨天她毕业了,穿上学士服,领了学位证书,拍完了毕业照,傍晚就赶回了住处,因为明天要上班。 出乎意料的是,在门外面她...
    雪地单衣阅读 237评论 0 0
  • 8天饮食计划: 早餐:猕猴桃/西瓜/葡萄柚或梨,榨汁+燕麦片 零食:一块水果+450g水 午餐:沙拉或煮蔬菜 零食...
    11_0f11阅读 440评论 0 1
  • 第五章 作用域与作用域链 1. 作用域 常见的作用域有两种,全局作用域和函数作用域。ES6中新增了块级作用域。全局...
    BeLLESS阅读 735评论 0 0