• 负载均衡Ribbon(三)


    更多内容参见个人技术博客,无广告欢迎关注

    1.1         消费者

    1.1.1      创建Maven工程

    1.1.2      pom.xml

    <?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>
    <parent>
    <groupId>com.wood</groupId>
    <artifactId>spring-cloud</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.wood</groupId>
    <artifactId>consumer-client</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>consumer-client</name>
    <description>Demo project for Spring Boot</description>

    <dependencies>
    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    </dependencies>
    </project>

    1.1.3      application.properties

    server.port=8091
    spring.application.name=consumer-client
    eureka.client.serviceUrl.defaultZone=http://localhost:6001/eureka

       

    1.1.4      HelloController.java

    RestTemplate是Spring提供的用于访问Rest服务的客户端,

    RestTemplate提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率。

    调用RestTemplate的默认构造函数,RestTemplate对象在底层通过使用java.net包下的实现创建HTTP 请求,

    可以通过使用ClientHttpRequestFactory指定不同的HTTP请求方式。

    ClientHttpRequestFactory接口主要提供了两种实现方式

    1、一种是SimpleClientHttpRequestFactory,使用J2SE提供的方式(既java.net包提供的方式)创建底层的Http请求连接。

    2、一种方式是使用HttpComponentsClientHttpRequestFactory方式,底层使用HttpClient访问远程的Http服务,使用HttpClient可以配置连接池和证书等信息。

    RestTemplate对象是在RunApp中声明并创建的,用它才可以实现负载均衡,同时注意url中的地址为VIP虚拟IP,为application.yml中配置的application-name

    package com.wood.consumerclient.controller;

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

    @RestController
    public class HelloController {

    /**
    * RestTemplate是Spring提供的用于访问Rest服务的客户端,
    *
    * RestTemplate提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率。
    *
    * 调用RestTemplate的默认构造函数,RestTemplate对象在底层通过使用java.net包下的实现创建HTTP 请求,
    *
    * 可以通过使用ClientHttpRequestFactory指定不同的HTTP请求方式。
    *
    * ClientHttpRequestFactory接口主要提供了两种实现方式
    *
    * 1、一种是SimpleClientHttpRequestFactory,使用J2SE提供的方式(既java.net包提供的方式)创建底层的Http请求连接。
    *
    * 2、一种方式是使用HttpComponentsClientHttpRequestFactory方式,底层使用HttpClient访问远程的Http服务,使用HttpClient可以配置连接池和证书等信息。
    *
    * RestTemplate对象是在RunApp中声明并创建的,用它才可以实现负载均衡,同时注意url中的地址为VIP虚拟IP,为application.yml中配置的application-name。
    * */
    @Autowired
    private RestTemplate restTemplate
    ;

    @GetMapping("/hello/{name}")
    @ResponseBody
    public String hello(@PathVariable String name){
    String url = "http://localhost:8081/hello" + name; //直接访问
    return this.restTemplate.getForObject(url, String.class);
    }
    }

    1.1.5      ConsumerRunApp.java

    重点在启动时要初始化RestTemplate对象,同时设置@LoadBalanced负载均衡

    package com.wood.consumerclient;

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
    import org.springframework.context.annotation.Bean;
    import org.springframework.web.client.RestTemplate;

    @SpringBootApplication
    @EnableEurekaClient
    public class ConsumerClientApplication {

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


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

    }

    1.1.6      测试

    package com.wood.consumerclient;

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
    import org.springframework.context.annotation.Bean;
    import org.springframework.web.client.RestTemplate;

    @SpringBootApplication
    @EnableEurekaClient
    public class ConsumerClientApplication {

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

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

    }

    执行顺序:

    先启动服务端     6001    eureka-server       EurekaServerApplication 

    在启动提供者1   8081    provider-a            ProviderAApplication

    在启动提供者2   8082    provider-b            ProviderBApplication

    最后启动消费者  8091    consumer-client    ConsumerClientApplication

    访问Eureka控制台:      http://localhost:6001/

    访问请求:               http://localhost:8091/hello/wood

    1.2         负载均衡Ribbon

    1.2.1      问题

    之前我们使用的是直接访问的方式,能否实现提供者端负载均衡呢?

        public String hello(){

            String url = "http://localhost:8091/hello/wood";

            return restTemplate.getForObject(url, String.class);

        }

    这是直接访问提供者,只能写死提供者的端口,并未使用Eureka注册中心,这样当服务宕机,我们也无从知道,只能访问超时。同时也无法“多例”服务进行支撑(负载均衡)。

    1.2.2      Ribbon

    Feignnetflix开发的声明式、模板化的http客户端,在使用时就像调用本地(服务消费者自己)的方法一般,帮助我们更加优雅的调用服务提供者的APIFeign自身支持springMVC,还整合了EurekaRibbon,极大的简化了Feign的使用。就整合Euraka而言,只需和普通的服务配置Eureka server的信息即可。整合Ribbon,就意味着不再需要通过标注@LoadBalanced的实例化后的RestTemplate去调用服务提供者方法了。Feign只需通过简单的定义一个接口即可实现负载均衡。

    nginx不同,它是客户端侧负载均衡。

     

    1.2.3      负载均衡策略

    常见提供的负载均衡算法有三种:

    第一种也是默认为轮询

    第二种为random随机

    第三种为WeightedResponseTimeRule,响应时间

     

    1.2.4      导包

    无需引入jar包,在spring-cloud-start-euraka已经依赖了ribbonjar包。

       

    1.3         消费者Ribbon

    1.3.1      修改Maven工程内容

    新建子工程 comsumer-client-ribbon,内容和consumer-client一样,修改端口为8092

    spring-cloud父工程pom.xml

    <!--Maven项目可以继承,三个子工程-->
    <modules>
    <module>eureka-server</module>
    <module>provider-a</module>
    <module>provider-b</module>
    <module>consumer-client</module>
    <module>consumer-client-ribbon</module>
    </modules> 

     1.3.2      pom.xml

    <?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>
    <parent>
    <groupId>com.wood</groupId>
    <artifactId>spring-cloud</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.wood</groupId>
    <artifactId>consumer-client-ribbon</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>consumer-client-ribbon</name>
    <description>Demo project for Spring Boot</description>

    <dependencies>
    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    </dependencies>
    </project>

    注意:怎么没有依赖ribbonjar包呢?

    因为eureka中已经含有对ribbon的支持,不需要额外的添加依赖

     

    1.3.3      application.properties

    server.port=8092
    spring.application.name=consumer-client-ribbon
    eureka.client.serviceUrl.defaultZone=http://localhost:6001/eureka
    # 定义根目录下日志级别
    logging.level.root=INFO

    1.3.4      HelloController.java

    RestTemplate对象是在RunApp中声明并创建的,用它才可以实现负载均衡,同时注意url中的地址为VIP虚拟IP,为application.yml中配置的application-name

    package 

    com.wood.consumerclientribbon.controller

    ;

    import

    org.springframework.beans.factory.annotation.

    Autowired;
    import

    org.springframework.web.bind.annotation.

    GetMapping;
    import

    org.springframework.web.bind.annotation.

    PathVariable;
    import

    org.springframework.web.bind.annotation.

    ResponseBody;
    import

    org.springframework.web.bind.annotation.

    RestController;
    import

    org.springframework.web.client.RestTemplate

    ;

    @RestController
    public class

    HelloController {

    /**
    * RestTemplate是Spring提供的用于访问Rest服务的客户端,
    *
    * RestTemplate提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率。
    *
    * 调用RestTemplate的默认构造函数,RestTemplate对象在底层通过使用java.net包下的实现创建HTTP 请求,
    *
    * 可以通过使用ClientHttpRequestFactory指定不同的HTTP请求方式。
    *
    * ClientHttpRequestFactory接口主要提供了两种实现方式
    *
    * 1、一种是SimpleClientHttpRequestFactory,使用J2SE提供的方式(既java.net包提供的方式)创建底层的Http请求连接。
    *
    * 2、一种方式是使用HttpComponentsClientHttpRequestFactory方式,底层使用HttpClient访问远程的Http服务,使用HttpClient可以配置连接池和证书等信息。
    *
    * RestTemplate对象是在RunApp中声明并创建的,用它才可以实现负载均衡,同时注意url中的地址为VIP虚拟IP,为application.yml中配置的application-name。
    * */
    @Autowired
    private

    RestTemplate

    restTemplate;

    @GetMapping

    (

    "/hello/{name}"

    )

    @ResponseBody
    public

    String

    hello

    (

    @PathVariable 

    String name){

    // VIP虚拟IP,提供者的application-name:provider-user
    String url = "http://provider-user/hello/"+name
    ;
    return this

    .

    restTemplate

    .getForObject(url

    , 

    String.

    class

    )

    ;

    }
    }

    1.3.5      ConsumerClientRibbonApplication.java

    重点在启动时要初始化RestTemplate对象,同时设置@LoadBalanced负载均衡

    package com.wood.consumerclientribbon;

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    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.RestTemplate;

    @SpringBootApplication
    @EnableEurekaClient
    public class ConsumerClientRibbonApplication {

    @Bean
    @LoadBalanced //Ribbon负载均衡
    public RestTemplate restTemplate(){
    return new RestTemplate();
    }

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

    }

    1.3.6      测试

    执行顺序:

    先启动服务端     6001    eureka-server        EurekaServerApplication

    在启动提供者1   8081    provider-user         ProviderAApplication

    在启动提供者2   8082    provider-user2       ProviderBApplication

    最后启动消费者  8092    consumer-client-ribbon  ConsumerClientRibbonApplication

    访问Eureka控制台:      http://localhost:6001/

     

    访问请求:               http://localhost:8092/hello/wood

    交替出现1:wood2:wood,说明两个提供者交替执行。这里注意有时可能提供者2还未准备好不能工作,多刷一会就正常了。可以看出Ribbon默认的负载均衡策略是轮询。

    服务提供者A:wood

    服务提供者B:wood 

    1.3.7      小结:怎么把普通的消费者改为Ribbon消费者

        Controller  

        @RequestMapping("/hello")

        public String hello(){

            //provider-user就是Eureka中提供服务

            String url = "http://provider-user/hello";

            //发起对Eureka中某个服务进行访问,返回值类型和业务返回值类型一致

            return restTemplate.getForObject(url, String.class);

        }

    启动类

    @EnableEurekaClient

    @SpringBootApplication

    public class CustomerClientRunApp {

        //初始化RestTemplate对象,Spring就初始化这个beand,就可以在Controller中注入

        @Bean

        @LoadBalanced    //实现负载均衡

        public RestTemplate restTemplate(){

            return new RestTemplate();

        }

    1.4         拓展:Ribbon随机负载算法

    1.4.1      RibbonRuleConfig.java

    自定义规则扩展对象

    package com.wood.config;

    import com.netflix.loadbalancer.IRule;
    import com.netflix.loadbalancer.RandomRule;
    import org.springframework.context.annotation.Bean;

    /**
    * <p>
    * RibbonRuleConfig
    * </p>
    * 自定义Ribbon配置
    * 规定:这个类不能再@ComponentScan和@SpringBootApplication本包和子包下,否则引起@RibbonClients扫描冲突
    * 注意:随机第一次打断点进入,之后多次刷新就不进入,可能由于本地缓存原因
    */
    public class RibbonRuleConfig {
    @Bean
    public IRule ribbonRule(){
    return new RandomRule();
    }
    }

    1.4.2      ConsumerClientRibbonApplication.java

    增加一个注解@RibbonClient(name="provider-user", configuration=RibbonRuleConfig.class)

    package com.wood.consumerclientribbon;

    import com.wood.config.RibbonRuleConfig;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.loadbalancer.LoadBalanced;
    import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
    import org.springframework.cloud.netflix.ribbon.RibbonClient;
    import org.springframework.context.annotation.Bean;
    import org.springframework.web.client.RestTemplate;

    @SpringBootApplication
    @EnableEurekaClient
    @RibbonClient(name="provider-user", configuration=RibbonRuleConfig.class)
    public class ConsumerClientRibbonApplication {

    @Bean
    @LoadBalanced //Ribbon负载均衡
    public RestTemplate restTemplate(){
    return new RestTemplate();
    }

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

    }

    附上代码 demo.zip

    https://pan.baidu.com/s/1X8GSuqMSMiyMz747aZtQTw 

  • 相关阅读:
    jquery插件课程1 幻灯片、城市选择、日期时间选择、拖放、方向拖动插件
    博客园随笔如何自动生成目录(原理:页脚js函数且执行)
    JAVA web四个属性的范围汇总
    关于继承modelDriven接口action的ajax来电参数
    Objective-C基调(4)Category
    Easyui使用记录
    jQuery地图热点效应-后在弹出的提示鼠标层信息
    跨境移动互联网的魅力演绎,hao123无论成就下一个条目?
    启示—地点IT高管20在职场心脏经(读书笔记6)
    C# 获得Excel工作簿Sheet页面(工作表)集合的名称
  • 原文地址:https://www.cnblogs.com/wood-life/p/10332499.html
Copyright © 2020-2023  润新知