Ribbon简介
简介
Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,它基于Netflix Ribbon实现。通过Spring Cloud的封装,可以让我们轻松地将面向服务的REST模版请求自动转换成客户端负载均衡的服务调用。Spring Cloud Ribbon虽然只是一个工具类框架,它不像服务注册中心、配置中心、API网关那样需要独立部署,但是它几乎存在于每一个Spring Cloud构建的微服务和基础设施中。因为微服务间的调用,API网关的请求转发等内容,实际上都是通过Ribbon来实现的,包括后续我们将要介绍的Feign,它也是基于Ribbon实现的工具。所以,对Spring Cloud Ribbon的理解和使用,对于我们使用Spring Cloud来构建微服务非常重要。
在这一章中,我们将具体介绍如何使用Ribbon来实现客户端的负载均衡,并且通过源码分析来了解Ribbon实现客户端负载均衡的基本原理。
客户端负载均衡
负载均衡在系统架构中是一个非常重要,并且是不得不去实施的内容。因为负载均衡是对系统的高可用、网络压力的缓解和处理能力扩容的重要手段之一。我们通常所说的负载均衡都指的是服务端负载均衡,其中分为硬件负载均衡和软件负载均衡。硬件负载均衡主要通过在服务器节点之间按照专门用于负载均衡的设备,比如F5等;而软件负载均衡则是通过在服务器上安装一些用于负载均衡功能或模块等软件来完成请求分发工作,比如Nginx等。不论采用硬件负载均衡还是软件负载均衡,只要是服务端都能以类似下图的架构方式构建起来:
负载均衡架构图
硬件负载均衡的设备或是软件负载均衡的软件模块都会维护一个下挂可用的服务端清单,通过心跳检测来剔除故障的服务端节点以保证清单中都是可以正常访问的服务端节点。当客户端发送请求到负载均衡设备的时候,该设备按某种算法(比如线性轮询、按权重负载、按流量负载等)从维护的可用服务端清单中取出一台服务端端地址,然后进行转发。
而客户端负载均衡和服务端负载均衡最大的不同点在于上面所提到服务清单所存储的位置。在客户端负载均衡中,所有客户端节点都维护着自己要访问的服务端清单,而这些服务端端清单来自于服务注册中心,比如上一章我们介绍的Eureka服务端。同服务端负载均衡的架构类似,在客户端负载均衡中也需要心跳去维护服务端清单的健康性,默认会创建针对各个服务治理框架的Ribbon自动化整合配置,比如Eureka中的org.springframework.cloud.netflix.ribbon.eureka.RibbonEurekaAutoConfiguration,Consul中的org.springframework.cloud.consul.discovery.RibbonConsulAutoConfiguration。在实际使用的时候,我们可以通过查看这两个类的实现,以找到它们的配置详情来帮助我们更好地使用它。
通过Spring Cloud Ribbon的封装,我们在微服务架构中使用客户端负载均衡调用非常简单,只需要如下两步:
▪️服务提供者只需要启动多个服务实例并注册到一个注册中心或是多个相关联的服务注册中心。
▪️服务消费者直接通过调用被@LoadBalanced注解修饰过的RestTemplate来实现面向服务的接口调用。
这样,我们就可以将服务提供者的高可用以及服务消费者的负载均衡调用一起实现了。
服务消费者整合Ribbon
依赖
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.itmuch.cloud</groupId>
<artifactId>microservice-consumer-movie-ribbon</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>microservice-consumer-movie-ribbon</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<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>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<!--引入spring cloud依赖-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Camden.SR4</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>
yml
server:
port: 8010
spring:
application:
name: microservice-consumer-movie
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/,http://localhost:8762/eureka/,http://localhost:8763/eureka/
instance:
prefer-ip-address: true
为RestTemplate添加@LoadBalance注解
package com.itmuch.cloud.microserviceconsumermovieribbon;
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;
@SpringBootApplication
@EnableDiscoveryClient
public class MicroserviceConsumerMovieRibbonApplication {
/**
* 实例化一个Bean并使用该方法的名字命名
* @return
*/
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(MicroserviceConsumerMovieRibbonApplication.class, args);
}
}
修改controller
package com.itmuch.cloud.microserviceconsumermovieribbon.controller;
import com.itmuch.cloud.microserviceconsumermovieribbon.entity.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class MovieController {
@Autowired
private RestTemplate restTemplate;
@Autowired
private LoadBalancerClient loadBalancerClient;
private static final Logger logger = LoggerFactory.getLogger(MovieController.class);
/**
* microservice-provider-user:虚拟主机名
* @param id
* @return
*/
@GetMapping("/user/{id}")
public User findById(@PathVariable Long id){
return this.restTemplate.getForObject("http://microservice-provider-user/" + id,User.class);
}
@GetMapping("/log-instance")
public void logUserInstance(){
ServiceInstance serviceInstance = this.loadBalancerClient.choose("microservice-provider-user");
//打印当前选择的那个节点
MovieController.logger.info("{}:{}:{}",serviceInstance.getServiceId(),serviceInstance.getHost(),serviceInstance.getPort());
}
}
启动多个服务提供user
依赖
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.itmuch.cloud</groupId>
<artifactId>microservice-provider-user</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>microservice-provider-user</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--提供Spring Data Jpa的支持-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!--提供Spring MVC的支持-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.9</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.11</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<!--引入spring cloud依赖-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Camden.SR4</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>
yml
server:
port: 8000 8001 #提供两个服务提供者
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/spring_cloud?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8
username: root
password: 123
type: com.alibaba.druid.pool.DruidDataSource
jpa:
show-sql: true
hibernate:
ddl-auto: update
database: mysql
application:
name: microservice-provider-user #注册到eureka server中的服务名
logging:
level:
root: info
org.hibernate: info
org.hibernate.type.descriptor.sql.BasicBinder: TRACE
org.hibernate.type.descriptor.sql.BasicExtractor: TRACE
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/,http://localhost:8762/eureka/,http://localhost:8763/eureka/
instance:
prefer-ip-address: true
# #表示讲自己的IP祖册到Eureka Server 如果不配置或者false,则表示注册微服务所在操作系统的hostname到Eureka server
启动类
package com.itmuch.cloud.microserviceprovideruser;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient //声明这是一个eureka客户端
public class MicroserviceProviderUserApplication {
public static void main(String[] args) {
SpringApplication.run(MicroserviceProviderUserApplication.class, args);
}
}
controller
package com.itmuch.cloud.microserviceprovideruser.controller;
import com.itmuch.cloud.microserviceprovideruser.dao.UserRepository;
import com.itmuch.cloud.microserviceprovideruser.entity.User;
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.RestController;
@RestController
public class UserController {
@Autowired
private UserRepository userRepository;
@GetMapping("/{id}")
public User findById(@PathVariable Long id){
User findOne = this.userRepository.findOne(id);
return findOne;
}
}
dao
package com.itmuch.cloud.microserviceprovideruser.dao;
import com.itmuch.cloud.microserviceprovideruser.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UserRepository extends JpaRepository<User,Long> {
}
实体类
package com.itmuch.cloud.microserviceprovideruser.entity;
import javax.persistence.*;
import java.math.BigDecimal;
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column
private String username;
@Column
private String name;
@Column
private Integer age;
@Column
private BigDecimal balance;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public BigDecimal getBalance() {
return balance;
}
public void setBalance(BigDecimal balance) {
this.balance = balance;
}
}
启动两个,然后启动eureka server集群
测试结果 http://localhost:8010/log-instance
"C:\Program Files\Java\jdk1.8.0_112\bin\java.exe" -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:56625,suspend=y,server=n -XX:TieredStopAtLevel=1 -noverify -Dspring.output.ansi.enabled=always -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=56624 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=localhost -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true -javaagent:C:\Users\user\.IntelliJIdea2018.2\system\captureAgent\debugger-agent.jar=file:/C:/Users/user/AppData/Local/Temp/capture.props -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_112\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_112\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_112\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_112\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_112\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_112\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_112\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_112\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_112\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_112\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_112\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_112\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_112\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_112\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_112\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_112\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_112\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_112\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_112\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_112\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_112\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_112\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_112\jre\lib\rt.jar;F:\gitsource\guns\stylefeng-guns-master\spring_cloud\microservice-consumer-movie-ribbon\target\classes;D:\m2_repository\org\springframework\boot\spring-boot-starter-web\1.4.3.RELEASE\spring-boot-starter-web-1.4.3.RELEASE.jar;D:\m2_repository\org\springframework\boot\spring-boot-starter\1.4.3.RELEASE\spring-boot-starter-1.4.3.RELEASE.jar;D:\m2_repository\org\springframework\boot\spring-boot\1.4.3.RELEASE\spring-boot-1.4.3.RELEASE.jar;D:\m2_repository\org\springframework\boot\spring-boot-autoconfigure\1.4.3.RELEASE\spring-boot-autoconfigure-1.4.3.RELEASE.jar;D:\m2_repository\org\springframework\boot\spring-boot-starter-logging\1.4.3.RELEASE\spring-boot-starter-logging-1.4.3.RELEASE.jar;D:\m2_repository\ch\qos\logback\logback-classic\1.1.8\logback-classic-1.1.8.jar;D:\m2_repository\ch\qos\logback\logback-core\1.1.8\logback-core-1.1.8.jar;D:\m2_repository\org\slf4j\jcl-over-slf4j\1.7.22\jcl-over-slf4j-1.7.22.jar;D:\m2_repository\org\slf4j\jul-to-slf4j\1.7.22\jul-to-slf4j-1.7.22.jar;D:\m2_repository\org\slf4j\log4j-over-slf4j\1.7.22\log4j-over-slf4j-1.7.22.jar;D:\m2_repository\org\yaml\snakeyaml\1.17\snakeyaml-1.17.jar;D:\m2_repository\org\springframework\boot\spring-boot-starter-tomcat\1.4.3.RELEASE\spring-boot-starter-tomcat-1.4.3.RELEASE.jar;D:\m2_repository\org\apache\tomcat\embed\tomcat-embed-core\8.5.6\tomcat-embed-core-8.5.6.jar;D:\m2_repository\org\apache\tomcat\embed\tomcat-embed-el\8.5.6\tomcat-embed-el-8.5.6.jar;D:\m2_repository\org\apache\tomcat\embed\tomcat-embed-websocket\8.5.6\tomcat-embed-websocket-8.5.6.jar;D:\m2_repository\org\hibernate\hibernate-validator\5.2.4.Final\hibernate-validator-5.2.4.Final.jar;D:\m2_repository\javax\validation\validation-api\1.1.0.Final\validation-api-1.1.0.Final.jar;D:\m2_repository\org\jboss\logging\jboss-logging\3.3.0.Final\jboss-logging-3.3.0.Final.jar;D:\m2_repository\com\fasterxml\classmate\1.3.3\classmate-1.3.3.jar;D:\m2_repository\com\fasterxml\jackson\core\jackson-databind\2.8.5\jackson-databind-2.8.5.jar;D:\m2_repository\com\fasterxml\jackson\core\jackson-annotations\2.8.5\jackson-annotations-2.8.5.jar;D:\m2_repository\com\fasterxml\jackson\core\jackson-core\2.8.5\jackson-core-2.8.5.jar;D:\m2_repository\org\springframework\spring-web\4.3.5.RELEASE\spring-web-4.3.5.RELEASE.jar;D:\m2_repository\org\springframework\spring-aop\4.3.5.RELEASE\spring-aop-4.3.5.RELEASE.jar;D:\m2_repository\org\springframework\spring-beans\4.3.5.RELEASE\spring-beans-4.3.5.RELEASE.jar;D:\m2_repository\org\springframework\spring-context\4.3.5.RELEASE\spring-context-4.3.5.RELEASE.jar;D:\m2_repository\org\springframework\spring-webmvc\4.3.5.RELEASE\spring-webmvc-4.3.5.RELEASE.jar;D:\m2_repository\org\springframework\spring-expression\4.3.5.RELEASE\spring-expression-4.3.5.RELEASE.jar;D:\m2_repository\org\springframework\boot\spring-boot-starter-actuator\1.4.3.RELEASE\spring-boot-starter-actuator-1.4.3.RELEASE.jar;D:\m2_repository\org\springframework\boot\spring-boot-actuator\1.4.3.RELEASE\spring-boot-actuator-1.4.3.RELEASE.jar;D:\m2_repository\org\springframework\cloud\spring-cloud-starter-eureka\1.2.4.RELEASE\spring-cloud-starter-eureka-1.2.4.RELEASE.jar;D:\m2_repository\org\springframework\cloud\spring-cloud-starter\1.1.7.RELEASE\spring-cloud-starter-1.1.7.RELEASE.jar;D:\m2_repository\org\springframework\cloud\spring-cloud-context\1.1.7.RELEASE\spring-cloud-context-1.1.7.RELEASE.jar;D:\m2_repository\org\springframework\security\spring-security-crypto\4.1.4.RELEASE\spring-security-crypto-4.1.4.RELEASE.jar;D:\m2_repository\org\springframework\cloud\spring-cloud-commons\1.1.7.RELEASE\spring-cloud-commons-1.1.7.RELEASE.jar;D:\m2_repository\org\springframework\security\spring-security-rsa\1.0.3.RELEASE\spring-security-rsa-1.0.3.RELEASE.jar;D:\m2_repository\org\bouncycastle\bcpkix-jdk15on\1.55\bcpkix-jdk15on-1.55.jar;D:\m2_repository\org\bouncycastle\bcprov-jdk15on\1.55\bcprov-jdk15on-1.55.jar;D:\m2_repository\org\springframework\cloud\spring-cloud-netflix-core\1.2.4.RELEASE\spring-cloud-netflix-core-1.2.4.RELEASE.jar;D:\m2_repository\org\springframework\cloud\spring-cloud-netflix-eureka-client\1.2.4.RELEASE\spring-cloud-netflix-eureka-client-1.2.4.RELEASE.jar;D:\m2_repository\com\netflix\eureka\eureka-client\1.4.12\eureka-client-1.4.12.jar;D:\m2_repository\org\codehaus\jettison\jettison\1.3.7\jettison-1.3.7.jar;D:\m2_repository\stax\stax-api\1.0.1\stax-api-1.0.1.jar;D:\m2_repository\com\netflix\netflix-commons\netflix-eventbus\0.3.0\netflix-eventbus-0.3.0.jar;D:\m2_repository\com\netflix\netflix-commons\netflix-infix\0.3.0\netflix-infix-0.3.0.jar;D:\m2_repository\commons-jxpath\commons-jxpath\1.3\commons-jxpath-1.3.jar;D:\m2_repository\joda-time\joda-time\2.9.6\joda-time-2.9.6.jar;D:\m2_repository\org\antlr\antlr-runtime\3.4\antlr-runtime-3.4.jar;D:\m2_repository\org\antlr\stringtemplate\3.2.1\stringtemplate-3.2.1.jar;D:\m2_repository\antlr\antlr\2.7.7\antlr-2.7.7.jar;D:\m2_repository\com\google\code\gson\gson\2.7\gson-2.7.jar;D:\m2_repository\org\apache\commons\commons-math\2.2\commons-math-2.2.jar;D:\m2_repository\com\netflix\archaius\archaius-core\0.7.4\archaius-core-0.7.4.jar;D:\m2_repository\javax\ws\rs\jsr311-api\1.1.1\jsr311-api-1.1.1.jar;D:\m2_repository\com\netflix\servo\servo-core\0.10.1\servo-core-0.10.1.jar;D:\m2_repository\com\netflix\servo\servo-internal\0.10.1\servo-internal-0.10.1.jar;D:\m2_repository\com\sun\jersey\jersey-core\1.19.1\jersey-core-1.19.1.jar;D:\m2_repository\com\sun\jersey\jersey-client\1.19.1\jersey-client-1.19.1.jar;D:\m2_repository\com\sun\jersey\contribs\jersey-apache-client4\1.19.1\jersey-apache-client4-1.19.1.jar;D:\m2_repository\org\apache\httpcomponents\httpclient\4.5.2\httpclient-4.5.2.jar;D:\m2_repository\org\apache\httpcomponents\httpcore\4.4.5\httpcore-4.4.5.jar;D:\m2_repository\commons-codec\commons-codec\1.10\commons-codec-1.10.jar;D:\m2_repository\com\google\inject\guice\4.0\guice-4.0.jar;D:\m2_repository\aopalliance\aopalliance\1.0\aopalliance-1.0.jar;D:\m2_repository\com\netflix\governator\governator-api\1.12.10\governator-api-1.12.10.jar;D:\m2_repository\com\netflix\eureka\eureka-core\1.4.12\eureka-core-1.4.12.jar;D:\m2_repository\com\netflix\governator\governator\1.12.10\governator-1.12.10.jar;D:\m2_repository\com\netflix\governator\governator-core\1.12.10\governator-core-1.12.10.jar;D:\m2_repository\com\google\inject\extensions\guice-multibindings\4.0\guice-multibindings-4.0.jar;D:\m2_repository\com\google\inject\extensions\guice-grapher\4.0\guice-grapher-4.0.jar;D:\m2_repository\com\google\inject\extensions\guice-assistedinject\4.0\guice-assistedinject-4.0.jar;D:\m2_repository\org\ow2\asm\asm\5.0.4\asm-5.0.4.jar;D:\m2_repository\org\codehaus\woodstox\woodstox-core-asl\4.4.1\woodstox-core-asl-4.4.1.jar;D:\m2_repository\javax\xml\stream\stax-api\1.0-2\stax-api-1.0-2.jar;D:\m2_repository\org\codehaus\woodstox\stax2-api\3.1.4\stax2-api-3.1.4.jar;D:\m2_repository\org\springframework\cloud\spring-cloud-starter-archaius\1.2.4.RELEASE\spring-cloud-starter-archaius-1.2.4.RELEASE.jar;D:\m2_repository\commons-configuration\commons-configuration\1.8\commons-configuration-1.8.jar;D:\m2_repository\com\google\guava\guava\18.0\guava-18.0.jar;D:\m2_repository\com\netflix\ribbon\ribbon-eureka\2.2.0\ribbon-eureka-2.2.0.jar;D:\m2_repository\org\slf4j\slf4j-api\1.7.22\slf4j-api-1.7.22.jar;D:\m2_repository\com\thoughtworks\xstream\xstream\1.4.9\xstream-1.4.9.jar;D:\m2_repository\xmlpull\xmlpull\1.1.3.1\xmlpull-1.1.3.1.jar;D:\m2_repository\xpp3\xpp3_min\1.1.4c\xpp3_min-1.1.4c.jar;D:\m2_repository\org\springframework\cloud\spring-cloud-starter-ribbon\1.2.4.RELEASE\spring-cloud-starter-ribbon-1.2.4.RELEASE.jar;D:\m2_repository\org\springframework\boot\spring-boot-starter-aop\1.4.3.RELEASE\spring-boot-starter-aop-1.4.3.RELEASE.jar;D:\m2_repository\org\aspectj\aspectjweaver\1.8.9\aspectjweaver-1.8.9.jar;D:\m2_repository\org\springframework\retry\spring-retry\1.1.5.RELEASE\spring-retry-1.1.5.RELEASE.jar;D:\m2_repository\com\netflix\ribbon\ribbon\2.2.0\ribbon-2.2.0.jar;D:\m2_repository\com\netflix\ribbon\ribbon-transport\2.2.0\ribbon-transport-2.2.0.jar;D:\m2_repository\io\reactivex\rxnetty-contexts\0.4.9\rxnetty-contexts-0.4.9.jar;D:\m2_repository\io\reactivex\rxnetty-servo\0.4.9\rxnetty-servo-0.4.9.jar;D:\m2_repository\com\netflix\hystrix\hystrix-core\1.5.6\hystrix-core-1.5.6.jar;D:\m2_repository\org\hdrhistogram\HdrHistogram\2.1.9\HdrHistogram-2.1.9.jar;D:\m2_repository\javax\inject\javax.inject\1\javax.inject-1.jar;D:\m2_repository\io\reactivex\rxnetty\0.4.9\rxnetty-0.4.9.jar;D:\m2_repository\io\netty\netty-codec-http\4.0.27.Final\netty-codec-http-4.0.27.Final.jar;D:\m2_repository\io\netty\netty-codec\4.0.27.Final\netty-codec-4.0.27.Final.jar;D:\m2_repository\io\netty\netty-handler\4.0.27.Final\netty-handler-4.0.27.Final.jar;D:\m2_repository\io\netty\netty-transport-native-epoll\4.0.27.Final\netty-transport-native-epoll-4.0.27.Final.jar;D:\m2_repository\io\netty\netty-common\4.0.27.Final\netty-common-4.0.27.Final.jar;D:\m2_repository\io\netty\netty-buffer\4.0.27.Final\netty-buffer-4.0.27.Final.jar;D:\m2_repository\io\netty\netty-transport\4.0.27.Final\netty-transport-4.0.27.Final.jar;D:\m2_repository\com\netflix\ribbon\ribbon-core\2.2.0\ribbon-core-2.2.0.jar;D:\m2_repository\commons-lang\commons-lang\2.6\commons-lang-2.6.jar;D:\m2_repository\com\netflix\ribbon\ribbon-httpclient\2.2.0\ribbon-httpclient-2.2.0.jar;D:\m2_repository\commons-collections\commons-collections\3.2.2\commons-collections-3.2.2.jar;D:\m2_repository\com\netflix\netflix-commons\netflix-commons-util\0.1.1\netflix-commons-util-0.1.1.jar;D:\m2_repository\com\netflix\ribbon\ribbon-loadbalancer\2.2.0\ribbon-loadbalancer-2.2.0.jar;D:\m2_repository\com\netflix\netflix-commons\netflix-statistics\0.1.1\netflix-statistics-0.1.1.jar;D:\m2_repository\io\reactivex\rxjava\1.1.10\rxjava-1.1.10.jar;D:\m2_repository\org\springframework\spring-core\4.3.5.RELEASE\spring-core-4.3.5.RELEASE.jar;D:\idea\IntelliJ IDEA 2018.2.4\lib\idea_rt.jar" com.itmuch.cloud.microserviceconsumermovieribbon.MicroserviceConsumerMovieRibbonApplication
Connected to the target VM, address: '127.0.0.1:56625', transport: 'socket'
2019-10-25 11:31:04.536 INFO 22436 --- [ main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@41ab013: startup date [Fri Oct 25 11:31:04 CST 2019]; root of context hierarchy
2019-10-25 11:31:04.873 INFO 22436 --- [ main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
2019-10-25 11:31:04.920 INFO 22436 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesRebinderAutoConfiguration' of type [class org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$cf0a7647] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v1.4.3.RELEASE)
2019-10-25 11:31:05.373 INFO 22436 --- [ main] croserviceConsumerMovieRibbonApplication : No active profile set, falling back to default profiles: default
2019-10-25 11:31:05.389 INFO 22436 --- [ main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@138a7441: startup date [Fri Oct 25 11:31:05 CST 2019]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@41ab013
2019-10-25 11:31:06.076 WARN 22436 --- [ main] o.s.c.a.ConfigurationClassPostProcessor : Cannot enhance @Configuration bean definition 'refreshScope' since its singleton instance has been created too early. The typical cause is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor return type: Consider declaring such methods as 'static'.
2019-10-25 11:31:06.185 INFO 22436 --- [ main] o.s.cloud.context.scope.GenericScope : BeanFactory id=e550db78-c83c-3c42-8451-90eed13f1417
2019-10-25 11:31:06.248 INFO 22436 --- [ main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
2019-10-25 11:31:06.420 INFO 22436 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration' of type [class org.springframework.cloud.netflix.metrics.MetricsInterceptorConfiguration$MetricsRestTemplateConfiguration$$EnhancerBySpringCGLIB$$e51d198b] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2019-10-25 11:31:06.420 INFO 22436 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [class org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$cf0a7647] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2019-10-25 11:31:06.701 INFO 22436 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8010 (http)
2019-10-25 11:31:06.717 INFO 22436 --- [ main] o.apache.catalina.core.StandardService : Starting service Tomcat
2019-10-25 11:31:06.717 INFO 22436 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.6
2019-10-25 11:31:06.826 INFO 22436 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2019-10-25 11:31:06.826 INFO 22436 --- [ost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1437 ms
2019-10-25 11:31:07.076 INFO 22436 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/]
2019-10-25 11:31:07.076 INFO 22436 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'metricsFilter' to: [/*]
2019-10-25 11:31:07.076 INFO 22436 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*]
2019-10-25 11:31:07.076 INFO 22436 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2019-10-25 11:31:07.076 INFO 22436 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2019-10-25 11:31:07.076 INFO 22436 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*]
2019-10-25 11:31:07.076 INFO 22436 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'webRequestLoggingFilter' to: [/*]
2019-10-25 11:31:07.076 INFO 22436 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'applicationContextIdFilter' to: [/*]
2019-10-25 11:31:07.779 INFO 22436 --- [ main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@138a7441: startup date [Fri Oct 25 11:31:05 CST 2019]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@41ab013
2019-10-25 11:31:07.857 INFO 22436 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/user/{id}],methods=[GET]}" onto public com.itmuch.cloud.microserviceconsumermovieribbon.entity.User com.itmuch.cloud.microserviceconsumermovieribbon.controller.MovieController.findById(java.lang.Long)
2019-10-25 11:31:07.857 INFO 22436 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/log-instance],methods=[GET]}" onto public void com.itmuch.cloud.microserviceconsumermovieribbon.controller.MovieController.logUserInstance()
2019-10-25 11:31:07.857 INFO 22436 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2019-10-25 11:31:07.857 INFO 22436 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
2019-10-25 11:31:07.904 INFO 22436 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2019-10-25 11:31:07.904 INFO 22436 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2019-10-25 11:31:07.935 INFO 22436 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2019-10-25 11:31:08.404 INFO 22436 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/env/{name:.*}],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EnvironmentMvcEndpoint.value(java.lang.String)
2019-10-25 11:31:08.404 INFO 22436 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/env || /env.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2019-10-25 11:31:08.404 INFO 22436 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/beans || /beans.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2019-10-25 11:31:08.404 INFO 22436 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/resume || /resume.json],methods=[POST]}" onto public java.lang.Object org.springframework.cloud.endpoint.GenericPostableMvcEndpoint.invoke()
2019-10-25 11:31:08.404 INFO 22436 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/configprops || /configprops.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2019-10-25 11:31:08.404 INFO 22436 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/refresh || /refresh.json],methods=[POST]}" onto public java.lang.Object org.springframework.cloud.endpoint.GenericPostableMvcEndpoint.invoke()
2019-10-25 11:31:08.404 INFO 22436 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/mappings || /mappings.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2019-10-25 11:31:08.404 INFO 22436 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/archaius || /archaius.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2019-10-25 11:31:08.404 INFO 22436 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/features || /features.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2019-10-25 11:31:08.404 INFO 22436 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/heapdump || /heapdump.json],methods=[GET],produces=[application/octet-stream]}" onto public void org.springframework.boot.actuate.endpoint.mvc.HeapdumpMvcEndpoint.invoke(boolean,javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws java.io.IOException,javax.servlet.ServletException
2019-10-25 11:31:08.419 INFO 22436 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/trace || /trace.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2019-10-25 11:31:08.419 INFO 22436 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/restart || /restart.json],methods=[POST]}" onto public java.lang.Object org.springframework.cloud.context.restart.RestartMvcEndpoint.invoke()
2019-10-25 11:31:08.419 INFO 22436 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/dump || /dump.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2019-10-25 11:31:08.419 INFO 22436 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/health || /health.json],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.HealthMvcEndpoint.invoke(java.security.Principal)
2019-10-25 11:31:08.419 INFO 22436 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/metrics/{name:.*}],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.MetricsMvcEndpoint.value(java.lang.String)
2019-10-25 11:31:08.419 INFO 22436 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/metrics || /metrics.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2019-10-25 11:31:08.419 INFO 22436 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/info || /info.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2019-10-25 11:31:08.419 INFO 22436 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/pause || /pause.json],methods=[POST]}" onto public java.lang.Object org.springframework.cloud.endpoint.GenericPostableMvcEndpoint.invoke()
2019-10-25 11:31:08.419 INFO 22436 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/autoconfig || /autoconfig.json],methods=[GET],produces=[application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
2019-10-25 11:31:08.419 INFO 22436 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/env],methods=[POST]}" onto public java.lang.Object org.springframework.cloud.context.environment.EnvironmentManagerMvcEndpoint.value(java.util.Map<java.lang.String, java.lang.String>)
2019-10-25 11:31:08.419 INFO 22436 --- [ main] o.s.b.a.e.mvc.EndpointHandlerMapping : Mapped "{[/env/reset],methods=[POST]}" onto public java.util.Map<java.lang.String, java.lang.Object> org.springframework.cloud.context.environment.EnvironmentManagerMvcEndpoint.reset()
2019-10-25 11:31:08.560 WARN 22436 --- [ main] c.n.c.sources.URLConfigurationSource : No URLs will be polled as dynamic configuration sources.
2019-10-25 11:31:08.560 INFO 22436 --- [ main] c.n.c.sources.URLConfigurationSource : To enable URLs as dynamic configuration sources, define System property archaius.configurationSource.additionalUrls or make config.properties available on classpath.
2019-10-25 11:31:08.560 WARN 22436 --- [ main] c.n.c.sources.URLConfigurationSource : No URLs will be polled as dynamic configuration sources.
2019-10-25 11:31:08.560 INFO 22436 --- [ main] c.n.c.sources.URLConfigurationSource : To enable URLs as dynamic configuration sources, define System property archaius.configurationSource.additionalUrls or make config.properties available on classpath.
2019-10-25 11:31:08.732 INFO 22436 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup
2019-10-25 11:31:08.747 INFO 22436 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Bean with name 'refreshScope' has been autodetected for JMX exposure
2019-10-25 11:31:08.747 INFO 22436 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Bean with name 'environmentManager' has been autodetected for JMX exposure
2019-10-25 11:31:08.747 INFO 22436 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Bean with name 'configurationPropertiesRebinder' has been autodetected for JMX exposure
2019-10-25 11:31:08.747 INFO 22436 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Bean with name 'refreshEndpoint' has been autodetected for JMX exposure
2019-10-25 11:31:08.747 INFO 22436 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Bean with name 'restartEndpoint' has been autodetected for JMX exposure
2019-10-25 11:31:08.747 INFO 22436 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Located managed bean 'environmentManager': registering with JMX server as MBean [org.springframework.cloud.context.environment:name=environmentManager,type=EnvironmentManager]
2019-10-25 11:31:08.763 INFO 22436 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Located managed bean 'restartEndpoint': registering with JMX server as MBean [org.springframework.cloud.context.restart:name=restartEndpoint,type=RestartEndpoint]
2019-10-25 11:31:08.763 INFO 22436 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Located managed bean 'refreshScope': registering with JMX server as MBean [org.springframework.cloud.context.scope.refresh:name=refreshScope,type=RefreshScope]
2019-10-25 11:31:08.779 INFO 22436 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Located managed bean 'configurationPropertiesRebinder': registering with JMX server as MBean [org.springframework.cloud.context.properties:name=configurationPropertiesRebinder,context=138a7441,type=ConfigurationPropertiesRebinder]
2019-10-25 11:31:08.794 INFO 22436 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Located managed bean 'refreshEndpoint': registering with JMX server as MBean [org.springframework.cloud.endpoint:name=refreshEndpoint,type=RefreshEndpoint]
2019-10-25 11:31:08.919 INFO 22436 --- [ main] o.s.c.support.DefaultLifecycleProcessor : Starting beans in phase 0
2019-10-25 11:31:08.935 INFO 22436 --- [ main] o.s.c.n.eureka.InstanceInfoFactory : Setting initial instance status as: STARTING
2019-10-25 11:31:09.357 INFO 22436 --- [ main] c.n.d.provider.DiscoveryJerseyProvider : Using JSON encoding codec LegacyJacksonJson
2019-10-25 11:31:09.357 INFO 22436 --- [ main] c.n.d.provider.DiscoveryJerseyProvider : Using JSON decoding codec LegacyJacksonJson
2019-10-25 11:31:09.435 INFO 22436 --- [ main] c.n.d.provider.DiscoveryJerseyProvider : Using XML encoding codec XStreamXml
2019-10-25 11:31:09.435 INFO 22436 --- [ main] c.n.d.provider.DiscoveryJerseyProvider : Using XML decoding codec XStreamXml
2019-10-25 11:31:09.638 INFO 22436 --- [ main] c.n.d.s.r.aws.ConfigClusterResolver : Resolving eureka endpoints via configuration
2019-10-25 11:31:09.732 INFO 22436 --- [ main] com.netflix.discovery.DiscoveryClient : Disable delta property : false
2019-10-25 11:31:09.732 INFO 22436 --- [ main] com.netflix.discovery.DiscoveryClient : Single vip registry refresh property : null
2019-10-25 11:31:09.732 INFO 22436 --- [ main] com.netflix.discovery.DiscoveryClient : Force full registry fetch : false
2019-10-25 11:31:09.732 INFO 22436 --- [ main] com.netflix.discovery.DiscoveryClient : Application is null : false
2019-10-25 11:31:09.732 INFO 22436 --- [ main] com.netflix.discovery.DiscoveryClient : Registered Applications size is zero : true
2019-10-25 11:31:09.732 INFO 22436 --- [ main] com.netflix.discovery.DiscoveryClient : Application version is -1: true
2019-10-25 11:31:09.732 INFO 22436 --- [ main] com.netflix.discovery.DiscoveryClient : Getting all instance registry info from the eureka server
2019-10-25 11:31:09.888 INFO 22436 --- [ main] com.netflix.discovery.DiscoveryClient : The response status is 200
2019-10-25 11:31:09.903 INFO 22436 --- [ main] com.netflix.discovery.DiscoveryClient : Starting heartbeat executor: renew interval is: 30
2019-10-25 11:31:09.903 INFO 22436 --- [ main] c.n.discovery.InstanceInfoReplicator : InstanceInfoReplicator onDemand update allowed rate per min is 4
2019-10-25 11:31:09.903 INFO 22436 --- [ main] com.netflix.discovery.DiscoveryClient : Discovery Client initialized at timestamp 1571974269903 with initial instances count: 3
2019-10-25 11:31:09.919 INFO 22436 --- [ main] c.n.e.EurekaDiscoveryClientConfiguration : Registering application microservice-consumer-movie with eureka with status UP
2019-10-25 11:31:09.919 INFO 22436 --- [ main] com.netflix.discovery.DiscoveryClient : Saw local status change event StatusChangeEvent [timestamp=1571974269919, current=UP, previous=STARTING]
2019-10-25 11:31:09.919 INFO 22436 --- [nfoReplicator-0] com.netflix.discovery.DiscoveryClient : DiscoveryClient_MICROSERVICE-CONSUMER-MOVIE/DESKTOP-3NP6QV0:microservice-consumer-movie:8010: registering service...
2019-10-25 11:31:09.966 INFO 22436 --- [nfoReplicator-0] com.netflix.discovery.DiscoveryClient : DiscoveryClient_MICROSERVICE-CONSUMER-MOVIE/DESKTOP-3NP6QV0:microservice-consumer-movie:8010 - registration status: 204
2019-10-25 11:31:10.013 INFO 22436 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8010 (http)
2019-10-25 11:31:10.013 INFO 22436 --- [ main] c.n.e.EurekaDiscoveryClientConfiguration : Updating port to 8010
2019-10-25 11:31:10.013 INFO 22436 --- [ main] croserviceConsumerMovieRibbonApplication : Started MicroserviceConsumerMovieRibbonApplication in 6.398 seconds (JVM running for 7.492)
2019-10-25 11:32:40.024 INFO 22436 --- [nio-8010-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring FrameworkServlet 'dispatcherServlet'
2019-10-25 11:32:40.024 INFO 22436 --- [nio-8010-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization started
2019-10-25 11:32:40.055 INFO 22436 --- [nio-8010-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization completed in 31 ms
2019-10-25 11:32:40.086 INFO 22436 --- [nio-8010-exec-1] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@ce5c0d6: startup date [Fri Oct 25 11:32:40 CST 2019]; parent: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@138a7441
2019-10-25 11:32:40.118 INFO 22436 --- [nio-8010-exec-1] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
2019-10-25 11:32:40.305 INFO 22436 --- [nio-8010-exec-1] c.netflix.config.ChainedDynamicProperty : Flipping property: microservice-provider-user.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647
2019-10-25 11:32:40.321 INFO 22436 --- [nio-8010-exec-1] c.n.u.concurrent.ShutdownEnabledTimer : Shutdown hook installed for: NFLoadBalancer-PingTimer-microservice-provider-user
2019-10-25 11:32:40.352 INFO 22436 --- [nio-8010-exec-1] c.netflix.loadbalancer.BaseLoadBalancer : Client:microservice-provider-user instantiated a LoadBalancer:DynamicServerListLoadBalancer:{NFLoadBalancer:name=microservice-provider-user,current list of Servers=[],Load balancer stats=Zone stats: {},Server stats: []}ServerList:null
2019-10-25 11:32:40.352 INFO 22436 --- [nio-8010-exec-1] c.n.l.DynamicServerListLoadBalancer : Using serverListUpdater PollingServerListUpdater
2019-10-25 11:32:40.383 INFO 22436 --- [nio-8010-exec-1] c.netflix.config.ChainedDynamicProperty : Flipping property: microservice-provider-user.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647
2019-10-25 11:32:40.383 INFO 22436 --- [nio-8010-exec-1] c.n.l.DynamicServerListLoadBalancer : DynamicServerListLoadBalancer for client microservice-provider-user initialized: DynamicServerListLoadBalancer:{NFLoadBalancer:name=microservice-provider-user,current list of Servers=[192.168.1.143:8000, 192.168.1.143:8001],Load balancer stats=Zone stats: {defaultzone=[Zone:defaultzone; Instance count:2; Active connections count: 0; Circuit breaker tripped count: 0; Active connections per server: 0.0;]
},Server stats: [[Server:192.168.1.143:8000; Zone:defaultZone; Total Requests:0; Successive connection failure:0; Total blackout seconds:0; Last connection made:Thu Jan 01 08:00:00 CST 1970; First connection made: Thu Jan 01 08:00:00 CST 1970; Active Connections:0; total failure count in last (1000) msecs:0; average resp time:0.0; 90 percentile resp time:0.0; 95 percentile resp time:0.0; min resp time:0.0; max resp time:0.0; stddev resp time:0.0]
, [Server:192.168.1.143:8001; Zone:defaultZone; Total Requests:0; Successive connection failure:0; Total blackout seconds:0; Last connection made:Thu Jan 01 08:00:00 CST 1970; First connection made: Thu Jan 01 08:00:00 CST 1970; Active Connections:0; total failure count in last (1000) msecs:0; average resp time:0.0; 90 percentile resp time:0.0; 95 percentile resp time:0.0; min resp time:0.0; max resp time:0.0; stddev resp time:0.0]
]}ServerList:org.springframework.cloud.netflix.ribbon.eureka.DomainExtractingServerList@14b71fb8
2019-10-25 11:32:40.477 INFO 22436 --- [nio-8010-exec-1] c.i.c.m.controller.MovieController : microservice-provider-user:192.168.1.143:8000
2019-10-25 11:32:41.368 INFO 22436 --- [erListUpdater-0] c.netflix.config.ChainedDynamicProperty : Flipping property: microservice-provider-user.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647
2019-10-25 11:32:41.789 INFO 22436 --- [nio-8010-exec-3] c.i.c.m.controller.MovieController : microservice-provider-user:192.168.1.143:8001
2019-10-25 11:32:41.977 INFO 22436 --- [nio-8010-exec-4] c.i.c.m.controller.MovieController : microservice-provider-user:192.168.1.143:8000
2019-10-25 11:32:42.164 INFO 22436 --- [nio-8010-exec-5] c.i.c.m.controller.MovieController : microservice-provider-user:192.168.1.143:8001
2019-10-25 11:32:42.320 INFO 22436 --- [nio-8010-exec-6] c.i.c.m.controller.MovieController : microservice-provider-user:192.168.1.143:8000
2019-10-25 11:32:42.492 INFO 22436 --- [nio-8010-exec-7] c.i.c.m.controller.MovieController : microservice-provider-user:192.168.1.143:8001
2019-10-25 11:32:42.664 INFO 22436 --- [nio-8010-exec-8] c.i.c.m.controller.MovieController : microservice-provider-user:192.168.1.143:8000
2019-10-25 11:32:42.836 INFO 22436 --- [nio-8010-exec-9] c.i.c.m.controller.MovieController : microservice-provider-user:192.168.1.143:8001
使用java代码自定义Ribbon配置
microservice-consumer-movie-ribbon项目
依赖
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.itmuch.cloud</groupId>
<artifactId>microservice-consumer-movie-ribbon</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>microservice-consumer-movie-ribbon</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<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>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<!--引入spring cloud依赖-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Camden.SR4</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>
yml
server:
port: 8010
spring:
application:
name: microservice-consumer-movie
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/,http://localhost:8762/eureka/,http://localhost:8763/eureka/
instance:
prefer-ip-address: true
启动类
package com.itmuch.cloud.microserviceconsumermovieribbon;
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;
@SpringBootApplication
@EnableDiscoveryClient
public class MicroserviceConsumerMovieRibbonApplication {
/**
* 实例化一个Bean并使用该方法的名字命名
* @return
*/
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(MicroserviceConsumerMovieRibbonApplication.class, args);
}
}
实体类
package com.itmuch.cloud.microserviceconsumermovieribbon.entity;
import java.math.BigDecimal;
public class User {
private Long id;
private String username;
private String name;
private Integer age;
private BigDecimal balance;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public BigDecimal getBalance() {
return balance;
}
public void setBalance(BigDecimal balance) {
this.balance = balance;
}
}
controller
package com.itmuch.cloud.microserviceconsumermovieribbon.controller;
import com.itmuch.cloud.microserviceconsumermovieribbon.entity.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class MovieController {
@Autowired
private RestTemplate restTemplate;
@Autowired
private LoadBalancerClient loadBalancerClient;
private static final Logger logger = LoggerFactory.getLogger(MovieController.class);
/**
* microservice-provider-user:虚拟主机名
* @param id
* @return
*/
@GetMapping("/user/{id}")
public User findById(@PathVariable Long id){
return this.restTemplate.getForObject("http://microservice-provider-user/" + id,User.class);
}
@GetMapping("/log-instance")
public void logUserInstance(){
ServiceInstance serviceInstance = this.loadBalancerClient.choose("microservice-provider-user");
//打印当前选择的那个节点
MovieController.logger.info("{}:{}:{}",serviceInstance.getServiceId(),serviceInstance.getHost(),serviceInstance.getPort());
}
}
复制项目microservice-consumer-movie-ribbon,将ArtifactId修改为microservice-consumer-movie-ribbon-customizing
创建Ribbon的配置类
package com.itmuch.cloud.microserviceconsumermovieribboncustomizing.config;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RibbonConfiguration {
/**
* BeanType是IRule
* beanName是ribbonRule
* ClassName是ZoneAvoidanceRule
* @return
*/
@Bean
public IRule ribbonRule(){
//负载均衡规则,改为随机
return new RandomRule();
}
}
创建一个空类,并在其添加上@Configuration注解和@RibbonClient注解
package com.itmuch.cloud.microserviceconsumermovieribboncustomizing.config;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.context.annotation.Configuration;
/**
* 使用@RibbonClient,为特定name的Ribbon Client自定义配置
* 使用@RibbonClient的configuration属性,指定Ribbon的配置类
*/
@Configuration
@RibbonClient(name = "microservice-provider-user",configuration = RibbonConfiguration.class)
public class TestConfiguration {
}
启动测试
使用属性自定义Ribbon配置
复制项目microservice-consumer-movie-ribbon,将ArtifactId修改为microservice-consumer-movie-ribbon-customizing-properties
只需要在yml中添加如下即可
microservice-provider-user:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
测试结果
脱离Eureka使用Ribbon
Ribbon支持脱离Eureka使用,架构图如下
复制项目microservice-consumer-movie-ribbon,将ArtifactId修改为microservice-consumer-movie-ribbon-wirhout-eureka
我们去掉Eureka的依赖spring-cloud-starter-eureka,只使用Ribbon的依赖spring-cloud-starter-ribbon
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
去掉启动类上的@EnableDiscoveryClient注解
将application.yml改成如下
server:
port: 8010
spring:
application:
name: microservice-consumer-movie
microservice-provider-user:
ribbon:
listOfServers: localhost:8000,localhost:8001
2019-10-25 14:21:40.638 INFO 9160 --- [nio-8010-exec-1] c.i.c.m.controller.MovieController : microservice-provider-user:localhost:8000
2019-10-25 14:21:41.279 INFO 9160 --- [erListUpdater-0] c.netflix.config.ChainedDynamicProperty : Flipping property: microservice-provider-user.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647
2019-10-25 14:21:41.825 INFO 9160 --- [nio-8010-exec-2] c.i.c.m.controller.MovieController : microservice-provider-user:localhost:8001
2019-10-25 14:21:42.967 INFO 9160 --- [nio-8010-exec-3] c.i.c.m.controller.MovieController : microservice-provider-user:localhost:8000
2019-10-25 14:21:43.655 INFO 9160 --- [nio-8010-exec-4] c.i.c.m.controller.MovieController : microservice-provider-user:localhost:8001
2019-10-25 14:21:43.858 INFO 9160 --- [nio-8010-exec-5] c.i.c.m.controller.MovieController : microservice-provider-user:localhost:8000
2019-10-25 14:21:44.030 INFO 9160 --- [nio-8010-exec-6] c.i.c.m.controller.MovieController : microservice-provider-user:localhost:8001
2019-10-25 14:21:44.201 INFO 9160 --- [nio-8010-exec-7] c.i.c.m.controller.MovieController : microservice-provider-user:localhost:8000
2019-10-25 14:21:44.389 INFO 9160 --- [nio-8010-exec-8] c.i.c.m.controller.MovieController : microservice-provider-user:localhost:8001
2019-10-25 14:21:44.686 INFO 9160 --- [nio-8010-exec-9] c.i.c.m.controller.MovieController : microservice-provider-user:localhost:8000
2019-10-25 14:21:44.873 INFO 9160 --- [io-8010-exec-10] c.i.c.m.controller.MovieController : microservice-provider-user:localhost:8001
2019-10-25 14:21:45.045 INFO 9160 --- [nio-8010-exec-1] c.i.c.m.controller.MovieController : microservice-provider-user:localhost:8000