Dubbo学习之(二)Dubbo负载均衡策略、集群容错策略和动态代理策略

Dubbo负载均衡策略

random loadbalance:dubbo的默认负载均衡策略,dubbo是random load balance随机调用实现负载均衡,可以对provider不同实例设置不同的权重,会按照权重来负载均衡,权重越大分配流量越高,一般就用这个默认的就可以了。

roundrobin loadbalance:默认情况是均匀地将流量打到各个机器上去,但是如果各个机器的性能不一样,容易导致性能差的机器负载过高。所以此时需要调整权重,让性能差的机器承载权重小一些,流量少一些。

leastactive loadbalance:这个就是自动感知一下,如果某个机器性能越差,那么接收的请求越少,越不活跃,此时就会给不活跃的性能差的机器更少的请求。

consistanthash loadbalance:一致性Hash算法,相同参数的请求一定分发到一个provider上去,provider挂掉的时候,会基于虚拟节点均匀分配剩余的流量,抖动不会太大。如果你需要的不是随机负载均衡,是要一类请求都到一个节点,那就走这个一致性hash策略。

Dubbo集群容错策略

failover cluster模式:尝试失败会自动切换重试其他机器,failover cluster模式集群容错策略默认设置模式,常见用于读操作,使用方式配置重试次数如下所示:

// 第一种方式

// 第二种方式

// 第三种方式

    

failfast cluster模式:一次调用失败就立即失败,常见于写操作;

failsafe cluster模式:出现异常时忽略掉,常用于不重要的接口调用,比如记录日志,常用配置方式:



OR

failbackc cluster模式:失败了后台自动记录请求,然后定时重发,多适用于写消息队列操作配置如上

forking cluster:并行调用多个provider,只要有一个成功就立即返回,通常用于实时性操作及响应速度迅速要求比较高的读操作,但是会浪费更多的服务器资源,为了避免不必要的资源浪费,通常根据权衡类比,通过“forks=2”,来设置最大并行数;

broadcacst cluster:逐个调用所有的provider,如果存在一个出错则报错(从2.1.0版本开始支持),通常用于通知所有的提供者更新缓存或日志等本地资源信息;

Dubbo动态代理策略

  • 默认使用javassist动态字节码生成,创建代理类;
  • 也可以通过spi扩展机制配置自己的动态代理策略;

javassist字节码创建动态代理:

package com.lghszz.neo;  
// 创建目标对象
public class JavassistTest{  

    private String name="test";  

    public JavassistTest(){  
        name="xiaoming";  
    }
    public String getName() {  
        return name;  
    }  
    public void setName(String name) {  
        this.name = name;  
    }  
    public void execute(){  
        System.out.println(name);  
        System.out.println("execute ok");  
    }  
} 
package com.lghszz.neo;  
import java.lang.reflect.Method;  
import java.lang.reflect.Modifier;  
  
import javassist.ClassPool;  
import javassist.CtClass;  
import javassist.CtConstructor;  
import javassist.CtField;  
import javassist.CtField.Initializer;  
import javassist.CtMethod;  
import javassist.CtNewMethod;  
/**
 * 字节码创建动态代理对象
 */
public class JavassistDemo{       
      
    public static void main(String[] args) throws Exception{  
        ClassPool cp=ClassPool.getDefault();  
        CtClass ctClass=cp.makeClass("com.lghszz.neo.JavassistTest");  
          
        StringBuffer body=null;  
        //参数  1:属性类型  2:属性名称  3:所属类CtClass  
        CtField ctField=new CtField(cp.get("java.lang.String"), "name", ctClass);  
        ctField.setModifiers(Modifier.PRIVATE);  
        //设置name属性的get set方法  
        ctClass.addMethod(CtNewMethod.setter("setName", ctField));  
        ctClass.addMethod(CtNewMethod.getter("getName", ctField));  
        ctClass.addField(ctField, Initializer.constant("test"));  
          
        //参数  1:参数类型   2:所属类CtClass  
        CtConstructor ctConstructor=new CtConstructor(new CtClass[]{}, ctClass);  
        body=new StringBuffer();  
        body.append("{\n name=\"xiaoming\";\n}");  
        ctConstructor.setBody(body.toString());  
        ctClass.addConstructor(ctConstructor);  
          
        //参数:  1:返回类型  2:方法名称  3:传入参数类型  4:所属类CtClass  
        CtMethod ctMethod=new CtMethod(CtClass.voidType,"execute",new CtClass[]{},ctClass);  
        ctMethod.setModifiers(Modifier.PUBLIC);  
        body=new StringBuffer();  
        body.append("{\n System.out.println(name);");  
        body.append("\n System.out.println(\"execute ok\");");  
        body.append("\n return ;");  
        body.append("\n}");  
        ctMethod.setBody(body.toString());  
        ctClass.addMethod(ctMethod);  
        Class c=ctClass.toClass();  
        Object o=c.newInstance();  
        Method method=o.getClass().getMethod("execute", new Class[]{});  
        //调用字节码生成类的execute方法  
        method.invoke(o, new Object[]{});  
    }  
  
}  
package com.lghszz.neo;  
import java.lang.reflect.Method;  
  
import javassist.util.proxy.MethodFilter;  
import javassist.util.proxy.MethodHandler;  
import javassist.util.proxy.ProxyFactory;  

/**
 * javassist还有一个比较常见的用途是AOP,例如对一些类统一加权限过滤、加日志监控等
 * 示例实现:对上面例子的JavassistTest类的getName()方法进行拦截前置处理
 */
public class JavassistLearn{  
      
    public static void main(String[] args) throws Exception{  
        ProxyFactory factory=new ProxyFactory();  
        //设置父类,ProxyFactory将会动态生成一个类,继承该父类  
        factory.setSuperclass(JavassistTest.class);  
        //设置过滤器,判断哪些方法调用需要被拦截  
        factory.setFilter(new MethodFilter() {  
            @Override  
            public boolean isHandled(Method m) {  
                if(m.getName().equals("getName")){  
                    return true;  
                }  
                return false;  
            }  
        });  
        //设置拦截处理  
        factory.setHandler(new MethodHandler() {  
            @Override  
            public Object invoke(Object self, Method thisMethod, Method proceed,  
                    Object[] args) throws Throwable {  
                //拦截后前置处理,改写name属性的内容  
                //实际情况可根据需求修改  
                JavassistTest obj=(JavassistTest)self;  
                obj.setName("xiaofang");  
                return proceed.invoke(self, args);  
            }  
        });  
          
        Class c=factory.createClass();  
        JavassistTest object=(JavassistTest)c.newInstance();  
        System.out.println("aop 获取目标对象名称" + object.getName());     
    }  
} 

如有披露或问题欢迎留言或者入群探讨

你可能感兴趣的:(Dubbo)