本文章是在 负载均衡和容错机制 实现 可参考
虽然使用了负载均衡(Ribbon)和容错机制(Hystrix)可以实现负载均衡和容错处理,但是这个编码在实现大量业务时会显得太过于冗余(如,多参数的URL拼接)
一 :首先导入依赖
<!--springboot 整合fegnin客户端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
二:创建一个ItemFeignClient 接口
package com.mr.feign;
/**
* Created by Admin on 2019/3/18.
*/
import com.mr.model.Item;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
/**
* 申明这是一个Feign客户端,并且指明服务id
* @author Evan
*/
@FeignClient(value = "app-item")
public interface ItemFeignClient {
/**
* 这里定义了类似于SpringMVC用法的方法,就可以进行RESTful方式的调用了
*
* @param id
* @return
*/
@RequestMapping(value = "/item/{id}", method = RequestMethod.GET) //itme/{id} 调用服务端的方法
Item queryItemById(@PathVariable("id") Long id);
}
在客户端 调用服务端的方法 这样写
/**
* 请求失败执行的方法
* fallbackMethod的方法参数个数类型要和原方法一致
*
* @param id
* @return
*/
public Item queryItemByIdFallbackMethod(Long id) {
return new Item(id, "查询商品信息出错!", null, null, null);
}
@Autowired
private ItemFeignClient itemFeignClient;
@HystrixCommand(fallbackMethod = "queryItemByIdFallbackMethod")
public Item queryItemById(Long id) {
String itemUrl = "http://app-item/item/{id}";
Item result = itemFeignClient.queryItemById(id);
System.out.println("===========HystrixCommand queryItemById-线程池名称:" + Thread.currentThread().getName() + "订单系统调用商品服务,result:" + result);
return result;
}
之前容错机制 是这样写的:
// Spring框架对RESTful方式的http请求做了封装,来简化操作
@Autowired
private RestTemplate restTemplate;
/* @Value("${myspcloud.item.url}")
private String itemUrl;
*/
@Autowired
OrderProperties orderProperties;
//容错机制 方法
/* @HystrixCommand(fallbackMethod = "queryItemByIdFallbackMethod")
public Item queryItemById(Long id) {
/* 该方法走eureka注册中心调用(去注册中心根据app-item查找服务,这种方式必须先开启负载均衡@LoadBalanced) */
String itemUrl = "http://app-item/item/{id}";
Item result = restTemplate.getForObject(itemUrl, Item.class, id);
System.out.println("订单系统调用商品服务,result:" + result);
return result;
}*/
/**
* 请求失败执行的方法
* fallbackMethod的方法参数个数类型要和原方法一致
*
* @param id
* @return
*/
public Item queryItemByIdFallbackMethod(Long id) {
return new Item(id, "查询商品信息出错!", null, null, null);
}
在启动类中添加 @EnableFeignClients 注解
package com.mr;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.http.client.OkHttp3ClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@ComponentScan(basePackages = {"com.mr.controller", "com.mr.service","com.mr.properties","com.mr.feign"})//手动指定bean扫描范围
@EnableEurekaClient
@EnableHystrix
@EnableFeignClients(basePackages ="com.mr.feign") //feign 包名
public class CloudorderApplication {
public static void main(String[] args) {
SpringApplication.run(CloudorderApplication.class, args);
}
/**
* 向Spring容器中定义RestTemplate对象
* @return
*/
@Bean
@LoadBalanced
/*在使用springcloud ribbon客户端负载均衡的时候,可以给RestTemplate bean
加一个@LoadBalanced注解,就能让这个RestTemplate在请求时拥有客户端负载均衡的能力:*/
public RestTemplate restTemplate() {
return new RestTemplate(new OkHttp3ClientHttpRequestFactory());
}
}
就不上图了 效果和 容错机制的效果一样
@Autowired
private ItemFeignClient itemFeignClient;
@HystrixCommand(fallbackMethod = "queryItemByIdFallbackMethod")
public Item queryItemById(Long id) {
String itemUrl = "http://app-item/item/{id}";
Item result = itemFeignClient.queryItemById(id);
System.out.println("===========HystrixCommand queryItemById-线程池名称:" + Thread.currentThread().getName() + "订单系统调用商品服务,result:" + result);
return result;
}
执行过程分析:
1、由于我们在入口程序使用了@EnableFeignClients注解,Spring启动后会扫描标注了@FeignClient注解的接口,然后生成代理类。
2、我们在@FeignClient接口中指定了value,其实就是指定了在Eureka中的服务名称。
3、在FeignClient中的定义方法以及使用了SpringMVC的注解,Feign就会根据注解中的内容生成对应的URL,然后基于Ribbon的负载均衡去调用REST服务。
为什么使用的是SpringMVC的注解?
i.其实,Feign是有自己的注解的@RequestLine,是因为Spring Cloud对Feign做了增强,兼容了SpringMVC的注解,使我们的学习成本更低
设置统一的hystrix fallback接口**
一般在实际开发中fallback 方法不会直接写在接口方法所在类里,那样太杂乱 所以改进一下
一:在接口中添加fallback 属性
package com.mr.feign;
/**
* Created by Admin on 2019/3/18.
*/
import com.mr.model.Item;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
/**
* 申明这是一个Feign客户端,并且指明服务id
* @author Evan
*/
@FeignClient(value = "app-item",fallback = ItemFeignClientHystrix.class)// 指向回调类
public interface ItemFeignClient {
/**
* 这里定义了类似于SpringMVC用法的方法,就可以进行RESTful方式的调用了
*
* @param id
* @return
*/
@RequestMapping(value = "/item/{id}", method = RequestMethod.GET) //itme/{id} 调用服务端的方法
Item queryItemById(@PathVariable("id") Long id);
}
二:配置文件中开启hystrix
feign:
hystrix:
enabled: true
三:不在方法上使用@HystrixCommand注解 把回调方法删除
四:创建回调类
package com.mr.feign;
import com.mr.model.Item;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PathVariable;
/**
* Created by Admin on 2019/3/18.
*/
@Component
public class ItemFeignClientHystrix implements ItemFeignClient {
@Override
public Item queryItemById(@PathVariable("id") Long id) {
return new Item(id, "查询商品信息出错!", null, null, null);
}
}
.修改启动类,增加包扫描
@ComponentScan(basePackages = {"com.mr.controller", "com.mr.service","com.mr.properties","com.mr.feign"})//手动指定bean扫描范围
正常效果:
关闭服务端 效果如下:
这样 fallback 类配置成功 如有关于 springcloud 疑问 首页进群咨询。