(三)Spring Cloud Ribbon 实现服务访问的负载均衡
本章将讲解通过Ribbon实现负载均衡去访问多台Eureka Client中的服务
本项目是一个独立的maven项目,其中的多个module。
Eureka-Server,Eureka-Client ,Eureka-Ribbon_Client模块,其中Eureka-Client后续会以2个端口启动,并分别在Eureka-Server注册
1. 新建一个maven项目eureka-ribbon
2. 新建一个eureka-server
具体配置和上一篇类似
2.1 pom文件
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</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> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-sleuth</artifactId> </dependency>
2.2 启动类
package com.devin.eurekaserver; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @EnableEurekaServer @SpringBootApplication public class EurekaServerApplication { public static void main(String[] args) { SpringApplication.run(EurekaServerApplication.class, args); } }
2.3 安全校验
package com.devin.eurekaserver.config; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { //关闭csrf super.configure(http); //开启认证 http.csrf().disable(); } }
2.4 application.yml配置文件
eureka-server的启动端口为 7001
server:
port: 7001 #启动端口
spring:
#应用名称
application:
name: eureka-server
#安全配置
security:
basic:
enabled: true
user:
name: dev
password: 123456
#eureka配置
eureka:
server:
#设置扫描失效服务的间隔时间
eviction-interval-timer-in-ms: 20000
enable-self-preservation: true
instance:
hostname: localhost
leaseRenewalIntervalInSeconds: 10
health-check-url-path: /actuator/health
client:
register-with-eureka: false #false:不作为一个客户端注册到注册中心
fetch-registry: false #为true时,可以启动,但报异常:Cannot execute request on any known server
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
# health endpoint是否必须显示全部细节。默认情况下, /actuator/health 是公开的,并且不显示细节。
# 设置actuator开关
management:
security:
enabled: false
endpoints:
web:
exposure:
include: "*"
endpoint:
health:
show-details: ALWAYS
3. 创建eureka-client
eureka client后续将启动两个端口7002,7003,并分别在eureka-server注册
3.1 pom文件
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.1.8.RELEASE</version> </dependency>
3.2 启动类
package com.devin.eurekaclient; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @EnableEurekaClient @SpringBootApplication public class EurekaClientApplication { public static void main(String[] args) { SpringApplication.run(EurekaClientApplication.class, args); } }
3.3 新建一个Controller类,该类打印出eureka-client的启动端口
package com.devin.eurekaclient.controller; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; /** * @author Devin Zhang * @className HelloController * @description TODO * @date 2020/3/28 10:45 */ @RestController public class HelloController { @Value("${server.port}") private Integer port; @GetMapping("/sayHello") public String sayHello(String name) { return "Hello ," + name + " ,this response is from eureka client port:" + port; } }
3.4 application.yml 配置文件
eureka:
auth:
user: dev
password: 123456
client:
serviceUrl:
defaultZone: http://${eureka.auth.user}:${eureka.auth.password}@localhost:7001/eureka/
instance:
#使用IP进行注册
prefer-ip-address: true
#配置实例的注册ID
instance-id: ${spring.cloud.client.ip-address}:${server.port}
#心跳时间,即服务续约间隔时间(缺省为30s)
lease-renewal-interval-in-seconds: 5
#发呆时间,即服务续约到期时间(缺省为90s)
lease-expiration-duration-in-seconds: 10
health-check-url-path: /actuator/health
server:
port: 7002
spring:
application:
name: eureka-client
启动eureka-client,分别在两个端口启动,这两个eureka-client实例将分别向 7001 eureka-server进行注册
java -jar eureka-client-0.0.1-SNAPSHOT.jar --server.port=7002
java -jar eureka-client-0.0.1-SNAPSHOT.jar --server.port=7003
4. eureka-client-ribbon
该服务将做为一个eureka-client进行注册,并通过RestTemplate对eureka-client进行负载均衡访问
4.1 pom.xml
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.1.8.RELEASE</version> </dependency>
4.2 启动类
package com.devin.eurekaribbonclient; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @EnableEurekaClient @SpringBootApplication public class EurekaRibbonClientApplication { public static void main(String[] args) { SpringApplication.run(EurekaRibbonClientApplication.class, args); } }
4.3 RestTemplate 配置类,支持负载均衡
package com.devin.eurekaribbonclient.config; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; /** * @author Devin Zhang * @className RibbonConfig * @description TODO * @date 2020/3/28 11:51 */ @Configuration public class RibbonConfig { @Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); } }
4.4 新建Service类,通过RestTemplate,负载均衡调用eureka-client的接口
package com.devin.eurekaribbonclient.service; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import javax.annotation.Resource; /** * @author Devin Zhang * @className RibbonHelloService * @description TODO * @date 2020/3/28 11:54 */ @Service public class RibbonHelloService { @Resource private RestTemplate restTemplate; public String sayHello(String name) { return restTemplate.getForObject("http://EUREKA-CLIENT/sayHello?name=" + name, String.class); } }
4.5 Controller入口类,用于测试
package com.devin.eurekaribbonclient.controller; import com.devin.eurekaribbonclient.service.RibbonHelloService; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; /** * @author Devin Zhang * @className RibbonHelloController * @description TODO * @date 2020/3/28 11:57 */ @RestController public class RibbonHelloController { @Resource private RibbonHelloService ribbonHelloService; @GetMapping("/sayHelloFromRibbon") public String sayHello(String name) { return ribbonHelloService.sayHello(name); } }
4.6 application.yml 配置文件
eureka:
auth:
user: dev
password: 123456
client:
serviceUrl:
defaultZone: http://${eureka.auth.user}:${eureka.auth.password}@localhost:7001/eureka/
instance:
#使用IP进行注册
prefer-ip-address: true
#配置实例的注册ID
instance-id: ${spring.cloud.client.ip-address}:${server.port}
#心跳时间,即服务续约间隔时间(缺省为30s)
lease-renewal-interval-in-seconds: 5
#发呆时间,即服务续约到期时间(缺省为90s)
lease-expiration-duration-in-seconds: 10
health-check-url-path: /actuator/health
server:
port: 7004
spring:
application:
name: eureka-ribbon-client
5. 测试结果
分别启动
eureka-server 7001
eureka-client 7002
eureka-client 7003
eureka-ribbon-client 7004
在注册中心http://localhost:7001可以看到,各个客户端已经进行了注册
验证负载均衡,访问 http://localhost:7004/sayHelloFromRibbon?name=devin ,可以看到对eureka-client的访问,会负载均衡到 7002,7003 对应的实例