Ribbon自定义算法---重写轮询算法

步骤1:先去对我们的8001和8002端口服务提供者进行改造,加上 @GetMapping(value = “/lb”)

package com.zsp.springcloud.controller;


import com.zsp.springcloud.entities.CommonResult;
import com.zsp.springcloud.entities.Payment;
import com.zsp.springcloud.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@Slf4j
@RequestMapping("/payment")
public class PaymentController {
    @Autowired
    PaymentService paymentService;

//    显示端口名称
    @Value("${server.port}")
    private String serverPort;
//    服务发现Discovery 用于告诉我们注册中心有多少微服务

    @Autowired
    private DiscoveryClient discoveryClient;

    @PostMapping(value = "/create")
    public CommonResult create(@RequestBody Payment payment){
        int result=paymentService.create(payment);
        log.info("插入的数据是: "+payment);
        if (result>0)
        {
            return new CommonResult(200,"插入数据成功"+serverPort,result);
        }
        else
        {
            return new CommonResult(444,"插入数据失败",null);
        }
    }
    @GetMapping(value = "/get/{id}")
    public CommonResult getPaymentById(@PathVariable("id") Long  id){
        Payment payment=paymentService.getPaymentById(id);
        log.info("查询到的数据是: "+payment);
        if (payment!=null)
        {
            return new CommonResult(200,"查询成功"+serverPort,payment);
        }
        else
        {
            return new CommonResult(444,"查询失败",null);
        }
    }

    @GetMapping("/discovery")
    public Object discovery(){
//        获取所有微服务的名称 例如 CLOUD-PAYMENT-SERVICE
        List<String> services = discoveryClient.getServices();
        for (String service : services) {
            log.info("名称是:"+service);
        }
//        给这个方法微服务名称会得到该名称下所有的微服务端口
        List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
        for (ServiceInstance instance : instances) {
            log.info("它的id是"+instance.getServiceId()+"他的ip地址是"+instance.getHost()+"他的端口是"+instance.getPort());
        }
        return this.discoveryClient;
    }
    @GetMapping(value = "/lb")
    public String getPaymentLB(){
        return serverPort;
    }
}


步骤2:在我们的80端口config里面注释掉原本的@LoadBalanced

package com.zsp.springcloud.config;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class ApplicationContextConfig {
    @Bean
//    @LoadBalanced //要自己写底层源码就不能使用他的注解
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }

}

步骤3:在原本的类包下创建lb.LoadBalancer接口,定义方法,将我们集群放到定义的接口方法内。

package com.zsp.springcloud.lb;

import org.springframework.cloud.client.ServiceInstance;
import org.springframework.stereotype.Component;

import java.util.List;

public interface LoadBalancer {
    //收集服务器总共有多少台能够提供服务的机器,并放到list里面
    ServiceInstance instances(List<ServiceInstance> serviceInstances);
}

步骤4:实现MyLB去实现我们写的LoadBalancer接口然后在里面重写我们的轮询算法,注意个点
这里一定要加上@Component

package com.zsp.springcloud.lb;


import org.springframework.cloud.client.ServiceInstance;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
@Component
public class MyLB implements LoadBalancer {

    private AtomicInteger atomicInteger= new AtomicInteger(0);
    private final int getAndIncrement(){
        int current;
        int next;
        do{
            current=atomicInteger.get();
            next=current>= Integer.MAX_VALUE? 0:current+1;
        }while(!atomicInteger.compareAndSet(current,next));
        System.out.println("这是第"+next+"次查询");
            return next;

    }
    @Override
    public ServiceInstance instances(List<ServiceInstance> serviceInstances) {
        int index= getAndIncrement()%serviceInstances.size();
        ServiceInstance instance = serviceInstances.get(index);

        return instance;
    }
}

步骤5:到controller里面去调用我们8001和8002端口的服务提供者最后发现可以调用到我们自定义的lb方法。

package com.zsp.springcloud.controller;


import com.zsp.springcloud.entities.CommonResult;

import com.zsp.springcloud.entities.Payment;
import com.zsp.springcloud.lb.LoadBalancer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;


import java.net.URI;
import java.util.List;

@RestController
@Slf4j
public class OrderController {
    @Autowired
    RestTemplate template;
    @Autowired
    LoadBalancer loadBalancer;
    @Autowired
    DiscoveryClient discoveryClient;
    private static final String url="http://CLOUD-PAYMENT-SERVICE";
    @GetMapping("/consumer/payment/create")
    public CommonResult create(Payment payment){
        return template.postForObject(url+"/payment/create",payment,CommonResult.class);
    }
    @GetMapping("/consumer/payment/get/{id}")
    public CommonResult get(@PathVariable("id") Long id){

        return template.getForObject(url+"/payment/get/"+id,CommonResult.class);

    }
        @GetMapping("/consumer/payment/getForEntity/{id}")
    public CommonResult getForEntity(@PathVariable("id") Long id){
        ResponseEntity<CommonResult> entity = template.getForEntity(url + "/payment/get/" + id, CommonResult.class);
        if (entity.getStatusCode().is2xxSuccessful())
        {
            return entity.getBody();
        }
        else {
            return new CommonResult(444,"返回错误");
        }
    }
    @GetMapping(value = "/comsumer/payment/lb")
    public String getPaymentLB(){
        List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
        if (instances  == null || instances .size() <= 0){
            return null;
        }
        ServiceInstance  serviceInstance  = loadBalancer.instances(instances);
        URI uri = serviceInstance.getUri();
        log.info(""+uri);
        return template.getForObject(uri+"/payment/lb",String.class);
    }



}

有趣的是,在调用的过程中,我发现原本可以使用的方法都不能用了,这是因为同一时间内只能有一个负载均衡策略生效,当我们开启了@LoadBalanced的时候,我们自己定义的负载均衡端口就会失效,再次访问只会得到500。

©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页