Spring Cloud(第二章)服务提供者 Eureka + 服务消费者(rest + Ribbon)

    Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具。它是一个基于HTTP和TCP的客户端负载均衡器。它可以通过在客户端中配置ribbonServerList来设置服务端列表去轮询访问以达到均衡负载的作用。

Ribbon是什么?

    Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法,将Netflix的中间层服务连接在一起。Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。简单的说,就是在配置文件中列出Load Balancer(简称LB)后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随即连接等)去连接这些机器。我们也很容易使用Ribbon实现自定义的负载均衡算法。
LB方案分类

    目前主流的LB方案可分成两类:一种是集中式LB, 即在服务的消费方和提供方之间使用独立的LB设施(可以是硬件,如F5, 也可以是软件,如nginx), 由该设施负责把访问请求通过某种策略转发至服务的提供方;另一种是进程内LB,将LB逻辑集成到消费方,消费方从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选择出一个合适的服务器。Ribbon就属于后者,它只是一个类库,集成于消费方进程,消费方通过它来获取到服务提供方的地址。
Ribbon的主要组件与工作流程

    微服务架构的核心思想是,一个应用是由多个小的、相互独立的、微服务组成,这些服务运行在自己的进程中,开发和发布都没有依赖。 不同服务通过一些轻量级交互机制来通信,例如 RPC、HTTP 等,服务可独立扩展伸缩,每个服务定义了明确的边界,不同的服务甚至可以采用不同的编程语言来实现,由独立的团队来维护。 简单的来说,一个系统的不同模块转变成不同的服务!而且服务可以使用不同的技术加以实现!
Ribbon的核心组件

均为接口类型,有以下几个

ServerList

    用于获取地址列表。它既可以是静态的(提供一组固定的地址),也可以是动态的(从注册中心中定期查询地址列表)。

ServerListFilter

    仅当使用动态ServerList时使用,用于在原始的服务列表中使用一定策略过虑掉一部分地址。

IRule

    选择一个最终的服务地址作为LB结果。选择策略有轮询、根据响应时间加权、断路器(当Hystrix可用时)等。
Ribbon在工作时首选会通过ServerList来获取所有可用的服务列表,然后通过ServerListFilter过虑掉一部分地址,最后在剩下的地址中通过IRule选择出一台服务器作为最终结果。

Ribbon提供的主要负载均衡策略介绍

简单轮询负载均衡(RoundRobin)

以轮询的方式依次将请求调度不同的服务器,即每次调度执行i = (i + 1) mod n,并选出第i台服务器。

随机负载均衡 (Random)

随机选择状态为UP的Server

加权响应时间负载均衡 (WeightedResponseTime)

根据相应时间分配一个weight,相应时间越长,weight越小,被选中的可能性越低。

区域感知轮询负载均衡(ZoneAvoidanceRule)

复合判断server所在区域的性能和server的可用性选择server

准备工作

本次项目示例,改造第一篇文章中的项目,使用spring-cloud-eureka-service作为服务注册中心,spring-cloud-eureka-provider,复制三分,项目名称依次修改为spring-cloud-eureka-provider-1 [1-3]

改造 Provider

服务提供者

在项目:spring-cloud-eureka-provider-1,spring-cloud-eureka-provider-2,spring-cloud-eureka-provider-3 的启动类,都加入@Value("${server.port}"),修改home()方法, 来区分不同端口的Controller 响应,因为接下来,使用ribbon做均衡需要测试需要使用到

package io.ymq.example.eureka.provider;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

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

@SpringBootApplication
@EnableEurekaClient
@RestController
public class EurekaProviderApplication {
    /**
     * 读取配置文件中的端口信息
    */
    @Value("${server.port}")
    String port;
    /**
     * 读取配置文件中的应用名
     */
    @Value("${spring.application.name}")
    String name;
    /**
     * 请求路径
     */
    @RequestMapping("/hello")
    /**
     * 返回map信息
     */
    public Map<String,String> home() {
        Map<String,String> map=new HashMap<>();
        map.put("port",port);
        map.put("name",name);
        return map;
    }

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

}

修改配置
在项目:spring-cloud-eureka-provider-1,spring-cloud-eureka-provider-2,spring-cloud-eureka-provider-3,修改server: port:端口依次为8081,8082,8083

server.port=8081
spring.application.name=eureka-provider
eureka.client.serviceUrl.defaultZone=http://192.168.0.101:8761/eureka
Ribbon Consumer

服务消费者

添加依赖
新建 spring-cloud-ribbon-consumer

<?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>io.ymq.example</groupId>
    <artifactId>spring-cloud-ribbon-consumer</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>spring-cloud-ribbon-consumer</name>
    <description>Eureka Ribbon Consumer Demo project for Spring Boot</description>

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

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

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--ribbon负载均衡-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--一定要加入这个依赖  -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <!-- RELEASE -->
                <version>Finchley.RELEASE</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向服务注册中心注册;并且向程序的ioc注入一个bean: restTemplate并通过@LoadBalanced注解表明这个restRemplate开启负载均衡的功能。

package io.ymq.example.ribbon.consumer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@EnableDiscoveryClient
@SpringBootApplication
public class RibbonConsumerApplication {
    /**
     * ribbon+restTemplate实现客户端负载均衡
    */
    @LoadBalanced
    @Bean
    RestTemplate restTemplate() {
        return new RestTemplate();
    }

	public static void main(String[] args) {
		SpringApplication.run(RibbonConsumerApplication.class, args);
	}
}
消费提供者方法

新建 ConsumerController 类,调用提供者的 hello 方法

package io.ymq.example.ribbon.consumer;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.Map;

/**
 * 描述:调用提供者的 `home` 方法
 *
 * @author lilei
 * @create 2019-04-23 22:48:53
 *
 * */

@RestController
public class ConsumerController {

    @Autowired
    private RestTemplate restTemplate;
        /**
         * 这个是调用eureka-consumer本身应用用的对应的hello方法
         */
    @GetMapping("/hello")
    public Map<String,String> hello() {
        /**
         * (1)http://eureka-provider/hello请求就是eureka-provider
         * 三个同名运用的 @RequestMapping("/hello")对应的home方法
         * (2)通过url就可以调用了home方法
         */
        return restTemplate.getForEntity("http://eureka-provider/hello", Map.class).getBody();
    }

}

添加配置
完整配置 application.properties

指定服务的注册中心地址,配置自己的服务端口,服务名称

server.port=8088
spring.application.name=eureka-consumer
eureka.client.serviceUrl.defaultZone=http://192.168.0.101:8761/eureka
测试服务

启动服务
依次启动项目:

spring-cloud-eureka-service
spring-cloud-eureka-provider-1
spring-cloud-eureka-provider-2
spring-cloud-eureka-provider-3
spring-cloud-ribbon-consumer

启动该工程后,访问服务注册中心,查看服务是否都已注册成功:http://192.168.0.101:8761/(192.168.0.101需要换成自己的IP)
在这里插入图片描述
负载均衡
在命令窗口curl http://192.168.0.101:8088/hello,发现Ribbon已经实现负载均衡

或者浏览器get 请求http://192.168.0.101:8088/hello F5 刷新
在这里插入图片描述
在这里插入图片描述
源码下载
GitHub:https://github.com/15029274098/springboot2.x-.git

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值