在之前进行微服务的调用用的是ribbon+RestTemplate,就像这样:
private static final String url="http://EUREKA-PROVIDER";
@Autowired
RestTemplate restTemplate;
@RequestMapping("get")
@ResponseBody
public List<User> all(){
List list = restTemplate.getForObject(url + "/user/get", List.class);
log.info("UserControllerComsumer-->{}",list);
return list;
}
这样调用微服务是更偏向面向restFull风格,但偏离了面向接口编程
使用openFeign,openFeign底层还是用的ribbon。
使用步骤
添加openFeign依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
openFeign已包含了ribbon
在启动类上添加@EnableFeignClients注解表示使用feign
@EnableAutoConfiguration
@Configuration
@ComponentScan(basePackages = "com")
@EnableDiscoveryClient
@EnableEurekaClient
@EnableFeignClients
@RibbonClient(name = "EUREKA-PROVIDER",configuration = IruleConfiguration.class)
public class SpringCloudConsumer {
public static void main(String[] args) {
SpringApplication.run(SpringCloudConsumer.class,args);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
在消费者中编写一个调用微服务的接口,接口上使用@FeignClient注解,方法上使用@…Mapping注解
//@Component
@FeignClient(name = "EUREKA-PROVIDER")
public interface UserService {
@RequestMapping("/user/feign/{id}")
User id(@PathVariable("id") Integer id);
@GetMapping("/user/testRibbon")
String port();
}
向Eureka中注入两个服务提供者
下面是服务提供者提供的api接口,两个提供者的代码相同
@RestController
@RequestMapping("user")
public class UserControllerProvider {
@Autowired
UserService userService;
@Value("${server.port}")
private String port;
@RequestMapping("testRibbon")
public String testRibbon(){
return port;
}
@RequestMapping("feign/{id}")
public User id(@PathVariable("id") Integer id){
return userService.findById(id);
}
}
消费者的api接口
@RestController
@RequestMapping("user")
@Slf4j
public class UserControllerComsumer {
@Autowired
UserService userService;
@RequestMapping("feign/{id}")
public User byId(@PathVariable("id") Integer id){
return userService.id(id);
}
@GetMapping("port")
public String port(){
return userService.port();
}
}
浏览器中进行测试
超时问题
当消费者调用提供者的代码如果出现网络等问题可能会出现长时间调用等待问题,ribbo默认的调用时间是1秒
在提供者的代码中添加耗时代码
@RequestMapping("testRibbon")
public String testRibbon(){
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return port;
}
再测试消费者接口就会报错
修改默认的超时时间的两种方式
1、再消费者端的application文件中添加
ribbon:
#连接超时时间
ConnectTimeout: 4000
#调用超时时间
ReadTimeout: 4000
2、添加
feign:
client:
config:
default:
connectTimeout: 2000
readTimeout: 4000
如果同时设置这两种,那么ribbon优先级大于feign
日志功能
在消费端创建一个feign日志配置类
@Configuration
public class FeignLogConfiguration {
@Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
}
在配置文件中设置日志级别
logging:
level:
com.tao.controller: debug
这样在进行服务调用时技能查看相关日志
负载均衡
因为底层还是使用ribbon,所以还是使用ribbon的负载均衡方式
1、配置文件方式
EUREKA-PROVIDER:
ribbon:
RoundRobinRule:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
2、配置类+注解
在主配置类不能扫描的包中创建一个配置类
@Configuration
public class IruleConfiguration {
@Bean
IRule myRule(){
return new RandomRule();
}
}
在主启动类上添加注解RibbonClient
name :服务名称,
IruleConfiguration:自定义配置负载均衡策略类
@RibbonClient(name = "EUREKA-PROVIDER",configuration = IruleConfiguration.class)
public class SpringCloudConsumer {
public static void main(String[] args) {
SpringApplication.run(SpringCloudConsumer.class,args);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}