一、概念

Dubbo是一个开源的分布式服务框架,它提供了服务治理、负载均衡、容错机制等一系列功能。主要用于提高应用的性能和可扩展性,让应用间通过远程调用的方式进行通信。
通过Dubbo,可以将一个大型的应用系统拆分成多个服务,每个服务可以独立部署和升级,提高了系统的灵活性和可维护性。
Dubbo支持多种协议和传输方式,包括HTTP、REST、RMI等,同时还提供了可靠性保证、负载均衡、服务注册与发现等核心功能。
总的来说,Dubbo可以帮助企业构建分布式架构,并提供可靠的服务调用和管理机制。

二、功能介绍

通过看dubbo-2.7.1源码,我们可以看到org.apache.dubbo.config.annotation,下面提供了4个注解:@Service,@Reference,@Method和@Argument

1、@Service

@Service注解用于将一个类标记为Dubbo服务的提供者。在需要暴露服务的类上添加该注解,并配置相应的接口,Dubbo会自动将该类实现的接口注册为一个Dubbo服务。

注解源码如下:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Inherited
public @interface Service {

    /**
     * Interface class, default value is void.class
     */
    Class<?> interfaceClass() default void.class;

    /**
     * Interface class name, default value is empty string
     */
    String interfaceName() default "";

    /**
     * Service version, default value is empty string
     */
    String version() default "";

    /**
     * Service group, default value is empty string
     */
    String group() default "";

    /**
     * Service path, default value is empty string
     */
    String path() default "";

    /**
     * Whether to export service, default value is true
     */
    boolean export() default true;

    /**
     * Service token, default value is false
     */
    String token() default "";

    /**
     * Whether the service is deprecated, default value is false
     */
    boolean deprecated() default false;

    /**
     * Whether the service is dynamic, default value is false
     */
    boolean dynamic() default false;

    /**
     * Access log for the service, default value is ""
     */
    String accesslog() default "";

    /**
     * Maximum concurrent executes for the service, default value is 0 - no limits
     */
    int executes() default 0;

    /**
     * Whether to register the service to register center, default value is true
     */
    boolean register() default true;

    /**
     * Service weight value, default value is 0
     */
    int weight() default 0;

    /**
     * Service doc, default value is ""
     */
    String document() default "";

    /**
     * Delay time for service registration, default value is 0
     */
    int delay() default 0;

    /**
     * @see Service#stub()
     * @deprecated
     */
    String local() default "";

    /**
     * Service stub name, use interface name + Local if not set
     */
    String stub() default "";

    /**
     * Cluster strategy, legal values include: failover, failfast, failsafe, failback, forking
     */
    String cluster() default "";

    /**
     * How the proxy is generated, legal values include: jdk, javassist
     */
    String proxy() default "";

    /**
     * Maximum connections service provider can accept, default value is 0 - connection is shared
     */
    int connections() default 0;

    /**
     * The callback instance limit peer connection
     *
     * @see Constants#DEFAULT_CALLBACK_INSTANCES
     */
    int callbacks() default Constants.DEFAULT_CALLBACK_INSTANCES;

    /**
     * Callback method name when connected, default value is empty string
     */
    String onconnect() default "";

    /**
     * Callback method name when disconnected, default value is empty string
     */
    String ondisconnect() default "";

    /**
     * Service owner, default value is empty string
     */
    String owner() default "";

    /**
     * Service layer, default value is empty string
     */
    String layer() default "";

    /**
     * Service invocation retry times
     *
     * @see Constants#DEFAULT_RETRIES
     */
    int retries() default Constants.DEFAULT_RETRIES;

    /**
     * Load balance strategy, legal values include: random, roundrobin, leastactive
     *
     * @see Constants#DEFAULT_LOADBALANCE
     */
    String loadbalance() default Constants.DEFAULT_LOADBALANCE;

    /**
     * Whether to enable async invocation, default value is false
     */
    boolean async() default false;

    /**
     * Maximum active requests allowed, default value is 0
     */
    int actives() default 0;

    /**
     * Whether the async request has already been sent, the default value is false
     */
    boolean sent() default false;

    /**
     * Service mock name, use interface name + Mock if not set
     */
    String mock() default "";

    /**
     * Whether to use JSR303 validation, legal values are: true, false
     */
    String validation() default "";

    /**
     * Timeout value for service invocation, default value is 0
     */
    int timeout() default 0;

    /**
     * Specify cache implementation for service invocation, legal values include: lru, threadlocal, jcache
     */
    String cache() default "";

    /**
     * Filters for service invocation
     *
     * @see Filter
     */
    String[] filter() default {};

    /**
     * Listeners for service exporting and unexporting
     *
     * @see ExporterListener
     */
    String[] listener() default {};

    /**
     * Customized parameter key-value pair, for example: {key1, value1, key2, value2}
     */
    String[] parameters() default {};

    /**
     * Application spring bean name
     */
    String application() default "";

    /**
     * Module spring bean name
     */
    String module() default "";

    /**
     * Provider spring bean name
     */
    String provider() default "";

    /**
     * Protocol spring bean names
     */
    String[] protocol() default {};

    /**
     * Monitor spring bean name
     */
    String monitor() default "";

    /**
     * Registry spring bean name
     */
    String[] registry() default {};

    /**
     * Service tag name
     */
    String tag() default "";

    /**
     * methods support
     * @return
     */
    Method[] methods() default {};
}

常用属性说明:

  • interface:指定实现的接口类,用于指定要发布的服务接口。包括2中方式,interfaceClass和interfaceName。
  • version:指定服务的版本号,用于支持多个版本的服务并存。
  • group:指定服务的分组,用于区分不同的服务实现。
  • cluster:指定集群容错策略,用于处理服务提供者的故障和网络异常。
  • actives:指定最大并发调用数,用于限制服务的并发访问量。
  • executes:指定服务的最大线程池大小,用于限制服务的并发处理能力。

使用的话,类似org.springframework.stereotype.Service,示例如下:

 @Service(interfaceClass=ForlanService.class,timeout = 300000)
 public class ForlanServiceImpl implements ForlanService{
     // 实现接口方法
 }

2、@Reference

@Reference注解用于将一个接口的引用注入到当前类中,在需要使用Dubbo服务的地方添加该注解,并配置相应的接口,Dubbo会自动将该接口的一个远程代理注入到当前类中。

注解源码如下:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE})
public @interface Reference {
    /**
     * Interface class, default value is void.class
     */
    Class<?> interfaceClass() default void.class;

    /**
     * Interface class name, default value is empty string
     */
    String interfaceName() default "";

    /**
     * Service version, default value is empty string
     */
    String version() default "";

    /**
     * Service group, default value is empty string
     */
    String group() default "";

    /**
     * Service target URL for direct invocation, if this is specified, then registry center takes no effect.
     */
    String url() default "";

    /**
     * Client transport type, default value is "netty"
     */
    String client() default "";

    /**
     * Whether to enable generic invocation, default value is false
     */
    boolean generic() default false;

    /**
     * When enable, prefer to call local service in the same JVM if it's present, default value is true
     */
    boolean injvm() default true;

    /**
     * Check if service provider is available during boot up, default value is true
     */
    boolean check() default true;

    /**
     * Whether eager initialize the reference bean when all properties are set, default value is false
     */
    boolean init() default false;

    /**
     * Whether to make connection when the client is created, the default value is false
     */
    boolean lazy() default false;

    /**
     * Export an stub service for event dispatch, default value is false.
     *
     * @see Constants#STUB_EVENT_METHODS_KEY
     */
    boolean stubevent() default false;

    /**
     * Whether to reconnect if connection is lost, if not specify, reconnect is enabled by default, and the interval
     * for retry connecting is 2000 ms
     *
     * @see Constants#DEFAULT_RECONNECT_PERIOD
     */
    String reconnect() default "";

    /**
     * Whether to stick to the same node in the cluster, the default value is false
     *
     * @see Constants#DEFAULT_CLUSTER_STICKY
     */
    boolean sticky() default false;

    /**
     * How the proxy is generated, legal values include: jdk, javassist
     */
    String proxy() default "";

    /**
     * Service stub name, use interface name + Local if not set
     */
    String stub() default "";

    /**
     * Cluster strategy, legal values include: failover, failfast, failsafe, failback, forking
     */
    String cluster() default "";

    /**
     * Maximum connections service provider can accept, default value is 0 - connection is shared
     */
    int connections() default 0;

    /**
     * The callback instance limit peer connection
     *
     * @see Constants#DEFAULT_CALLBACK_INSTANCES
     */
    int callbacks() default 0;

    /**
     * Callback method name when connected, default value is empty string
     */
    String onconnect() default "";

    /**
     * Callback method name when disconnected, default value is empty string
     */
    String ondisconnect() default "";

    /**
     * Service owner, default value is empty string
     */
    String owner() default "";

    /**
     * Service layer, default value is empty string
     */
    String layer() default "";

    /**
     * Service invocation retry times
     *
     * @see Constants#DEFAULT_RETRIES
     */
    int retries() default 2;

    /**
     * Load balance strategy, legal values include: random, roundrobin, leastactive
     *
     * @see Constants#DEFAULT_LOADBALANCE
     */
    String loadbalance() default "";

    /**
     * Whether to enable async invocation, default value is false
     */
    boolean async() default false;

    /**
     * Maximum active requests allowed, default value is 0
     */
    int actives() default 0;

    /**
     * Whether the async request has already been sent, the default value is false
     */
    boolean sent() default false;

    /**
     * Service mock name, use interface name + Mock if not set
     */
    String mock() default "";

    /**
     * Whether to use JSR303 validation, legal values are: true, false
     */
    String validation() default "";

    /**
     * Timeout value for service invocation, default value is 0
     */
    int timeout() default 0;

    /**
     * Specify cache implementation for service invocation, legal values include: lru, threadlocal, jcache
     */
    String cache() default "";

    /**
     * Filters for service invocation
     *
     * @see Filter
     */
    String[] filter() default {};

    /**
     * Listeners for service exporting and unexporting
     *
     * @see ExporterListener
     */
    String[] listener() default {};

    /**
     * Customized parameter key-value pair, for example: {key1, value1, key2, value2}
     */
    String[] parameters() default {};

    /**
     * Application spring bean name
     */
    String application() default "";

    /**
     * Module spring bean name
     */
    String module() default "";

    /**
     * Consumer spring bean name
     */
    String consumer() default "";

    /**
     * Monitor spring bean name
     */
    String monitor() default "";

    /**
     * Registry spring bean name
     */
    String[] registry() default {};

    /**
     * Protocol spring bean names
     */
    String protocol() default "";

    /**
     * methods support
     * @return
     */
    Method[] methods() default {};
}

常用的属性说明:

  • interface:指定要引用的接口类,用于指定要调用的服务接口。包括2中方式,interfaceClass和interfaceName。
  • version:指定要引用的服务的版本号,用于支持多个版本的服务并存。
  • group:指定要引用的服务的分组,用于区分不同的服务实现。
  • url:指定要引用的服务的URL地址,用于直连方式调用服务。
  • loadbalance:指定负载均衡策略,用于决定服务调用时选择哪个提供者实例。默认为random,可选值还有roundrobin(轮询), leastactive(最小连接数)
  • cluster:指定集群容错策略,用于处理服务提供者的故障和网络异常。
  • timeout:指定服务的超时时间,用于限制服务调用的最大耗时。默认为0,表示不设置超时时间。
  • check:指定是否启动时检查服务依赖关系,用于自动检测缺失的依赖服务。默认为true。只有当check=true且服务提供方处于可用状态时,才会引用该服务。
  • async:指定服务调用是否异步,用于支持异步调用模式。默认为false。如果设置为true,则远程调用将以异步方式执行,并返回一个CompletableFuture对象。
  • lazy:该属性用于指定是否要延迟初始化服务。默认为false。如果设置为true,则在第一次调用该服务时才会进行初始化。
  • retries:该属性用于指定调用远程服务方法的重试次数,默认为2。如果设置为0,则表示不进行重试。
  • mock:该属性用于指定远程服务的Mock实现类,默认为空。在远程服务不可用时,会使用Mock实现类的方法返回默认值。

使用的话,类似@Autowired,示例如下:

@Reference(version = "1.0.0")
private ForlanService forlanService;

3、@Method

@Method注解用于标记方法的信息,以便在方法调用时进行配置,它通常与@Reference或@Service一起使用。

注解源码如下:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.ANNOTATION_TYPE})
@Inherited
public @interface Method {
    String name();

    int timeout() default -1;

    int retries() default -1;

    String loadbalance() default "";

    boolean async() default false;

    boolean sent() default true;

    int actives() default 0;

    int executes() default 0;

    boolean deprecated() default false;

    boolean sticky() default false;

    boolean isReturn() default true;

    String oninvoke() default "";

    String onreturn() default "";

    String onthrow() default "";

    String cache() default "";

    String validation() default "";

    Argument[] arguments() default {};
}

用得少,要使用的话,在需要使用的方法上添加@Method注解,并设置相应的属性。
例如,假设你有一个接口定义如下:

public interface ForlanService {
    @Method(name = "getById", timeout = 5000)
    User getById(int id);
}

在上面的示例中,@Method注解应用于getById方法,并设置了两个属性:name和timeout。name属性指定方法在远程调用时的名称,timeout属性指定方法调用的超时时间为5000毫秒。

4、@Argument

@Argument注解用于标记方法参数的信息,以便在方法调用时进行配置,它通常与@Method一起使用。

注解源码如下:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.ANNOTATION_TYPE})
@Inherited
public @interface Argument {
    //argument: index -1 represents not set
    int index() default -1;

    //argument type
    String type() default "";

    //callback interface
    boolean callback() default false;
}

用得少,要使用的话,在需要使用的方法参数上添加@Argument注解,并设置相应的属性。
例如,假设你有一个接口定义如下:

public interface ForlanService {
    Forlan getById(@Argument(index = 0, callback = true) int id);
}

在上面的示例中,@Argument注解应用于getById方法的id参数,并设置了两个属性:index和callback。index属性指定参数的顺序索引,callback属性指定是否回调该参数。

三、分析

我们可以看到,@Service和@Reference的属性,刚好就满足某种特性,比如timeout控制超时时间;retries指定重试次数;mock在远程服务不可用时,会使用Mock实现类的方法返回默认值;executes限制服务的并发处理能力;loadbalance指定负载均衡策略,等等
所以,Hystrix和Sentinel的熔断降级和限流功能,是不是Dubbo就可以实现替代,同样可以防止系统因为某个服务的问题而崩溃,保护整个系统的正常运行。除此之外,Ribbon是一个客户端负载均衡的工具,Dubbo也一样可以替代

四、如何实现?

Dubbo怎么实现熔断、降级、限流,负载均衡,具体代码实现?

1、熔断(Circuit Breaker)

熔断机制用于在服务出现故障或异常时,暂时中断对该服务的调用,以避免连锁故障,Dubbo提供了circuitbreaker配置来启用熔断机制。

XML配置方式

 <dubbo:service interface="com.example.ForlanService" retries="3">
    <dubbo:parameter key="circuitbreaker" value="10"/>
</dubbo:service>

在上面的示例中,retries属性设置了重试次数,circuitbreaker参数设置了熔断阈值,当调用失败次数达到阈值时,Dubbo会触发熔断。

注解方式

使用Dubbo的@Service注解标记服务提供者,并配置retries属性来设置重试次数,例如:

@Service(retries = 3,parameters = {"circuitbreaker", "10"})
public class ForlanServiceImpl implements ForlanService{
    // ...
}

2、降级(Fallback)

降级机制用于在服务不可用时,提供备用的处理逻辑,Dubbo提供了mock配置来实现降级。

XML配置方式

以下是一个示例配置:

<dubbo:reference id="forlanService" interface="com.example.ForlanService">
    <dubbo:parameter key="mock" value="com.example.ForlanServiceMock"/>
</dubbo:reference>

在上面的示例中,mock参数指定了一个实现了ForlanService接口的ForlanServiceMock类,当服务不可用时,Dubbo会调用该类中的方法来提供备用逻辑。

注解方式

  • 使用Dubbo的@Reference注解标记服务消费者,并配置mock属性来指定降级逻辑,例如:
@Reference(mock = "com.example.ForlanServiceMock")
private ForlanService forlanService;
  • 创建一个实现了UserService接口的ForlanServiceMock类,用于提供降级逻辑,例如:
public class ForlanServiceMock implements ForlanService{
    // 实现降级逻辑
}

3、限流(Rate Limiting)

限流机制用于控制对服务的并发访问量,以保护服务的稳定性。Dubbo提供了executes配置来实现限流。

XML配置方式

<dubbo:service interface="com.example.ForlanService" executes="10"/>

在上面的示例中,executes属性设置了最大并发执行数,Dubbo会限制同时执行的请求数量不超过该值。

注解方式

使用Dubbo的@Service注解标记服务提供者,并配置executes属性来设置最大并发执行数,例如:

@Service(executes = 10)
public class ForlanServiceImpl implements ForlanService{
    // ...
}

4、负载均衡(Load Balancing)

负载均衡机制用于在多个服务提供者之间分配请求,以实现负载均衡。Dubbo提供了多种负载均衡策略,例如随机、轮询、一致性哈希等。

XML配置方式

<dubbo:reference id="userService" interface="com.example.ForlanService">
    <dubbo:parameter key="loadbalance" value="random"/>
</dubbo:reference>

在上面的示例中,loadbalance参数设置了负载均衡策略为随机,Dubbo会随机选择一个服务提供者来处理请求。

注解方式

使用Dubbo的@Reference注解标记服务消费者,并配置loadbalance属性来指定负载均衡策略,例如:

@Reference(loadbalance = "random")
private ForlanService forlanService;

五、扩展

1、Feign和Openfeign区别?

OpenFeign是Spring Cloud在Feign的基础上支持了SpringMVC的注解

2、Hystrix和Sentinel的区别?

Hystrix和Sentinel都是用于分布式系统中的容错和熔断保护的开源框架,但两者在一些方面有所不同。

  1. 项目背景:Hystrix是由Netflix开发的,而Sentinel是由阿里巴巴开发的。这意味着Hystrix更多地关注于Netflix内部的需求,而Sentinel则更适合阿里巴巴的业务场景。
  2. 语言支持:Hystrix主要支持Java语言,而Sentinel不仅支持Java,还支持Go、C++等多种语言。
  3. 功能特性:Hystrix提供基于线程池隔离和信号量隔离的熔断机制,并提供了线程池的监控和度量功能。Sentinel除了提供熔断机制外,还具备流量控制、系统负载保护、统计和降级等功能。
  4. 生态系统:Hystrix已进入维护模式,停止了新功能的开发。而Sentinel在国内得到了广泛的应用,并且还与Spring Cloud、Dubbo等框架进行了集成。
  5. 综上所述,Hystrix和Sentinel在功能特性、语言支持和生态系统等方面存在一些差异,选择哪个取决于实际的业务需求和技术栈。
GitHub 加速计划 / sentine / Sentinel
22.24 K
7.98 K
下载
alibaba/Sentinel: Sentinel 是阿里巴巴开源的一款面向分布式服务架构的流量控制、熔断降级组件,提供实时监控、限流、降级和系统保护功能,适用于微服务治理场景。
最近提交(Master分支:1 个月前 )
195150bc * fix issue 2485 which occur oom when using async servlet request. * optimize imports * 1. fix the same issue in the webmvc-v6x 2. improve based on review comments 24 天前
b78b09d3 27 天前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐