6、SpringBoot整合ribbon项目实战 - lixiang987654321的专栏 - CSDN博客

一、客户端负载均衡

    Spring Cloud Ribbon是基于HTTP和TCP的客户端负载均衡工具,它是基于Netflix Ribbon实现的。通过Spring Cloud的封装,可以轻松地将面向服务的REST模板请求,自动转换成客户端负载均衡服务调用。 客户端负载均衡示意图如下所示:

二、Ribbon负载均衡实战

    我将要建立一个组合实例spring-ribbon-eureka,他包含如下实例,各个实例的作用如下:

(1)eureka_register_service

        eureka 注册服务,提供其他服务器的注册。

(2)ribbon_service_a

        系统中提供hello服务的服务器a

(3)ribbon_service_b

        系统中同样提供hello服务的服务器b

(4)ribbon_customer

          客户端负载均衡客户,同事负载从a或b服务器随机获取hello服务,启动服务发现功能,从注册中心发现提供hello服务的a和b并负载到a或b(根据各种算法,当然默认算法是轮训)。

2.1 新建spring-ribbon-eureka父项目

eclipse建立父项目步骤如下:

File->New->Others->Maven->Maven Project,选择Create a simple project,下一步填写GroupId和ArtifactId,重点是选择Packaging为pom,然后结束创建。

(1)创建之后修改父项目依赖,以便子项目继承(将子项目公共依赖提取出来,作为公共的依赖,放到父项目依赖中)

<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.0http://maven.apache.org/xsd/maven-4.0.0.xsd">  <!-- 项目属性 -->  <modelVersion>4.0.0</modelVersion>  <groupId>com.easystudy</groupId>  <artifactId>spring-ribbon-eureka</artifactId>  <version>0.0.1-SNAPSHOT</version>    <!-- 父级工程或聚合工程中,用来做jar包的版本控制 ,项目中所有要使用到的jar包的版本都集中由父工程管理-->  <packaging>pom</packaging>  <name>spring-ribbon-eureka</name>  <description>SpringBoot结合eureka使用</description>    <!-- 聚合的工程模块:通过继承聚合相关联-->  <modules>   <module>eureka_register_service</module> <!-- eureka注册中心:提供各个模块注册 -->   <module>ribbon_service_a</module> <!-- 服务器a,提供test-service服务 -->   <module>ribbon_service_b</module> <!-- 服务器b,提供test-service服务 -->   <module>ribbon_customer</module> <!-- 负载均衡客户端:服务发现与服务负载均衡 -->  </modules>    <!-- spring boot项目 -->  <parent>      <groupId>org.springframework.boot</groupId>      <artifactId>spring-boot-starter-parent</artifactId>      <version>2.0.2.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>Finchley.BUILD-SNAPSHOT</spring-cloud.version>  </properties>    <!-- 项目依赖管理声明,统一管理项目依赖的版本信息,继承项目无需声明版本 -->  <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>    <!-- 远程仓库:中央仓库找不到时候,从远程仓库中查找 -->  <repositories>      <repository>          <id>spring-snapshots</id>          <name>Spring Snapshots</name>          <url>https://repo.spring.io/snapshot</url>          <snapshots>              <enabled>true</enabled>          </snapshots>      </repository>      <repository>          <id>spring-milestones</id>          <name>Spring Milestones</name>          <url>https://repo.spring.io/milestone</url>          <snapshots>              <enabled>false</enabled>          </snapshots>      </repository>  </repositories>    <!-- 项目依赖 -->  <dependencies><!-- spring boot依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--spring boot测试--><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-actuator</artifactId></dependency><!-- 修改自动检测加载工具 -->    <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><optional>true</optional></dependency><!-- RESTFul接口文档:通过接口访问文档:http://localhost:8762/swagger-ui.html,8762为服务配置的监听端口,默认8080--><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.2.2</version></dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>2.2.2</version></dependency>  </dependencies>  <!-- 编译插件 -->  <build>      <plugins>         <!-- SpringBoot编译插件 -->          <plugin>              <groupId>org.springframework.boot</groupId>              <artifactId>spring-boot-maven-plugin</artifactId>          </plugin>      </plugins>  </build></project>

    各个依赖如上所述,不在一一说明,请自行查询相关依赖作用。spring-ribbon-eureka作用仅仅是提供公共部分的依赖和依赖管理以及build管理。

2.2 新建 eureka_register_service项目

eureka_register_service项目作用是提供服务注册功能,所有的服务都可以通过协议注册上来。新建步骤:选择spring-ribbon-eureka父项目,右键鼠标,弹出菜单中,选择Maven->New Maven Module Project,在弹出项目编辑框选择create a simple project并填写名称,下一步填写groupid和Artifactid,选择packaging类型为jar包,然后下一步即可完成。

(1)修改此时eureka_register_service注册中心pom.xml如下。

<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.0http://maven.apache.org/xsd/maven-4.0.0.xsd">  <!-- 项目信息 -->  <modelVersion>4.0.0</modelVersion>  <artifactId>eureka_register_service</artifactId>  <name>eureka register service</name>  <description>注册中心</description>   <!-- 父亲项目 -->  <parent>    <groupId>com.easystudy</groupId>    <artifactId>spring-ribbon-eureka</artifactId>    <version>0.0.1-SNAPSHOT</version>  </parent>   <!-- 项目依赖:特殊强制依赖,其他继承父亲 -->  <dependencies>       <!-- eureka服务器 -->      <dependency>          <groupId>org.springframework.cloud</groupId>          <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>      </dependency>  </dependencies> </project>

我们可以看到,父亲项目为spring-ribbon-eureka,且除了父亲依赖的依赖之外,自己依赖了spring-cloud-starter-netflix-eureka-server即eureka-server组件。

(2)在src/main/java下创建com.easystudy包,并添加启动入口:EurekaServerApp

package com.easystudy; import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @EnableEurekaServer                    // 开启eureka服务@SpringBootApplicationpublic class EurekaServerApp {     public static void main(String[] args) {        SpringApplication.run(EurekaServerApp.class, args);    } }

(3)在src/main/resources下添加启动配置文件,这里我们添加yml文件application.yml(当然可以application.properties文件,看你喜欢),配置信息如下:

# 第一个高可用注册中心server:  # 指定服务端口  port: 8761# eureka配置eureka:   instance:     hostname: localhost  client:    # 是否将eureka自身作为应用注册到eureka注册中心【这里设置为false,因为eureka服务和client不可能自己监听两套端口,serviceUrl可以天其他eureka服务地址,实现高可用】    registerWithEureka: false    # 为true时,可以启动,但报异常:Cannot execute request on any known server    fetchRegistry: false     serviceUrl:       # 引用对应值,通过配置其他可用的serviceUrl来实现相互注册【高可用配置】,这里可以实现本服务器注册到其他服务器去,实现服务器互为注册功能,达到两个或多个注册中心【即整个系统】的服务提供者信息共享      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/  server:    # 关闭自我保护    enable-self-preservation: false    # 清理服务器    eviction-interval-timer-in-ms: 60000    # 关闭程序endpoints:  shutdown:    enabled: true    sensitive: true

 具体配置项目描述很清楚,不明白自己查一下,这里我指出重点是:server.port端口8761即启动的内置tomcat监听端口8671提供服务。eureka.client.registerWithEureka=false表明eureka自己不是服务提供者,不需要将自己注册到注册中心,否则会出错。fetchRegistry表示是否从Eureka服务器中获取注册信息,默认为true,这里因为是服务器本身,不需要获取。defaultZone为注册中信息服务器提供的注册地址。

2.3 新建ribbon_service_a项目

    ribbon_service_a项目提供hello服务,也就是他是一个地地道道的SpringBoot项目,新建过程同2.2新建eureka_register_service

(1)新建之后配置pom.xml配置如下:

<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.0http://maven.apache.org/xsd/maven-4.0.0.xsd">  <!-- 项目信息 -->  <modelVersion>4.0.0</modelVersion>  <artifactId>ribbon_service_a</artifactId>  <name>service provider a</name>   <!-- 父亲项目 -->  <parent>    <groupId>com.easystudy</groupId>    <artifactId>spring-ribbon-eureka</artifactId>    <version>0.0.1-SNAPSHOT</version>  </parent>   <!-- 特别依赖,其他依赖继承父亲,其他元素也继承父亲 -->  <dependencies>     <!-- spring cloud 客户注册 -->     <dependency>           <groupId>org.springframework.cloud</groupId>          <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>     </dependency>  </dependencies> </project>

 (2)SpringBoot配置application.yml如下(src/main/resource)

# 多环境通用部分[各个环境可以覆盖通用字段]spring:   application:    # 通用名字,其他环境可以覆盖:为你的应用起个名字,该名字将注册到eureka注册中心    name: test-serviceserver:   # 服务提供监听端口[eureka客户端],注意改端口不能与本机服务器端口冲突  port: 8762eureka:  client:    # 是否将eureka自身作为应用注册到eureka注册中心,默认为true    registerWithEureka: true    service-url:      # 这里可以填写所有的eureka服务器地址并以','分离,当前面不能注册时候,自动选择后面的进行注册,排除单点故障问题      defaultZone:http://localhost:8761/eureka/

(3)新建ServiceAController控制层,提供hello服务

package com.easystudy.controller; import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController; @RestControllerpublic class ServiceAController {        @RequestMapping("/hello")    public String testA(){        return "Hello world AAAAAAAAAA!";    }}

 为了区分它与b服务器的打印,a它提供的hello服务打印“Hello world AAAAAAAAAA!”;

(4)创建a服务器的程序入口RibbonServiceApp

package com.easystudy; import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @SpringBootApplication@EnableDiscoveryClient     // 该注解会根据配置文件中的地址,将服务自身注册到服务注册中心public class RibbonServiceApp {     public static void main(String[] args) {        SpringApplication.run(RibbonServiceApp.class, args);    } }

2.3 新建ribbon_service_b项目

(1)新建ribbon_service_b

过程同ribbon_service_a

(2)修改pom配置文件

<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.0http://maven.apache.org/xsd/maven-4.0.0.xsd">  <!-- 项目信息 -->  <modelVersion>4.0.0</modelVersion>  <artifactId>ribbon_service_b</artifactId>  <name>ribbon service b</name>   <!-- 父亲项目 -->  <parent>    <groupId>com.easystudy</groupId>    <artifactId>spring-ribbon-eureka</artifactId>    <version>0.0.1-SNAPSHOT</version>  </parent>   <!-- 特别依赖,其他依赖继承父亲,其他元素也继承父亲 -->  <dependencies>     <!-- spring cloud 客户注册 -->     <dependency>           <groupId>org.springframework.cloud</groupId>          <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>     </dependency>  </dependencies> </project>

依赖配置同service_a,注意依赖eurreka客户端注册组件。

(3)添加(src/main/resources)application.yml配置文件

# 多环境通用部分[各个环境可以覆盖通用字段]spring:   application:    # 通用名字,其他环境可以覆盖:为你的应用起个名字,该名字将注册到eureka注册中心    name: test-serviceserver:   # 服务提供监听端口[eureka客户端],注意改端口不能与本机服务器端口冲突  port: 8763eureka:  client:    # 是否将eureka自身作为应用注册到eureka注册中心,默认为true    registerWithEureka: true    service-url:      # 这里可以填写所有的eureka服务器地址并以','分离,当前面不能注册时候,自动选择后面的进行注册,排除单点故障问题      defaultZone:http://localhost:8761/eureka/

注意:spring.application.name注册到eureka的同名的服务test-service,都提供hello服务。

(4)创建控制器ServiceBController提供服务

package com.easystudy.controller; import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController; @RestControllerpublic class ServiceBController {        @RequestMapping("/hello")    public String testB(){        return "Hello world BBBBBBB!";    }}

此处service_b服务打印的是Hello world BBBBBBB!,区别与service_a

(5)创建service_b的入口RibbonServiceApp

package com.easystudy; import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @SpringBootApplication@EnableDiscoveryClient     // 该注解会根据配置文件中的地址,将服务自身注册到服务注册中心public class RibbonServiceApp {     public static void main(String[] args) {        SpringApplication.run(RibbonServiceApp.class, args);    } }

2.3 新建ribbon_customer项目

ribbon_service_b项目和ribbon_service_a项目都提供hello服务,ribbon_customer则是提供了ribbon_service_a和ribbon_service_b负载的hello服务,也就是说ribbon_customer注册到eureka中心获取hello服务的service_a和service_b,然后通过客户端ribbon_customer的ribbon客户端负载均衡到service_a或service_b查找hello服务。

(1)新建ribbon_customer项目,过程同以上项目

(2)修改pom.xml配置

<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.0http://maven.apache.org/xsd/maven-4.0.0.xsd">  <!-- 本项目信息 -->  <modelVersion>4.0.0</modelVersion>  <artifactId>ribbon_customer</artifactId>  <name>customer</name>  <description>customer by ribbon</description>   <!-- 父项目 -->  <parent>    <groupId>com.easystudy</groupId>    <artifactId>spring-ribbon-eureka</artifactId>    <version>0.0.1-SNAPSHOT</version>  </parent>   <!-- 项目强依赖 -->  <dependencies>     <!-- spring cloud 客户注册 -->     <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-ribbon</artifactId>     </dependency>-->     <!-- Ribbon依赖 -->     <dependency>       <groupId>com.netflix.ribbon</groupId>       <artifactId>ribbon-core</artifactId>     </dependency>             <dependency>       <groupId>com.netflix.ribbon</groupId>       <artifactId>ribbon-httpclient</artifactId>     </dependency>     <!-- 加入熔断机制依赖 -->     <dependency>        <groupId>org.springframework.cloud</groupId>        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>    </dependency>  </dependencies>

注意,这里增加了ribbon依赖,hystrix熔断机制依赖

(3)增加配置文件application.yml

# 多环境通用部分[各个环境可以覆盖通用字段]spring:   application:    # 通用名字,其他环境可以覆盖:为你的应用起个名字,该名字将注册到eureka注册中心    name: ribbon-consumerserver:   # 服务提供监听端口[eureka客户端],注意改端口不能与本机服务器端口冲突  port: 8764eureka:  client:    # 是否将eureka自身作为应用注册到eureka注册中心,默认为true    registerWithEureka: true    service-url:      # 这里可以填写所有的eureka服务器地址并以','分离,当前面不能注册时候,自动选择后面的进行注册,排除单点故障问题      defaultZone:http://localhost:8761/eureka/

(4)增加CustomerController

package com.easystudy.controller; import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController; import com.easystudy.service.HelloService; @RestControllerpublic class CustomerController {        @Autowired    HelloService service;        @RequestMapping("/hi")    public String customer(){        return service.helloService();    }}

通过访问/hi访问hello服务

(4)增加hello负载均衡服务

package com.easystudy.service; import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import org.springframework.web.client.RestTemplate;import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; @Servicepublic class HelloService {        @Autowired    RestTemplate restTemplate;            // 负载均衡ribbon对象        // 熔断错误回调方法    public String helloFallBack(){        return "Error occurred!";    }        /**     * 调用Eureka系统中名都为test-service的ribbon_service_a或ribbon_service_b的方法/hello     * @return     */    // 注解指定发生错误时的回调方法    @HystrixCommand(fallbackMethod="helloFallBack")    public String helloService(){        // Get请求调用服务,restTemplate被@LoadBalanced注解标记,Get方法会自动进行负载均衡        // restTemplate会交替调用service_a和service_b        return restTemplate.getForObject("http://test-service/hello", String.class);    }}

 (5)增加启动入口

启动入口注入了RestTemplate提供负载均衡服务

package com.easystudy; import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;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; @EnableCircuitBreaker         // 开启断路器功能,进行容错管理@EnableDiscoveryClient        // 开启服务发现功能@SpringBootApplication        // SpringBoot应用public class CustomerApp {     @Bean                     // 注册一个具有容错功能的RestTemplate    @LoadBalanced             // 开启负载均衡客户端    RestTemplate restTemplate() {        return new RestTemplate();    }     public static void main(String[] args) {        SpringApplication.run(CustomerApp.class, args);    } }

三、测试

  通过访问ribbon_customer,负载到ribbon_service_a和ribbon_service_b,提供hello服务

(1)启动eureka_register_service提供eureka注册服务

(2)启动service_a服务

(3)启动service_b服务

(4)启动ribbon_customer服务

(5)访问eureka后台服务,查看test-service机器数量和状态

可以看到TEST-SERVICE服务有2机器分别对应服务名和端口为8762和8763,RIBBON-CONSUMER有一台机器对应服务端口8764;

(6)直接访问service_a服务http://localhost:8762/hello

(7)直接访问service_b服务http://localhost:8763/hello

(8)访问customer服务

再次刷新访问:

发现customer轮训负载到a和b机器提供hello服务,至此,ribbon负载均衡实例负载整个流程实例到此结束!


Original url: Access
Created at: 2019-04-25 17:32:00
Category: default
Tags: none

请先后发表评论
  • 最新评论
  • 总共0条评论