6.ribbon结合项目

 

 创建三个相同数据库分别为db01,db02,db03内容一致只不过是db_souce字段分别代表三个数据库的名字

效果如图:刷新页面,数据来源于三个数据库

 

 

 

 配置Ribbon的步骤

1. 针对Consumer模块

1.1 导入依赖包括ribbon和eureka

<!--ribbon-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-ribbon</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>
<!--eureka-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>

1.2 配置文件

#80配置之后localhost可以直接访问
server:
  port: 80
#eureka配置
eureka:
  client:
    register-with-eureka: false #不向eureka注册自己
    service-url: #需求是他随机进这三个注册中心注册
      defaultZone: http://localhost:7001/eureka/,http://localhost:7002/eureka/,http://localhost:7003/eureka/

1.3 添加LoadBalanced注解在配置类中

@Configuration//相当于spring中的applicationContext
public class ConfigBean {
    //注册RestTemplate模板
    @Bean
    @LoadBalanced//负载均衡实现了
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}

1.4 更改前缀名为eureka的统一名字在Controller类中

@RestController
public class DeptConsumerController {
    //消费者不应该有service层
    //restTemplate模板有很多可以直接调用的方法,首先需要在配置文件注册到spring中
    //(url,实体:map,Class<T>responseType)
    @Autowired
    private RestTemplate restTemplate;//提供便捷访问远程http服务的方法,是一个简单的restful服务模板
    //通过ribbon实现的时候这个地址应该是一个变量,通过服务名来访问
    //private static final String REST_URL_PREFIX="http://localhost:8001";
    private static final String REST_URL_PREFIX="http://SPRINGCLOUD-PROVIDER-DEPT";
    @RequestMapping("/consumer/dept/get/{id}")
    public Dept get(@PathVariable("id")Long id){
        //请求的地址,返回值类型
        return restTemplate.getForObject(REST_URL_PREFIX+"/dept/get/"+id,Dept.class);
    }

    @RequestMapping("/consumer/dept/add")
    public boolean add(Dept dept){
        //请求的地址,参数,返回值类型
        return restTemplate.postForObject(REST_URL_PREFIX+"/dept/add",dept,Boolean.class);
    }
    @RequestMapping("/consumer/dept/list")
    public List<Dept> add(){
        //请求的地址,参数,返回值类型
        return restTemplate.getForObject(REST_URL_PREFIX+"/dept/list",List.class);
    }

}

 1.5 在主启动类上增加eureka注解

//Ribbon和Eureka整合以后,客户端可以直接调用,不用关心IP地址和端口号
@SpringBootApplication
@EnableEurekaClient
public class DeptConsumer_80 {
    public static void main(String[] args) {
        SpringApplication.run(DeptConsumer_80.class,args);
    }
}

2. 三个proivider类

 

 需要修改配置文件中数据库相关东西和端口号

server:
  port: 8002
  #mybatis的配置
mybatis:
  type-aliases-package: com.wu.springcloud.pojo
  mapper-locations: classpath:mybatis/mapper/*.xml
  config-location: classpath:mybatis/mybatis-config.xml
#spring的配置
spring:
  application:
    name: springcloud-provider-dept
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: org.gjt.mm.mysql.Driver
    url: jdbc:mysql://localhost:3306/db02?useSSL=true&useUnicode=true&characterEncoding=utf-8
    username: root
    password: root
#注册eureka,服务注册到哪里
eureka:
  client:
    service-url:
      #集群发布
      defaultZone: http://localhost:7001/eureka/,http://localhost:7002/eureka/,http://localhost:7003/eureka/
  instance:
    instance-id: provider-dept-8002 #修改描述信息

info:
  app.name: xiaowu-springcloud
  company.name: yuzhibo.com

 3.自定义Ribbon策略

3.1 在如下位置建立一个myrule文件夹

myRule自定义配置类

@Configuration
public class MyRule {
    /* 关于负载均衡注解的解释
   有一个接口名为IRule,实现类里重写的choose方法中有以下方法
   --RoundRobinRule 轮询
   --RandomRule 随机
   --AvailabilityFilteringRule 先过滤掉跳闸,访问故障的服务,对接下来的进行轮询
   --RetryRule 会先按照轮询获取服务,如果服务获取失败,则会在指定的事件内进行重试
    */
    @Bean
    public IRule myRule111() {
        return new MyRandomRule();
    }
}

MyRandomRule方法类

public class MyRandomRule extends AbstractLoadBalancerRule {
    private int total=0;//进行了多少次服务
    private int currentIndex=0;//当前是谁在提供服务
    public Server choose(ILoadBalancer lb, Object key) {
        //自定义
        //每个服务访问5次,换下一个服务(总共三个服务)
        if (lb == null) {
            return null;
        }
        Server server = null;
        while (server == null) {
            if (Thread.interrupted()) {
                return null;
            }
            List<Server> upList = lb.getReachableServers();//获得活着的服务
            List<Server> allList = lb.getAllServers();//获得全部的服务

            int serverCount = allList.size();
            if (serverCount == 0) {
                return null;
            }
            //-------------------------自定义
            if(total<5){
                server=upList.get(currentIndex);
                total++;
            }else{
                total=0;
                currentIndex++;
                if(currentIndex>upList.size()-1){
                    currentIndex=0;
                }
                server=upList.get(currentIndex);//从活着的服务中获取指定的服务来进行操作
            }
            //----------------------------
            if (server == null) {
                Thread.yield();
                continue;
            }
            if (server.isAlive()) {
                return (server);
            }
            server = null;
            Thread.yield();
        }
        return server;
    }
    protected int chooseRandomInt(int serverCount) {
        return ThreadLocalRandom.current().nextInt(serverCount);
    }
    @Override
    public Server choose(Object key) {
        return choose(getLoadBalancer(), key);
    }
    @Override
    public void initWithNiwsConfig(IClientConfig clientConfig) {
        // TODO Auto-generated method stub

    }
}

3.2 在主启动类上增加注解,配置Ribbon类

//Ribbon和Eureka整合以后,客户端可以直接调用,不用关心IP地址和端口号
@SpringBootApplication
@EnableEurekaClient
@RibbonClient(name="SPRINGCLOUD-PROVIDER-DEPT",configuration = MyRule.class)//在微服务启动的时候加载自定义的Ribbon类
public class DeptConsumer_80 {
    public static void main(String[] args) {
        SpringApplication.run(DeptConsumer_80.class,args);
    }
}

 

posted @ 2021-07-01 20:09  一拳超人的逆袭  阅读(50)  评论(0)    收藏  举报