1.服务治理-Ribbon-给消费者添加负载均衡功能
2020-05-02 本文已影响0人
溅十三
image.png
1.创建项目ribbon-consumer
2.添加pom依赖eureka、ribbon、boot
<?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">
<parent>
<artifactId>spring-cloud-demo</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<name>ribbon-consumer</name>
<artifactId>ribbon-consumer</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<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>
</dependencies>
</project>
4.创建启动类
ribbon的精华在哪里?
package com.imooc.springcloud;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
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 RibbonConsumerApplication {
// 精华所在
@Bean
@LoadBalanced
public RestTemplate template() {
return new RestTemplate();
}
public static void main(String[] args) {
new SpringApplicationBuilder(RibbonConsumerApplication.class)
.web(WebApplicationType.SERVLET)
.run(args);
}
}
5.创建Controller
没有引入Ribbon前如何使用RestTemplate来发送请求?
- RestTemplate
- LoadBalancerClient
- client.choose("eureka-client")
启动类:
package com.imooc.springcloud;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableDiscoveryClient
public class EurekaConsumerApplication {
/*
* @Bean注解,spring会在初始化的时候会把这个方法加入到上下文,然后我们就可以在Controller里得到这个方法了
* */
@Bean
public RestTemplate register(){
return new RestTemplate();
}
public static void main(String[] args) {
new SpringApplicationBuilder(EurekaConsumerApplication.class)
.web(WebApplicationType.SERVLET)
.run(args);
}
}
controller:
package com.imooc.springcloud;
import lombok.extern.slf4j.Slf4j;
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.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@Slf4j
@RestController
public class Controller {
/*
* 负载均衡器,帮我们从注册中心拉取的服务列表中挑选一个可用的serviceprovider
* */
@Autowired
private LoadBalancerClient client;
@Autowired
private RestTemplate restTemplate;
@GetMapping("/hello")
public String hello(){
/*
* 1.拿到服务提供者的实例
* 2.借助RestTemplate发起真实的服务调用
* 3.单独声明RestTemplate
* */
ServiceInstance instance = client.choose("eureka-client");
/*
* 防疫性编程:假定所有的输入都是不安全的,instance可能get到空
* */
if (instance == null) {
return "No aviliable instance";
}
String target = String.format("http://%s:%s/sayHi",instance.getHost(),instance.getPort());
log.info("url is {}",target);
return restTemplate.getForObject(target, String.class);
}
@PostMapping("/hello")
public Friend helloPost(){
/*
* 1.拿到服务提供者的实例
* 2.借助RestTemplate发起真实的服务调用
* 3.单独声明RestTemplate
* 4.启动顺序:启动注册中心->服务提供者->服务消费者
* */
ServiceInstance instance = client.choose("eureka-client");
/*
* 防疫性编程:假定所有的输入都是不安全的,instance可能get到空
* */
if (instance == null) {
return null;
}
String target = String.format("http://%s:%s/sayHi",instance.getHost(),instance.getPort());
log.info("url is {}",target);
Friend friend = new Friend();
friend.setName("eureka-consumer");
return restTemplate.postForObject(target, friend,Friend.class);
}
}
引入Ribbon如何使用RestTemplate来发送请求?
启动类:
package com.imooc.springcloud;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
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 RibbonConsumerApplication {
// 精华所在
@Bean
@LoadBalanced
public RestTemplate template() {
return new RestTemplate();
}
public static void main(String[] args) {
new SpringApplicationBuilder(RibbonConsumerApplication.class)
.web(WebApplicationType.SERVLET)
.run(args);
}
}
controller:
package com.imooc.springcloud;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class Controller {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/sayHi")
public String sayHi() {
return restTemplate.getForObject(
"http://eureka-client/sayHi",
String.class);
}
}
5.Ribbon application.properties的书写步骤?
1.name
2.port
3.serviceUrl
6.要做几件事情?
1.启动eureka-server
2.启动2个eureka-client
3.启动ribbon-consumer
4.看3个服务是否都在注册中心上
5.调用ribbon-consumer方法(或调用eureka-server的eureka-client方法?),看会不会轮训调用eureka-client,看ribbon服务负载均衡是否生效了
6.遇到哪些问题?
负载均衡没有起到作用
原因:2个eureka-client的name名称不一致导致的
eureka-server报连接超时错误:
解决:pom加eureka.client.serviceUrl.defaultZone=http://localhost:20000/eureka/