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的专栏-CSDN博客