Dubbo-笔记随记一

一、实战

1 . Springboot整合

1.1 服务提供者

1.1.1 依赖
         <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>3.2.10</version>
        </dependency>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-zookeeper-spring-boot-starter</artifactId>
            <version>3.2.10</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <artifactId>logback-classic</artifactId>
                    <groupId>ch.qos.logback</groupId>
                </exclusion>
            </exclusions>
        </dependency>
1.1.2 配置
dubbo:
  protocol:
    name: tri
    port: 50051
  application:
    name: lyl-dubbo-server
    logger: slf4j
  registry:
    address: zookeeper://localhost:2181
1.1.3 开启dubbo

@EnableDubbo 使用该注释,开启dubbo

@SpringBootApplication
@EnableDubbo
public class ServerApp
{
    public static void main( String[] args )
    {
        SpringApplication.run(ServerApp.class, args);
        System.out.println("server started!");
    }
}
1.1.4 服务暴露(服务注册)
@DubboService 使用该注释,进行服务暴露(注册到注册中心)
package com.doumi.service;

import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.stereotype.Service;

@DubboService
@Service
public class DemoServiceImpl implements DemoService {

    @Override
    public String hello(String name) {
        return "i am server hello " + name;
    }
}

1.2 服务消费者

1.2.1 依赖
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.6.8</version>
        </dependency>
<!--        dubbo 依赖-->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>3.2.10</version>
        </dependency>

        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-zookeeper-spring-boot-starter</artifactId>
            <version>3.2.10</version>
        </dependency>
1.2.2 配置
dubbo:
  protocol:
    name: tri
    port: 50052
  application:
    name: lyl-dubbo-client
    logger: slf4j
  registry:
    address: zookeeper://localhost:2181
1.2.3 开启dubbo
package com.doumi;

import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RestController;

/**
 * 服务调用端!
 *
 */
@SpringBootApplication
@RestController
@EnableDubbo
public class ClientApp
{
    public static void main( String[] args )
    {
        SpringApplication.run(ClientApp.class, args);
        System.out.println( "client start!" );
    }
}
1.2.4 使用服务
@DubboReference 使用该注解,调用dubbo服务
package com.doumi.controller;

import com.doumi.service.DemoService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/users")
public class MyRestController {
    /**
     * mock 容错处理,返回null
     * mock = true
     */
    @DubboReference(mock = "true")
    private DemoService demoService;

    @GetMapping(path = "/hello")
    public String hello(@RequestParam String name) {
        return demoService.hello(name);
//        return "i am client, hello "+name;

    }

}

2、高级特性

2.1 序列化

package com.doumi.service;

import com.doumi.pojo.User;

public interface DemoService {

    String hello(String name);

    User find(Integer id);

}
package com.doumi.service;

import com.doumi.pojo.User;
import org.apache.dubbo.config.annotation.DubboService;

@DubboService
public class DemoServiceImpl implements DemoService {

    @Override
    public String hello(String name) {
        return "i am server hello " + name;
    }

    @Override
    public User find(Integer id) {
        User user = new User(id, "user-" + id);
        return user;
    }

}
package com.doumi.controller;

import com.doumi.pojo.User;
import com.doumi.service.DemoService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/users")
public class MyRestController {
    /**
     * mock 容错处理,返回null
     * mock = true
     */
    @DubboReference(mock = "false")
    private DemoService demoService;

    @GetMapping(path = "/hello")
    public String hello(@RequestParam String name) {
        return demoService.hello(name);
    }


    @GetMapping(path = "/find")
    public User find(@RequestParam Integer id) {
        return demoService.find(id);
    }

}

当返回是个对象时,该对象必须进行序列化,因为该对象需要在两台服务器间(网络)传输

pojo定义如下:

package com.doumi.pojo;

import java.io.Serializable;

public class User implements Serializable {
    private Integer id;
    private String name;

    public User() {
    }

    public User(Integer id, String name) {
        this.id = id;
        this.name = name;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

当对象没有序列化的时候,报错如下:


org.apache.dubbo.rpc.StatusRpcException: INTERNAL : Serialize response failed
	at org.apache.dubbo.rpc.TriRpcStatus.asException(TriRpcStatus.java:213) ~[dubbo-3.2.10.jar:3.2.10]
	at org.apache.dubbo.rpc.protocol.tri.call.UnaryClientCallListener.onClose(UnaryClientCallListener.java:53) ~[dubbo-3.2.10.jar:3.2.10]

2.2  地址缓存

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

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

2.3 超时

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

import com.doumi.pojo.User;
import org.apache.dubbo.config.annotation.DubboService;

@DubboService(timeout = 3000)//服务端配置超时时间
public class DemoServiceImpl implements DemoService {

    @Override
    public String hello(String name) throws InterruptedException {
        Thread.sleep(5000);
        return "i am server hello " + name;
    }

    int i ;
    @Override
    public User find(Integer id) throws InterruptedException {
        System.out.println("调用服务端"+i++);
        User user = new User(id, "user-" + id);
        Thread.sleep(5000);
        return user;
    }


}
客户端配置超时时间
package com.doumi.controller;

import com.doumi.pojo.User;
import com.doumi.service.DemoService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/users")
public class MyRestController {
    /**
     * mock 容错处理,返回null
     * mock = true
     */
    @DubboReference(mock = "true",timeout = 6000) //客户端设置超时时间,服务端设置成3s,服务调用实际时间是5s,此时可以调用成功
    private DemoService demoService;

    @GetMapping(path = "/hello")
    public String hello(@RequestParam String name) throws InterruptedException {
        timer();
        return demoService.hello(name);
    }


    @GetMapping(path = "/find")
    public User find(@RequestParam Integer id) throws InterruptedException {
        timer();
        return demoService.find(id);
    }

    int i = 1;
    public void timer() {

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

}

2.4 重试

设置了超时时间,在这个时间段内,无法完成服务访问,则自动断开连接。

如果出现网络抖动,则这次请求就会失败。

dubbo提供重试机制,来避免类似问题的发生。

通过retries属性来设置重试次数,默认为2次。

@RestController
@RequestMapping("/users")
public class MyRestController {
    /**
     * mock 容错处理,返回null
     * mock = true
     */
    @DubboReference(mock = "true",timeout = 1000,retries = 5) 当前服务1秒超时,重试5次,共调用6次
    private DemoService demoService;

2.5 多版本

2.5.1 使用场景

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

服务端两个版本的实现,分别标识 version = "v1.0" version = "v2.0"

客户端使用version = "v1.0" 和version = "v2.0",控制具体使用哪个版本

package com.doumi.service;

import com.doumi.pojo.User;
import org.apache.dubbo.config.annotation.DubboService;

@DubboService(timeout = 3000,retries =1,version = "v1.0")
public class DemoServiceImpl implements DemoService {

    @Override
    public String hello(String name) throws InterruptedException {
        Thread.sleep(5000);
        return "i am server hello " + name;
    }

    int i ;
    @Override
    public User find(Integer id) throws InterruptedException {
        System.out.println("old 调用服务端"+i++);
        User user = new User(id, "user-" + id);
        Thread.sleep(5000);
        return user;
    }
}
package com.doumi.service;

import com.doumi.pojo.User;
import org.apache.dubbo.config.annotation.DubboService;

@DubboService(timeout = 3000,retries =1,version = "v2.0" )
public class DemoServiceImpl2 implements DemoService {

    @Override
    public String hello(String name) throws InterruptedException {
        Thread.sleep(5000);
        return "i am server hello " + name;
    }

    int i ;
    @Override
    public User find(Integer id) throws InterruptedException {
        System.out.println("new  调用服务端 "+i++);
        User user = new User(id, "user-" + id);
        Thread.sleep(5000);
        return user;
    }
}
@RestController
@RequestMapping("/users")
public class MyRestController {
    /**
     * mock 容错处理,返回null
     * mock = true
     */
    @DubboReference(mock = "true",timeout = 1000,retries = 5,version = "v1.0") //当前服务1秒超时,重试5次,共调用6次
    private DemoService demoService;

2.6 负载均衡

负载均衡策略:(4种)

  • Random:按权重随机,默认值,按权重设置随机概率
  • RoundRobin:按权重轮询
  • LeastActive:最少活跃调用数,相同活跃数的随机
  • ConsistantHash:一致性Hash,相同参数的请求总是发到同一提供者
@RestController
@RequestMapping("/users")
public class MyRestController {
    /**
     * mock 容错处理,返回null
     * mock = true
     */
    @DubboReference(loadbalance ="RandomLoadBalance" ) //负载均衡策略
    private DemoService demoService;

2.7 集群容错

集群容错模式:

FailOver Cluster:失败重试,默认值。当出现失败,重试其他

FailFast Cluster:快速失败,只发起一次调用,失败立即报错。通常用于写操作。

FailSafe Cluster:失败安全,出现异常时,直接忽略。返回一个空结果。

FailBack Cluster:失败自动恢复,后台记录失败请求,定时重发。

Forking Cluster:并行调用多个服务器,只要有一个成功即返回。

//    @DubboReference(cluster = "failover",version = "v1.0")//失败重试
//    @DubboReference(cluster = "failfast",version = "v1.0")//快速失败,失败了直接返回错误
//    @DubboReference(cluster = "failsafe",version = "v1.0")//失败了返回一个空结果,防止出现异常
//    @DubboReference(cluster = "failback",version = "v1.0")//失败自动恢复,后台记录失败请求,定时重发。
    @DubboReference(cluster = "forking",version = "v1.0")//并行调用多个服务器,只要有一个成功即返回。
    private DemoService demoService;

2.8 服务降级

服务降级方式:

  • mock=force:return null :表示消费方对该服务的方法的调用都直接返回null值,不发起远程调用。用来屏蔽不重要服务不可用时对调用方的影响。
  • mock=fail:return null 表示消费方对该服务的方法调用在失败后,再返回null值,不抛出异常。用来容忍不重要服务不稳定时,对调用方的影响。
//@DubboReference(mock = "force:return null")//不会发起调用,直接失败,用于服务降级的场景,保证重点服务可用,非重点服务直接失败
@DubboReference(mock = "fail:return null",version="v1.0")//表示消费方对该服务的方法调用在失败后,再返回null值,不抛出异常。用来容忍不重要服务不稳定时,对调用方的影响。
    private DemoService demoService;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值