上一节中,article服务调用user微服务,我们发现,每次请求,都是由不同的user微服务提供的。其实这是由于SpringCloud默认指定了Ribbon组件来提供的负载均衡策略。而Ribbon默认的负载均衡策略是轮询,因此我们在连续刷新页面时,user服务依次来提供服务。
在article服务运行的时候,我们可以仔细观察一下,有下面一段输出:
You already have RibbonLoadBalancerClient on your classpath. It will be used by default. As Spring Cloud Ribbon is in maintenance mode. We recommend switching to BlockingLoadBalancerClient instead. In order to use it, set the value of spring.cloud.loadbalancer.ribbon.enabled to false or remove spring-cloud-starter-netflix-ribbon from your project.
spring.cloud.loadbalancer.ribbon.enabled=false
运行顺序:
从实际测试看,即使我们设置了禁用ribbon,EurekaClient仍然有自己的负载均衡策略(轮询)。
负载均衡建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽、增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性。
负载均衡(Load Balance)其意思就是分摊到多个操作单元上进行执行,例如Web服务器、FTP服务器、企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务。
nginx可以使用负载均衡分配流量
#自定义配置负载均衡策略
server1.ribbon.NFLoadBalancerRuleClassName= com.netflix.loadbalancer.RandomRule
server2.ribbon.NFLoadBalancerRuleClassName= com.netflix.loadbalancer.RoundRobinRule
## application.properties
spring.application.name=server-blog-good
server.port=8900
# eureka client
eureka.client.service-url.defaultZone=http://localhost:6060/eureka/
eureka.instance.prefer-ip-address=true
package com.mazong.serverbloggood.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.HashMap;
import java.util.Map;
@Controller
public class GoodController {
@RequestMapping(value = "/getGood")
@ResponseBody
public Object getGood(@RequestParam("id") Integer id) {
Map<String, Object> resultMap = new HashMap<>();
resultMap.put("welcome", "hello,i am good service");
return resultMap;
}
}
<!-- 引入TbUser类的包 -->
<dependency>
<groupId>com.mazong</groupId>
<artifactId>server-blog-user</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
package com.mazong.serverbloggood;
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 ServerBlogGoodApplication {
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(ServerBlogGoodApplication.class, args);
}
}
package com.mazong.serverbloggood.controller;
import com.mazong.serverbloguser.entity.TbUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;
import java.util.HashMap;
import java.util.Map;
@Controller
public class GoodController {
@Autowired
RestTemplate restTemplate;
@Autowired
LoadBalancerClient loadBalancerClient;
@RequestMapping(value = "/getGood")
@ResponseBody
public Object getGood(@RequestParam("id") Integer id) {
// http://localhost:8900/getGood?id=1
Map<String, Object> resultMap = new HashMap<>();
resultMap.put("welcome", "hello,i am good service");
ServiceInstance serviceInstance = loadBalancerClient.choose("server-blog-user");
String url = "http://" + serviceInstance.getHost() + ":" + serviceInstance.getPort() + "/getUser?id=" + id;
System.out.println(url);
TbUser user = restTemplate.getForObject(url, TbUser.class);
resultMap.put("user", user);
return resultMap;
}
}