springcloud是使用rest协议(RestTemplate)进行信息传递,同时在netfix的项目中实现了一个feign组件来简化编写代码的麻烦,并且有自动负载均衡
调用的原理:
通过动态代理,产生了一个代理类交给了spring容器。然后通过反射获取接口的注解以及里面的配置,获取路径,获取参数名,参数值,获取返回的类型。然后封装到RestTemolate中,然后模拟浏览器请求。
简单使用:
1,加入起步依赖,在调用者模块中加入
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2,启动类添加@EnableFeignClients注解
@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker//开启熔断机制
@EnableFeignClients//
public class UserConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(UserConsumerApplication.class,args);
}
/* @Bean
@LoadBalanced //启动负载均衡
public RestTemplate restTemplate(){
return new RestTemplate();
}*/
}
3,创建一个接口,接口里面的方法名,参数名,以及返回值要和controller类一致
package org.example.feign;
import org.example.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
//声明feign组件,name是指定服务名,
//@FeignClient(name = "${feign.name}", url = "${feign.url}")
@FeignClient(name = "user-provider")
public interface UserFeign {
@GetMapping("/user/{id}")
public User findById(@PathVariable(name = "id") Integer id);
}
4,controller类,直接注入接口,然后调用接口的方法即可
package org.example.controller;
import org.example.feign.UserFeign;
import org.example.pojo.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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/feign")
public class TestFeignController {
@Autowired
private UserFeign userFeign;
@GetMapping("/{id}")
public User findByid(@PathVariable(name = "id") Integer id){
//接受浏览器请求
//调用feign
User user = userFeign.findById(id);
return user;
}
}
负载均衡配置
1,通过Ribbon来配置
# 修改服务地址轮询策略,默认是轮询,配置之后变随机
# WeightedResponseTimeRule 根据服务响应时间权重值策略
# RoundRobinRule 轮询策略
# RandomRule 随机策略
# Zone Avoidance Rule 区域避免规则。
# 配置负载均衡
user-provider:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #默认是轮询,配置为随机
ConnectTimeout: 1000 # 连接超时时间
ReadTimeout: 2000 # 数据读取超时时间,连接之后,数据传输过程
MaxAutoRetries: 0 # 最大重试次数(第一个服务)
MaxAutoRetriesNextServer: 0 # 最大重试下一个服务次数(集群的情况才会用到)
OkToRetryOnAllOperations: false # 是否对所有的请求都重试
2,或者通过fegin来配置
feign:
client:
config:
feignName:
connectTimeout: 5000
readTimeout: 5000
loggerLevel: full
errorDecoder: com.example.SimpleErrorDecoder
retryer: com.example.SimpleRetryer
defaultQueryParameters:
query: queryValue
defaultRequestHeaders:
header: headerValue
requestInterceptors:
- com.example.FooRequestInterceptor
- com.example.BarRequestInterceptor
decode404: false
encoder: com.example.SimpleEncoder
decoder: com.example.SimpleDecoder
contract: com.example.SimpleContract
熔断器支持(默认没有开启)
# To disable Hystrix in Feign
feign:
hystrix:
enabled: true
使用:
创建一个对应的Feign类的实现类
package org.example.feign.impl;
import org.example.feign.UserFeign;
import org.example.pojo.User;
@Component
public class UserFeignImpl implements UserFeign {
//降级方法
@Override
public User findById(Integer id) {
User user = new User();
user.setId(0);
user.setUsername("默认名称");
return user;
}
}
然后在@FeignClient注解加上一个参数fallback
package org.example.feign;
import org.example.feign.impl.UserFeignImpl;
import org.example.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
//声明feign组件,name是指定服务名,
//@FeignClient(name = "${feign.name}", url = "${feign.url}")
@FeignClient(name = "user-provider",fallback = UserFeignImpl.class)
public interface UserFeign {
@GetMapping("/user/{id}")
public User findById(@PathVariable(name = "id") Integer id);
}
注意项:
如果你需要使用Hystrix那么就不要把@RequestMapping注解写到类上,因为实现类实现了接口,而@RequestMapping加在接口上,那么实现类也会生成两个动态代理类和一个同样的路径,导致url路径不唯一,所以会报错
解决方法:
1,直接不在类上加@RequestMapping注解
2,或者在@FeignClient加入一个参数:path即可
package org.example.feign;
import org.example.feign.impl.UserFeignImpl;
import org.example.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
//声明feign组件,name是指定服务名,
//@FeignClient(name = "${feign.name}", url = "${feign.url}")
@FeignClient(name = "user-provider",fallback = UserFeignImpl.class,path="/user")
public interface UserFeign {
@GetMapping("/{id}")
public User findById(@PathVariable(name = "id") Integer id);
}
另外还可以了解一下请求压缩,和日志级别配置
(15条消息) SpringCloud Feign 优化_xjune的专栏-****博客