Ribben

Ribben

基于Netflix Ribbon实现的一套客户端负载均衡的工具,主要功能是提供客户端软件负载均衡算法和服务调用

Nginx:  是服务器负载均衡,客户端所有请求都会交给nginx,然后由nginx实现转发请求,即负载均衡是由服务端实  现。
Ribbon:本地负载均衡,调用微服务接口时候,会在注册中心获取注册信息服务列表之后缓存到JVM本地,从而在本地实现RPC远程服务调用技术

Ribben负载均衡替换

  • 新建一个包。不能是启动类所在包及其子包

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l1kAz7iJ-1624523058159)(C:\Users\张丰\AppData\Roaming\Typora\typora-user-images\image-20210623162446075.png)]

  • 添加自定义负载均衡规则类
@Configuration
public class MySelfRule {
    @Bean
    public IRule myRule(){
        //自定义规则为随机  不再是轮询
        return new RandomRule();
    }
}
  • 主启动类加上@RibbonClient()注解
@SpringBootApplication
@EnableEurekaClient
//参数一:服务名
//参数二:自定义负载均衡类反射
@RibbonClient(name = "CLOUD-PAYMENT-SERVICE", configuration = MySelfRule.class)
public class OrderMain80 {
    public static void main(String[] args) {
        SpringApplication.run(OrderMain80.class,args);
    }
}

Ribben负载轮询算法原理

负载均衡算法:

rest接口第几次请求数 % 服务器集群总数量 = 实际调用服务器位置下标,每次服务重启动后rest接口计数从1开始


## 手写轮询算法

##### **去掉默认的轮询算法**

```java
@Configuration
public class ApplicationContextConfig {
    @Bean
    //手写负载均衡,注释默认的
//    @LoadBalanced
    /**
     * 实现负载负载均衡效果
     */
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}
建立接口并添加实现类

建立接口

package com.atguigu.springcloud.lb;
import org.springframework.cloud.client.ServiceInstance;
import java.util.List;
public interface LoadBlancer {
    ServiceInstance instance(List<ServiceInstance> serviceInstances);
}

实现类

package com.atguigu.springcloud.lb;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.stereotype.Component;
import java.lang.annotation.Annotation;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
@Component
public class MyLb implements LoadBlancer{
    //原子类,解决了多线程访问同一资源问题
    private AtomicInteger atomicInteger = new AtomicInteger(0);
    /**
     * 计数 调用一次加next加一
     * @return
     */
    public final int getAndIncrement(){
        int current;
        int next;
        do{
            current = atomicInteger.get();
            next = current >= 2147483647 ? 0 : current+1;
//      compareAndSet 比较并交换 如果当前值和期待值相同  值为true
        }while (! this.atomicInteger.compareAndSet(current,next));
        System.out.println("next:"+next);
        return next;
    }
    
    @Override
    public ServiceInstance instance(List<ServiceInstance> serviceInstances) {
        //rest接口请求的次数对服务器集群总数量求余数,则得到了当前调用服务器的下标
        int i = this.getAndIncrement() % serviceInstances.size();
        return serviceInstances.get(i);
    }
}
8001 和 8002
package com.atguigu.springcloud.controller;

@RestController
@RequestMapping("/payment")
@CrossOrigin
public class PaymentController {
	//当前端口号
    @Value("${server.port}")
    private String serverPort;
    @Resource
    DiscoveryClient discoveryClient;

    @GetMapping("/lb")
    public String getPort(){
        return serverPort;
    }
}
order
package com.atguigu.springcloud.controller;

import com.atguigu.springcloud.entities.CommonResult;
import com.atguigu.springcloud.entities.Payment;
import com.atguigu.springcloud.lb.MyLb;
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.stereotype.Controller;
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 javax.annotation.Resource;
import java.net.URI;
import java.util.List;

/**
 * @Author: 张丰
 * @DateTime: 2021/5/31 18:50
 * @Description: TODO
 */
@RestController
@Slf4j
public class OrderController {
    public static final String PAYMENT_URL = "http://CLOUD-PAYMENT-SERVICE";
    @Resource
    private RestTemplate restTemplate;
    @Autowired
    DiscoveryClient discoveryClient;
    @Resource
    MyLb myLb;

    @GetMapping(value = "/consumer/payment/lb")
    public String getpaymentLb(){
        List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
        if(instances == null || instances.size() == 0){
            return null;
        }
        ServiceInstance instance = myLb.instance(instances);
        URI uri = instance.getUri();
        ResponseEntity<String> forEntity = restTemplate.getForEntity(uri + "/payment/lb", String.class);
        if (forEntity.getStatusCode().is2xxSuccessful()){
            return forEntity.getBody();
        }else{
            return "{\"code\":\"444\",\"message\":\"操作失败\"}";
        }
    }
}
测试

http://localhost/consumer/payment/lb

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值