在feign整合sentinel時遇到了一個問題,折騰了一天,發現是@EnableFeignClients掃包的問題
具體錯誤:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'productController': Unsatisfied dependency expressed through field 'productService'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.yushanma.service.ProductService': FactoryBean threw exception on object creation; nested exception is java.lang.NullPointerException
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:643) ~[spring-beans-5.3.3.jar:5.3.3]
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119) ~[spring-beans-5.3.3.jar:5.3.3]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399) ~[spring-beans-5.3.3.jar:5.3.3]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1415) ~[spring-beans-5.3.3.jar:5.3.3]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:608) ~[spring-beans-5.3.3.jar:5.3.3]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:531) ~[spring-beans-5.3.3.jar:5.3.3]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.3.jar:5.3.3]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.3.jar:5.3.3]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.3.jar:5.3.3]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.3.jar:5.3.3]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944) ~[spring-beans-5.3.3.jar:5.3.3]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:923) ~[spring-context-5.3.3.jar:5.3.3]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:588) ~[spring-context-5.3.3.jar:5.3.3]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:144) ~[spring-boot-2.4.2.jar:2.4.2]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:767) ~[spring-boot-2.4.2.jar:2.4.2]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759) ~[spring-boot-2.4.2.jar:2.4.2]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:426) ~[spring-boot-2.4.2.jar:2.4.2]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:326) ~[spring-boot-2.4.2.jar:2.4.2]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1311) ~[spring-boot-2.4.2.jar:2.4.2]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1300) ~[spring-boot-2.4.2.jar:2.4.2]
at com.yushanma.TestApplication.main(TestApplication.java:21) ~[classes/:na]
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.yushanma.service.ProductService': FactoryBean threw exception on object creation; nested exception is java.lang.NullPointerException
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:176) ~[spring-beans-5.3.3.jar:5.3.3]
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:101) ~[spring-beans-5.3.3.jar:5.3.3]
at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1884) ~[spring-beans-5.3.3.jar:5.3.3]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getObjectForBeanInstance(AbstractAutowireCapableBeanFactory.java:1268) ~[spring-beans-5.3.3.jar:5.3.3]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:267) ~[spring-beans-5.3.3.jar:5.3.3]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.3.jar:5.3.3]
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) ~[spring-beans-5.3.3.jar:5.3.3]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.addCandidateEntry(DefaultListableBeanFactory.java:1605) ~[spring-beans-5.3.3.jar:5.3.3]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1562) ~[spring-beans-5.3.3.jar:5.3.3]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1343) ~[spring-beans-5.3.3.jar:5.3.3]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1300) ~[spring-beans-5.3.3.jar:5.3.3]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:640) ~[spring-beans-5.3.3.jar:5.3.3]
... 20 common frames omitted
Caused by: java.lang.NullPointerException: null
at com.alibaba.cloud.sentinel.feign.SentinelFeign$Builder$1.create(SentinelFeign.java:92) ~[spring-cloud-starter-alibaba-sentinel-2020.0.RC1.jar:2020.0.RC1]
at feign.ReflectiveFeign.newInstance(ReflectiveFeign.java:64) ~[feign-core-10.10.1.jar:na]
at feign.Feign$Builder.target(Feign.java:269) ~[feign-core-10.10.1.jar:na]
at org.springframework.cloud.openfeign.DefaultTargeter.target(DefaultTargeter.java:30) ~[spring-cloud-openfeign-core-3.0.0.jar:3.0.0]
at org.springframework.cloud.openfeign.FeignClientFactoryBean.loadBalance(FeignClientFactoryBean.java:306) ~[spring-cloud-openfeign-core-3.0.0.jar:3.0.0]
at org.springframework.cloud.openfeign.FeignClientFactoryBean.getTarget(FeignClientFactoryBean.java:335) ~[spring-cloud-openfeign-core-3.0.0.jar:3.0.0]
at org.springframework.cloud.openfeign.FeignClientFactoryBean.getObject(FeignClientFactoryBean.java:315) ~[spring-cloud-openfeign-core-3.0.0.jar:3.0.0]
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:169) ~[spring-beans-5.3.3.jar:5.3.3]
... 31 common frames omitted
Process finished with exit code 1
雖然用了@EnableFeignClients注解,但是在微服務多子產品項目中也掃不到@FeignClient注解的類,這個類沒有生成執行個體,在controller中@Autowire就沒有辦法注入依賴,最後報不滿足依賴的錯誤。
解決方法:指定掃描@FeignClient所在的包路徑
package com.yushanma;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.SpringCloudApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication//(scanBasePackages = {"com.yushanma.service","com.yushanma.controller"})
//@EnableDiscoveryClient
@EnableFeignClients(basePackages="com.yushanma.fallback")
//@EnableFeignClients
//@SpringCloudApplication
@MapperScan("com.pojo.mapper")
public class TestApplication {
public static void main(String[] args) {
SpringApplication.run(TestApplication.class);
}
}

關閉商品微服務後,訂單微服務進入容錯邏輯
完整代碼
package com.yushanma.service;
//Product product =
// restTemplate.getForObject("http://" + url + "/product/" + pid, Product.class);
import com.pojo.model.Product;
import com.yushanma.config.FeignConfiguration;
import com.yushanma.fallback.EchoServiceFallback;
import com.yushanma.fallback.EchoServiceFallbackFactory;
import com.yushanma.fallback.ProductServiceFallback;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.context.annotation.Primary;
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.RequestMethod;
@FeignClient(
name = "service-product",
// fallback = ProductServiceFallback.class
// fallbackFactory = ProductServiceFallBackFactory.class
fallbackFactory = EchoServiceFallbackFactory.class,
primary = true
// fallback = EchoServiceFallback.class,
// configuration = FeignConfiguration.class
)
public interface ProductService {
//@[email protected] 就是一個完整的請求路徑 http://service-product/product/{pid}
@RequestMapping(method = RequestMethod.GET, value = "/product/{pid}")
Product findByPid(@PathVariable("pid") Integer pid);
}
package com.yushanma.fallback;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;
@Component
public class EchoServiceFallbackFactory implements FallbackFactory<EchoServiceFallback> {
@Override
public EchoServiceFallback create(Throwable throwable) {
return new EchoServiceFallback(throwable);
}
}
package com.yushanma.fallback;
import com.pojo.model.Product;
import com.yushanma.service.ProductService;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class EchoServiceFallback implements ProductService {
private Throwable throwable;
EchoServiceFallback(Throwable throwable) {
this.throwable = throwable;
}
@Override
public Product findByPid(Integer pid) {
Product product = new Product();
product.setPid(-1);
product.setPname("product-service調用出錯,進入容錯邏輯");
// log.info("{}",throwable.getMessage());
return product;
}
}
package com.yushanma.controller;
import com.alibaba.fastjson.JSON;
import com.pojo.model.Order;
import com.pojo.model.Product;
import com.yushanma.service.OrderService;
import com.yushanma.service.ProductService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Slf4j
public class ProductController {
@Autowired
private OrderService orderService;
@Autowired
private ProductService productService;
// 基于Ribbon實作負載均衡
@RequestMapping("order/prod/{pid}")
public Order order(@PathVariable("pid") Integer pid) {
log.info("查詢商品{}", pid);
Product product = productService.findByPid(pid);
//容錯處理
if (product.getPid() == -1) {
Order order = new Order();
order.setPname("下單失敗");
return order;
}
log.info("查詢到的商品資訊為{}", JSON.toJSONString(product));
Order order = new Order();
order.setUid(1);
order.setUsername("yushanma");
order.setPid(pid);
order.setPname(product.getPname());
order.setPprice(product.getPprice());
order.setNumber(1);
// orderService.createOrder(order);
log.info("建立新的訂單{}", JSON.toJSONString(order));
return order;
}
}
但是出現後續問題:無論商品微服務是否開啟,訂單微服務一直進入容錯邏輯
發現是(basePackages="com.yushanma.fallback")的問題,應指定為"com.yushanma.service",但還是報空指針錯誤。最終考慮更換父工程版本:
<!-- 父工程-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.2.RELEASE</version>
</parent>
<!--版本依賴的鎖定-->
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-cloud.version>Hoxton.SR8</spring-cloud.version>
<spring-cloud-alibaba.version>2.2.5.RELEASE</spring-cloud-alibaba.version>
</properties>
去掉feign的版本指定:
<!--fegin元件-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- Feign Client for loadBalancing -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>
不需再指定掃包:
開啟兩個服務後:請求下單成功
關閉商品微服務後下單:進入容錯邏輯
至此,feign整合sentinel完成。
參考:
https://www.cnblogs.com/keeya/p/14476548.html
https://docs.spring.io/spring-cloud-openfeign/docs/current/reference/html/#spring-cloud-feign-overriding-defaults
https://segmentfault.com/a/1190000018914017
https://github.com/alibaba/spring-cloud-alibaba/tree/master/spring-cloud-alibaba-examples/sentinel-example/sentinel-feign-example