springcloud提供了两种消费服务的方式,feign和ribbon。实质上feign是集成了ribbon的,终也是利用ribbon做了均衡负载发了http请求。ribbon的方式编码的时候更像是用到了http请求,feign编码的时候感觉上更像使用了一个接口。所有还是用了feign(用起来舒服一点)
有spring cloud b2b2c电子商务需求的朋友可以加企鹅求求:一零三八七七四六二六
1.在消费者的项目里面新建一个类:
@RestController
@SpringBootApplication
@EnableFeignClients//开启feign
public class Hello {
@Autowired
private HelloRemote helloRemote;//定义的接口,供feign使用
@RequestMapping("/hello/{name}")
public String index(@PathVariable("name") String name) {
return helloRemote.hello(name);
// return "hello " + name;
}
@RequestMapping("/sayIp/{name}")
public String sayIp(@PathVariable("name") String name) {
if (!"aaa".equals(name)) {
name = null;
}
return helloRemote.sayIp(name);
}
}
2.在消费者的项目里面创建HelloRemote接口
@FeignClient(name = "PRODUCER", fallback = HelloRemoteFallback.class)
//PRODUCER是生产者的名字fallback是断路后降级执行的类
public interface HelloRemote {@RequestMapping(value = "/hello")//服务提供者的路由地址,这里不支持getMapping方法@ResponseBodypublic String hello(@RequestParam(value = "name") String name);@RequestMapping(value = "/getIp", method = RequestMethod.POST)//参数包含了对象后,好用post,get方式只能传简单参数(参数的地方有坑,需要注意到用)@ResponseBodypublic String sayIp(@PathVariable(value = "name") String name);//参数是null的时候,会报错}
3.在生产者里面创建一个服务:
@RestController
public class SayWord {
@Autowired
private DiscoveryClient discoveryClient;
@RequestMapping(value = "hello")//消费者寻找的路由
public String index(@RequestParam String name) {
ServiceInstance aa = discoveryClient.getLocalServiceInstance();
System.out.println(aa);
return "hello! " + name + ",this is my first messge!";
}
@RequestMapping(value = "getIp")
public String getIp(@RequestParam String name) throws UnknownHostException {
ServiceInstance aa = discoveryClient.getLocalServiceInstance();
String addr = InetAddress.getLocalHost().getHostAddress();
System.out.println(aa);
return "hello! " + name + ",this is my second messge!,I will tell you what is my IP:" + addr;
}
}
4.在消费者项目中创建降级处理的类:
@Component
public class HelloRemoteFallback implements HelloRemote {//要实现需要降级处理的接口
@Override
public String hello(String name) {
return null;
}
@Override
public String sayIp(String name) {
return "sayIp 错了";
}
}
5.在消费者项目中创建
/***
*
做一个熔断的判断,在400期间的异常,不熔断服务(400 期间的异常很多是使用feign的参数传递错误造成的,不必让服务熔断)**
*
* @author aa
**/
@Configuration
public class BizExceptionFeignErrorDecoder implements feign.codec.ErrorDecoder {
//重写一下errorDecoder,把400-500区间的异常,用不做服务熔断的方式进行一下处理
private static final Logger logger = LoggerFactory.getLogger(BizExceptionFeignErrorDecoder.class);
@Override
public Exception decode(String methodKey, Response response) {
logger.debug("bizExceptionFeignErrorDecoder decode:" + methodKey + "/" + response);
Exception exception = null;
if (response.status() >= 400 && response.status() <= 499) {
exception = new HystrixBadRequestException(String.valueOf(response.status()));// 不会被计数,也不会进入阻断器
logger.debug(exception.getMessage());
} else {
exception = feign.FeignException.errorStatus(methodKey, response);
logger.debug(exception.getMessage());
}
return exception;
}
}