Spring Cloud 负载均衡 Ribbon实现

Spring Cloud组件中常用的组件里也包含了Ribbon,做负载均衡功能。

目录

 

(一)简介

(二)实现

1.配置多个服务端

 2.配置ribbon

(三)Ribbon和Nginx对比


(一)简介

spring Cloud Ribbon 是一个客户端的负载均衡器,它提供对大量的HTTP和TCP客户端的访问控制。

客户端负载均衡即是当浏览器向后台发出请求的时候,客户端会向 Eureka Server 读取注册到服务器的可用服务信息列表,然后根据设定的负载均衡策略(没有设置即用默认的),抉择出向哪台服务器发送请求。

(二)实现

工程基于之前eureka工程基础上继续实现,之前eureka项目

这里为了方便从浏览器和postman工具中查看结果项目中增加了web Controller类。

1.配置多个服务端

SPRING-CLIENT-01服务中增加了一个Controller:

package com.cloud.client.controller;

import com.cloud.client.service.DemoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;

@RestController
@RequestMapping("/getInfo")
public class Controller {
    
    @Value("${server.port}")
    String port;

    @Value("${spring.application.name}")
    String serviceName;

    @RequestMapping("/show")
    public String getInfo(){
        return "I'm form service:"+serviceName+",port:"+port;
    }

    @RequestMapping(value = "no/{no}", method = RequestMethod.GET)
    public String getPolicyFileByPolicyNo(@PathVariable String no,HttpServletResponse httpServletResponse){

        try {
            String  result = "I'm form service:"+serviceName+",port:"+port;
            if (result == null){
                httpServletResponse.setStatus(HttpServletResponse.SC_NOT_FOUND);
                return null;
            } else
                return result;
        } catch (Exception e) {
            e.printStackTrace();
            httpServletResponse.setStatus(HttpServletResponse.SC_BAD_REQUEST);
            return e.getMessage();
        }
    }

    @RequestMapping("/port")
    public String findInfo(){
        return "I'm form service:"+serviceName+",port:"+port;
    }

}

启动eureka server,启动 SPRING-CLIENT-01,然后再网页或者postman中输入

http://localhost:10001/getInfo/show

得到结果:

然后在IDEA的edit Configurations里面将Single instance Only 勾选掉,SPRING-CLIENT-01服务的配置端口输入不同的端口号,启动,就可以启动多个不同端口号但服务名都是SPRING-CLIENT-01的服务了。

 

我这边分别启动了端口号是10001,10002的服务,然后在配置中心可以看到服务列表。

 2.配置ribbon

之后就是配置ribbon服务了。

在工程之前新建一个module,建立方式和之前建立eureka server和client相同,只是在选择组件的时候加上ribbon组件。

生成之后对应的pom.xml文件里面也就是多了ribbon的配置

<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>

 配置文件application.properties的内容,我这边因为配置呢mysql,所以有本地mysql的配置,如果没有选jpa和mysql组件,这部分可以不要。

server.port = 11000

eureka.client.serviceUrl.defaultZone= http://localhost:12345/eureka/
spring.application.name= SPRING-CLIENT-02

SPRING-CLIENT-01.ribbon.NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

spring.datasource.url=jdbc:mysql://127.0.0.1:3306/testmysql
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.max-idle=10
spring.datasource.max-wait=10000
spring.datasource.min-idle=5
spring.datasource.initial-size=5

ribbon的启动类RibbonserviceApplication:

package com.cloud.ribbonservice;

import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestOperations;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
@EnableDiscoveryClient
public class RibbonserviceApplication {

    public static void main(String[] args) {
        SpringApplication.run(RibbonserviceApplication.class, args);
    }

    @Bean
    @LoadBalanced
    RestTemplate restTemplate() {
        return new RestTemplate();
    }

    @Bean
    public IRule ribbonRule() {
        return new RandomRule();	//这里配置策略,和配置文件对应
    }

}

 我这里增加了一个RibbonService和IRibbonService

package com.cloud.ribbonservice.service;

public interface IRibbonService {
}
package com.cloud.ribbonservice.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.ResourceAccessException;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.Map;

@Service
public class RibbonService implements IRibbonService {

    @Autowired
    RestTemplate restTemplate;

    @Autowired
    LoadBalancerClient loadBalancerClient;

    public String port() {
        this.loadBalancerClient.choose("SPRING-CLIENT-01");
        String info = restTemplate.getForObject("http://SPRING-CLIENT-01/getInfo/port", String.class);
        return restTemplate.getForObject("http://SPRING-CLIENT-01/getInfo/port", String.class);
    }

}

SpringCloud 里面访问其他服务可以通过RestTemplate来实现。 

RestTemplate进行rest请求有很多种方式。这个可以看下RestTemplate类具体的接口。

 在Spring Cloud里面RestTemplate中直接加对应微服务的名称然后接对应Controller的Web接口。

这边Ribbon服务中对应的Controller是:

package com.cloud.ribbonservice.controller;

import com.cloud.ribbonservice.service.RibbonService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


@RestController
@RequestMapping("/getInfo")
public class Controller {

    @Autowired
    RibbonService ribbonService;

    private static final Logger logger = LoggerFactory.getLogger(Controller.class);


    @Value("${server.port}")
    String port;

    @Value("${spring.application.name}")
    String serviceName;

    @RequestMapping("/show")
    public String getInfo(){
        return "I'm form service:"+serviceName+",port:"+port;
    }

    @RequestMapping("/hellol")
    public String showInfol(){
        System.out.println("find port");
        logger.info("find port");
        return ribbonService.port();

    }


}

然后运行 启动RibbonserviceApplication,启动之后可以在eureka服务中心看到对应的Ribbon服务也注册进去了。

然后稍等会(这里应该是将服务注册加入进Ribbon需要少量时间),在浏览器或者postman中输入 

http://localhost:11000/getInfo/hellol

 调用ribbon服务中的RestTemplate

多刷几次就可以看到结果在端口号10001,10002之间切换,也就是达到负债均衡的效果了。

(三)Ribbon和Nginx对比

从上面的结果可以看出来Ribbon 实现的是客户端负载均衡,它可以在客户端经过一系列算法来均衡调用服务。Ribbon 比 Nginx 更注重的是承担并发而不是请求分发,Ribbon 工作时分两步:

第一步:选择 Eureka Server,它优先选择在同一个 Zone 且负载较少的 Server。

第二步:根据用户指定的策略,在从 Server 取到的服务注册列表中选择一个地址,其中 Ribbon 提供了多种策略,例如轮询 RoundRobinRule、随机 RandomRule等。

以上源码github地址: 源码地址

猜你喜欢

转载自blog.csdn.net/harryptter/article/details/88075239