1.准备

Ribbon是一个基于HTTP和TCP客户端的负载均衡器,可以在通过客户端中配置的ribbonServerList服务端列表去轮询访问以达到均衡负载的作用.

当Ribbon与Eureka联合使用时,ribbonServerList会被DiscoveryEnabledNIWSServerList重写,扩展成从Eureka注册中心中获取服务端列表。同时它也会用NIWSDiscoveryPing来取代IPing,它将职责委托给Eureka来确定服务端是否已经启动。

下面我们通过实例看看如何使用Ribbon来调用服务,并实现客户端的均衡负载。
启动服务注册中心:wish.eureka.server(端口设置为1000)
启动服务提供方:wish.user.service(端口设置为2000)
启动服务提供方:wish.user.service(端口设置为2001)
可以使用命令 java -jar  wish.user.service-0.0.1-SNAPSHOT.jar --server.port=2001 启动服务并指定端口

此时访问:http://localhost:1000/
image

2.使用Ribbon实现客户端负载均衡的消费者

1.通过 http://start.spring.io/ 使用SPRING INITIALIZR 创建一个基础的Spring Boot工程,

  • Dependencies :Eureka Discovery + Ribbon
  • Group : com.alanzh.platform
  • Artifact : wish.ribbon.server
  • Spring boot 版本: 1.5.4
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.alanzh.platform</groupId>
    <artifactId>wish.ribbon.server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>wish.ribbon.server</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Dalston.SR1</spring-cloud.version>
    </properties>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>

@EnableDiscoveryClient注解来添加发现服务能力。

@Bean 创建RestTemplate实例,并注入到Spring容器里面.

@LoadBalanced注解开启均衡负载能力。

@EnableDiscoveryClient
@SpringBootApplication
public class Application {

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

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

3. 创建RibbonController通过RestTemplate来消费wish.user.service服务.

WISH.USER.SERVICE 是服务名字 可在http://localhost:1000查看

@RequestMapping(value="/user")
@RestController
public class RibbonController {

    @RequestMapping(value="/{userEntryID}", method=RequestMethod.GET) 
    public String getHelloWorld(@PathVariable String userEntryID) {
        return restTemplate.getForEntity("http://WISH.USER.SERVICE/user/" + userEntryID, String.class).getBody();
    }

    @Autowired
    RestTemplate restTemplate;
}

application.yml中配置eureka服务注册中心

# Portal Info

info:
  app:
    name: "@project.name@"
    description: "@project.description@"
    version: "@project.version@"

# Spring Info

spring:
  application:
    name: "@project.name@"

server:
  port: 3000

eureka:
  instance:
    lease-renewal-interval-in-seconds: 5      # 心跳时间,即服务续约间隔时间(缺省为30s)
    lease-expiration-duration-in-seconds: 10  # 发呆时间,即服务续约到期时间(缺省为90s)
  client:
    serviceUrl:
      defaultZone: http://admin:123123@localhost:1000/eureka/

启动应用,访问:http://localhost:3000/user/{ID}

3.在服务提供方打印日志

在UserEntryService.Java 中添加日志输出

    private void sleep() {
        try {
            ServiceInstance instance = client.getLocalServiceInstance();

            Thread.sleep(new Random().nextInt(2000));

            logger.info("host:" + instance.getHost() + ", service_id:" + instance.getServiceId());

        }
        catch (Exception e) {
        }
    }

    @Autowired
    private DiscoveryClient client;

    private final Logger logger = Logger.getLogger(getClass());

重启之后调用服务就会发现,WISH.USER.SERVICE的两个服务提供方,分别输出了类似下面的日志内容:

2017-07-03 16:14:30.227  INFO 4188 --- [nio-2000-exec-4] c.a.platform.service.UserEntryService    : host:ALAN-HOME, service_id:wish.user.service

4.齐活