Spring Cloud 详解(第二篇:Ribbon负载均衡)

Spring Cloud 详解(第二篇:Ribbon负载均衡)
@(Spring Cloud微服务)[java, spring-cloud, eureka,rtibbon]
接上一篇:http://blog.csdn.net/amon1991/article/details/79347660
我们测试了如何通过Eureka组件来构建一个注册中心,这一篇中,我们将使用注册中心Eureka和Ribbon组件实现简单的负载均衡功能。


      • 1搭建一组服务实例集群
      • 2搭建Ribbon客户端调用Service-hi服务
        • 第一步添加Mavan依赖
        • 第二步注解相关类
        • 第三步调用Service-hi服务
        • 第三步配置applicationyml文件
      • 3测试负载均衡服务

1、搭建一组服务实例集群

在本章中,我们将发布两个功能完全一致的service-hi实例,这两个实例在最终的生产环境中应该是无状态的,这样提供服务时,就可以保证无论使用哪个实例都可以提供相同的服务能力。

Eureka-client的基本搭建方法可参考http://blog.csdn.net/amon1991/article/details/79347660,我们在该服务中,在Controller层加入一个简单的测试功能,代码如下:

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

@RequestMapping("/hi")
public String home(@RequestParam String name) {
    return "hi "+name+",i am from port:" +port;
}

具体代码可以参考:https://github.com/amon1991/spring-cloud-demo/tree/master/eureka-client
接着,我们修改application.yml文件中的port参数,分别配置为8762、8763两个端口,并分别打包启动实例,启动后,可以在Eureka Server查看到两个实例已经被正常注册至注册中心:

Spring Cloud 详解(第二篇:Ribbon负载均衡)_第1张图片
如图所示,已经有两个service-hi注册到了注册中心,此时/hi这个接口就可以被其它服务使用了。

2、搭建Ribbon客户端调用Service-hi服务

服务实例集群注册到注册中心后,需要被成功调用才能发挥微服务框架的能力,Spring Cloud框架中提供两种方式实现负载均衡式的调用,分别为Ribbon和Feign。相对而言,Ribbon是对Spring的RestTemple接口的能力扩展,更加底层和通用一些;而Feign是基于Ribbon的又一层封装,层次更加高一些,集成度较高。本小节将说明如何搭建一个简单的Ribbon客户端并使用微服务的方式调用service-hi的服务。
搭建Ribbon客户端的具体步骤如下:
- 第一步:添加Mavan依赖 :加入Spring Boot和Spring Cloud相关依赖,并对应好版本;
- 第二步:注解相关类 :在启用类上加入@EnableDiscoveryClient注解,任意类配置 @LoadBalanced负载均衡注解;
- 第三步:调用Service-hi服务 :使用两种方式调用Service-hi提供的服务。
- 第四步:配置application.yml文件 :修改默认配置,适应生产环境。

第一步:添加Mavan依赖

完整的Maven依赖如下:


<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.0modelVersion>

    <groupId>com.siemens.springcloudgroupId>
    <artifactId>service-ribbonartifactId>
    <version>0.0.1-SNAPSHOTversion>
    <packaging>jarpackaging>

    <name>service-ribbonname>
    <description>Demo project for Spring Bootdescription>

    <parent>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>1.5.8.RELEASEversion>
        <relativePath/> 
    parent>

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

    <dependencies>

        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-eurekaartifactId>
        dependency>

        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-actuatorartifactId>
        dependency>

        
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-ribbonartifactId>
        dependency>

        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>

        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
            <scope>testscope>
        dependency>
    dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-dependenciesartifactId>
                <version>${spring-cloud.version}version>
                <type>pomtype>
                <scope>importscope>
            dependency>
        dependencies>
    dependencyManagement>

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


project>

第二步:注解相关类

首先需要在启用类上做如下配置:

@SpringBootApplication
@EnableDiscoveryClient
public class ServiceRibbonApplication {

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

}

为了让大家更加区分清楚普通服务请求方式和Ribbon请求方式的区别,本例中构造了两个RestTemplate实例,分别对应于普通实例和Ribbon实例:

@Bean(name = "ribbonRestTemplate")
@LoadBalanced
RestTemplate ribbonRestTemplate() {
    return new RestTemplate();
}


@Bean(name = "commonRestTemplate")
RestTemplate commonRestTemplate() {
    return new RestTemplate();
}

这两个实例的构造可以放置于任意可被加载进Spring Context环境的配置类中,比如启用类,或者专门的配置类(加@Configuration注解)

第三步:调用Service-hi服务

我们使用两种方式来调用service-hi的服务,一种是用过IP和端口直连调用的方式,另外一种使用Ribbon的方式。

1、IP+端口直接调用:

@Resource(name = "commonRestTemplate")
RestTemplate commonRestTemplate;

/**
 * send restful request by common restTemplate
 * @param name
 * @return
 */
public String commonHiService(String name) {
    return commonRestTemplate.getForObject("http://localhost:8762/hi?name="+name,String.class);
}

2、Ribbon方式调用:

@Resource(name = "ribbonRestTemplate")
RestTemplate ribbonRestTemplate;

/**
 * send restful request by ribbon interceptor
 * @param name
 * @return
 */
public String hiService(String name) {
    return ribbonRestTemplate.getForObject("http://service-hi/hi?name="+name,String.class);
}

可以看到Ribbon方式直接使用服务名来访问服务,实际代码底层,会通过eureka提供的注册服务表及相应的负载均衡算法转化为IP和端口,并最终向具体实例发送相关请求。

具体代码可参考:https://github.com/amon1991/spring-cloud-demo/tree/master/service-ribbon

第三步:配置application.yml文件

server:
  port: 8764
spring:
  application:
    name: service-ribbon

eureka:
  instance:
    lease-renewal-interval-in-seconds: 5      # 心跳时间,即服务续约间隔时间(缺省为30s)
    lease-expiration-duration-in-seconds: 15  # 发呆时间,即服务续约到期时间(缺省为90s)
  client:
    registry-fetch-interval-seconds: 10 # 拉取服务注册信息间隔(缺省为30s)
    service-url:
      defaultZone: http://localhost:8761/eureka/
    healthcheck:
      enabled: true # 开启健康检查(依赖spring-boot-starter-actuator)

1、eureka.instance.lease-renewal-interval-in-seconds:
lease-renewal-interval-in-seconds,表示eureka client发送心跳给server端的频率。如果在leaseExpirationDurationInSeconds后,server端没有收到client的心跳,则将摘除该instance。除此之外,如果该instance实现了HealthCheckCallback,并决定让自己unavailable的话,则该instance也不会接收到流量,默认30秒。

2、eureka.instance.lease-expiration-duration-in-seconds:
lease-expiration-duration-in-seconds,表示eureka server至上一次收到client的心跳之后,等待下一次心跳的超时时间,在这个时间内若没收到下一次心跳,则将移除该instance,该值默认为90秒。

3、eureka.client.registry-fetch-interval-seconds:
表示eureka client间隔多久去拉取服务注册信息,默认为30秒,对于api-gateway,如果要迅速获取服务注册状态,可以缩小该值,比如5秒。

配置结束之后,启动Spring-Boot程序,该实例也会注册到Eureka注册中心中,如图:
Spring Cloud 详解(第二篇:Ribbon负载均衡)_第2张图片

3、测试负载均衡服务

我们通过访问Ribbon客户端所在web服务来测试其内部是否对service-hi中的服务进行了正确调用。

1、IP+端口直接调用:
Spring Cloud 详解(第二篇:Ribbon负载均衡)_第3张图片
如图所示,不断刷新浏览器,可以看到服务返回的端口保持在8762,不会变化,因为代码内部固定了访问的端口信息。

2、Ribbon方式调用:
Spring Cloud 详解(第二篇:Ribbon负载均衡)_第4张图片

Spring Cloud 详解(第二篇:Ribbon负载均衡)_第5张图片

如图所示,不断刷新浏览器,返回端口信息不断在8762和8763之间切换,说明ribbon客户端已经帮我们在负载均衡的访问Service-hi实例,且访问的频率是基本平均的。

至此,我们已经完成了一个简单Ribbon客户端的测试,通过测试我们通过了对eureka-client的负载均衡访问测试。

你可能感兴趣的:(java高级编程,spring-cloud)