文章目录
负载均衡
动态扩缩容:Docker、Rancher、K8S
负载均衡就是将负载(请求)分摊到各个服务应用上执行。
根据服务均衡发生位置不同,可以分为:服务端负载均衡和客户端负载均衡。
- 服务端负载均衡:Nginx
- 客户端负载均衡:Nacos、Feign、Ribbon
Ribbon负载均衡组件
SpringCloud默认整合Ribbon负载均衡。
案例代码 启用负载均衡@LoadBalanced
// 给启动类上的restTemplate添加注解
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
@Autowired
private RestTemplate restTemplate;
// 在代码中请求使用
@Override
public String testRibbon() {
String uri = "http://cloud2-product-server/";
return restTemplate.getForObject(uri, String.class);
}
Ribbon负载均衡策略
可以通过配置修改负载均衡算法
cloud2-product-server:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
Feign(HttpClient)
SpringCloud提供的一个声明式Http客户端。使得远程调用像调用本地服务一样见到那,只需要创建接口并添加注解即可。
Nacos很好的兼容了Feign,Feign默认集成了Ribbon。所以在Nacos下使用Feign则默认实现了负载均衡。
案例代码(注意参数列表、接口需要保持一致)
引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
注解启用Feign@EnableFeignClients
@SpringBootApplication
@RestController
@EnableDiscoveryClient // 当前服务是nacos客户端
@EnableFeignClients
public class Cloud2OrderApp {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(Cloud2OrderApp.class, args);
}
@RequestMapping("/")
public String index() {
return "Cloud2OrderApp";
}
}
编写测试代码
@Service
@FeignClient("cloud2-product-server")
public interface ProductService {
@GetMapping("/")
String index();
}
@Autowired
private ProductService productService;
@RequestMapping("/ribbon")
public String ribbon() {
// return orderService.testRibbon();
return productService.index();
}
原理分析
- 远程接口调用需要的前提条件?
- ip、端口、接口uri、参数、返回值
- 大致逻辑
- 项目启动时,扫描所有带有@FeignClient注解的接口类并解析
- 解析Feign接口中配置的服务名称,结合注册中心服务清单可以获得远程接口(IP/port)
- 解析Feign接口中定义的方法,可以得到远程接口的url、参数、返回值
- 当获取到ip、端口、接口uri、参数、返回值这些参数,完全可以发起远程调用。
常见异常与注意要点:
Load balancer does not have available server for client:xxxx-service
- @FeignClient中的name必须为服务提供者在nacos上注册的服务名称,否则报错
feign.FeignExceptionSNotFound: [404] during [GET] to [http://xxx-service/xxx]
- @GetMapping(“/product/{pid}”)指定接口路径,必须与生产者保持一致,否则报错
- 定义接口参数:如果使用了参数路径访问方式,需要使用@PathVariable注解来指定
- 定义接口参数:如果使用普通方式访问,参数需要使用@RequestParam注解来指定
- 参数无法获取问题
- 定义接口参数:如果是对象参数,参数需要使用@RequestBody注解来指定(Feign和Controller都需要)
- 定义接口参数:如果是对象可以使用@SpringQueryMap替换@RequestBody
- 定义接口参数:如果需要进行文件上传需要@RequestPart注解来指定
- Feign接口默认连接时间为1s。可以通过配置来指定连接时间
feign:
client:
config:
default:
connectTimeout: 5000 # 连接超时时间
readTimeout: 5000 # 操作时间