Dubbo

目录

什么是Dubbo?

环境要求

Dubbo架构

基于注解的代码实现:

供应者配置

消费者配置        

Dubbo 高级特性 

序列化 

地址缓存 

超时与重试

 多版本

 负载均衡(必须有集群的环境)

集群容错

延伸阅读

    1. 消费端是怎么找到服务端的?

2. 消费端是如何发起请求的?


 

什么是Dubbo?

Dubbo_第1张图片        Dubbo实现多种语言,为所有主流语言提供对等的微服务开发体验

Dubbo_第2张图片        作为一款微服务框架,最重要的是向用户提供跨进程的 RPC 远程调用能力。如上图所示,Dubbo 的服务消费者(Consumer)通过一系列的工作将请求发送给服务提供者(Provider)。

        在数据面,Dubbo作为一款微服务框架最重要的是向用户提供跨进程的 RPC 远程调用能力,在控制面,作为微服务的抽象控制面,Dubbo由一系列可选的微服务治理组件构成,负责Dubbo集群的服务发现,流量管控,可视化监测等

Dubbo官方推荐使用Zookeeper作为注册中心

Dubbo_第3张图片

环境要求

  • 系统:Windows、Linux、MacOS

  • JDK 8 及以上(推荐使用 JDK17)

  • Git

  • IntelliJ IDEA(可选)

  • Docker (可选)

Dubbo架构

Dubbo_第4张图片

节点角色说明:

Provider 暴露服务的服务提供方
Container :服务运行容器
Consumer :调用远程服务的服务消费方
Registry :服务注册与发现的注册中心 
Monitor :统计服务的调用次数和调用时间的监控中心

基于注解的代码实现:

首先,必须有一个提供程序的整体配置:

供应者配置

配置: 

dubbo.application.name=samples-annotation-provider
dubbo.registry.address=zookeeper://121.37.118.193:2181
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880
dubbo.provider.token=true

配置类 

@Configuration
@EnableDubbo(scanBasePackages = "org.apache.dubbo.samples.annotation.impl")
@PropertySource("classpath:/spring/dubbo-provider.properties")
static class ProviderConfiguration {
}

@EnableDubbo将使 Spring 包能够找到任何由 Dubbo 注释注释的内容。org.apache.dubbo.samples.annotation.impl

作为提供程序,接口实现类必须由以下项注释:@DubboService

@DubboService
public class AnnotatedGreetingService implements GreetingService {

    public String sayHello(String name) {
        System.out.println("greeting service received: " + name);
        return "hello, " + name;
    }

}

消费者配置        

消费者的整体配置对提供商来说非常温和:

配置:

dubbo.application.name=samples-annotation-consumer
dubbo.registry.address=zookeeper://121.37.118.193:2181

配置类 :

@Configuration
@EnableDubbo(scanBasePackages = "org.apache.dubbo.samples.annotation.action")
@PropertySource("classpath:/spring/dubbo-consumer.properties")
@ComponentScan(value = {"org.apache.dubbo.samples.annotation.action"})
static class ConsumerConfiguration {

}

 您可以使用注释将提供程序自动连接到使用者:@DubboReference

@Component("annotatedConsumer")
public class GreetingServiceConsumer {

    @DubboReference
    private GreetingService greetingService;
    
    ...
}

依赖配置:

 


    
        1.8
        1.8
        3.2.0
        4.3.30.RELEASE
        4.13.1
        3.7.0
        3.8.0
    

    
        
            
                org.springframework
                spring-framework-bom
                ${spring.version}
                pom
                import
            
            
                org.apache.dubbo
                dubbo-bom
                ${dubbo.version}
                pom
                import
            
            
                org.apache.dubbo
                dubbo-dependencies-zookeeper-curator5
                ${dubbo.version}
                pom
            
            
                org.apache.zookeeper
                parent
                ${zookeeper_version}
                pom
                import
            
        
    

    
        
            org.apache.dubbo
            dubbo
        

        
            org.apache.dubbo
            dubbo-dependencies-zookeeper-curator5
            pom
        

        
            junit
            junit
            ${junit.version}
            test
        

        
            org.springframework
            spring-test
            test
        

        
            com.github.spotbugs
            spotbugs-annotations
            true
        
        
            commons-cli
            commons-cli
        
        
            org.eclipse.jetty
            jetty-server
        
        
            org.eclipse.jetty
            jetty-servlet
        
        
            org.eclipse.jetty
            jetty-client
        
        
            jline
            jline
        
        
            io.dropwizard.metrics
            metrics-core
        
        
            org.xerial.snappy
            snappy-java
        
    

    
        
        
            javax.annotation
            
                [1.11,)
            
            
                
                    javax.annotation
                    javax.annotation-api
                    1.3.2
                
            
        
    

    
        
            
                org.apache.maven.plugins
                maven-compiler-plugin
                ${maven-compiler-plugin.version}
                
                    ${source.level}
                    ${target.level}
                
            
        
    

Dubbo 高级特性 

序列化 

        dubbo 内部已经将序列化和反序列化的过程内部封装了,我们只需要在定义pojo类时实现Serializable接口即可,一般会定义一个公共的pojo模块,让生产者和消费者都依赖该模块。

地址缓存 

注册中心挂了,服务是否可以正常访问?

可以,因为dubbo服务消费者在第一次调用时,会将服务提供方地址缓存到本地,以后在调用则不会访问注册中心。当服务提供者地址发生变化时,注册中心会通知服务消费者。

超时与重试

Dubbo_第5张图片

        服务消费者在调用服务提供者的时候发生了阻塞、等待的情形,这个时候,服务消费者会一直等待下去。在某个峰值时刻,大量的请求都在同时请求服务消费者,会造成线程的大量堆积,势必会造成雪崩
        dubbo 利用超时机制来解决这个问题,设置一个超时时间,在这个时间段内,无法完成服务访问,则自动断开连接。
        使用timeout属性配置超时时间,默认值1000,单位毫秒。

        设置了超时时间,在这个时间段内,无法完成服务访问,则自动断开连接。
        如果出现网络抖动,则这一次请求就会失败。
        Dubbo 提供重试机制来避免类似问题的发生。
        通过 retries  属性来设置重试次数。默认为 2 次

供应端代码:(建议配置在供应端)

@Service(timeout = 3000,retries = 2)//当前服务3秒超时,重试2次,一共3次
public class UserServiceImpl implements UserService {

    int i = 1;
    public String sayHello() {
        return "hello dubbo hello!~";
    }


    public User findUserById(int id) {
        System.out.println("服务被调用了:"+i++);
        //查询User对象
        User user = new User(1,"zhangsan","123");
        //数据库查询很慢,查了5秒

        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return user;
    }
}

消费者代码 


@RestController
@RequestMapping("/user")
public class UserController {

    //注入Service
    //@Autowired//本地注入

    /*
        1. 从zookeeper注册中心获取userService的访问url
        2. 进行远程调用RPC
        3. 将结果封装为一个代理对象。给变量赋值

     */

    @Reference(timeout = 1000)//远程注入
    private UserService userService;


    @RequestMapping("/sayHello")
    public String sayHello(){
        return userService.sayHello();
    }

    /**
     * 根据id查询用户信息
     * @param id
     * @return
     */
    int i = 1;
    @RequestMapping("/find")
    public User find(int id){

        new Thread(new Runnable() {
            public void run() {
                while (true){
                    System.out.println(i++);
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();


        return userService.findUserById(id);
    }

 多版本

Dubbo_第6张图片

灰度发布:当出现新功能时,会让一部分用户先使用新功能,用户反馈没问题时,再将所有用户迁移到新功能。 dubbo 中使用version 属性来设置和调用同一个接口的不同版本

 

@Service(version = "v2.0")
public class UserServiceImpl2 implements UserService {
    ...
}
    @Reference(version = "v2.0")//远程注入
    private UserService userService;

 负载均衡(必须有集群的环境)

负载均衡策略4种)

Random :按权重随机,默认值。按 权重设置随机 概率。
2号机的权重概率:200/(100+200+100)
Dubbo_第7张图片
配置如下,分别对应上面三个提供者,100,200,100,启动三个服务
@Service(weight = 100)
public class UserServiceImpl implements UserService {
    ...
}
    @Reference(loadbalance = "random")//远程注入
    private UserService userService;
RoundRobin :按权重轮询。(1,2,3然后发现2的权重最大随后访问2
LeastActive :最少活跃调用 数, 相同活跃数的 随机。(
ConsistentHash :一致性 Hash 相同参数的请求总是发到同一提供者。

Dubbo_第8张图片

集群容错

    @Reference(cluster = "failover")//远程注入
    private UserService userService;

集群容错模式:
Failover Cluster:失败重试。默认值。当出现失败,重试其它服务器 ,默认重试2次,使用 retries 配置。一般用于读操作
Failfast Cluster :快速失败,只发起一次调用,失败立即报错。通常用于写操作。
Failsafe Cluster :失败安全,出现异常时,直接忽略。返回一个空结果。
Failback Cluster :失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。
Forking Cluster :并行调用多个服务器,只要一个成功即返回。
Broadcast  Cluster :广播调用所有提供者,逐个调用,任意一台报错则报错

延伸阅读

    1. 消费端是怎么找到服务端的?

服务提供者会向注册中心中写入自己的地址,供服务消费者获取。

2. 消费端是如何发起请求的?

在 Dubbo 的调用模型中,起到连接服务消费者和服务提供者的桥梁是接口。

服务提供者通过对指定接口进行实现,服务消费者通过 Dubbo 去订阅这个接口。服务消费者调用接口的过程中 Dubbo 会将请求封装成网络请求,然后发送到服务提供者进行实际的调用。

// 1-basic/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/api/GreetingsService.java

package org.apache.dubbo.samples.api;

public interface GreetingsService {

    String sayHi(String name);

}

        服务消费者通过 Dubbo 的 API 可以获取这个 GreetingsService 接口的代理,然后就可以按照普通的接口调用方式进行调用。得益于 Dubbo 的动态代理机制,这一切都像本地调用一样。

// 1-basic/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/client/Application.java

// 获取订阅到的 Stub
GreetingsService service = reference.get();
// 像普通的 java 接口一样调用
String message = service.sayHi("dubbo");

你可能感兴趣的:(微服务,dubbo,服务器)