标签: feign

如何使用spring-cloud-netflix和feign编写集成测试

我使用Spring-Cloud-Netflix进行微服务之间的通信.假设我有两个服务,Foo和Bar,而Foo使用Bar的REST端点之一.我使用一个带注释的接口@FeignClient:

@FeignClient
public interface BarClient {
  @RequestMapping(value = "/some/url", method = "POST")
  void bazzle(@RequestBody BazzleRequest);
}
Run Code Online (Sandbox Code Playgroud)

然后我SomeService在Foo中有一个服务类,它调用了BarClient.

@Component
public class SomeService {
    @Autowired
    BarClient barClient;

    public String doSomething() {
      try {
        barClient.bazzle(new BazzleRequest(...));
        return "so bazzle my eyes dazzle";
      } catch(FeignException e) {
        return "Not bazzle today!";
      }

    }
}
Run Code Online (Sandbox Code Playgroud)

现在,为了确保服务之间的通信正常工作,我想构建一个测试,使用WireMock之类的东西,对一个假的Bar服务器发出真正的HTTP请求.测试应确保假设正确解码服务响应并报告SomeService.

public class SomeServiceIntegrationTest {

    @Autowired SomeService someService;

    @Test
    public void shouldSucceed() {
      stubFor(get(urlEqualTo("/some/url"))
        .willReturn(aResponse()
            .withStatus(204);

      String result = someService.doSomething();

      assertThat(result, is("so …
Run Code Online (Sandbox Code Playgroud)

java wiremock netflix-eureka feign spring-cloud-netflix

21
推荐指数
4
解决办法
2万
查看次数

如果受hystrix保护的呼叫超时,我可以抛出自定义错误吗?

这个外部呼叫我有一个假装客户端:

@RequestMapping(method = RequestMethod.GET, value = "GetResourceA", consumes = "application/json")
@Cacheable("ResourceA")
List<Stop> getResourceA() throws MyOwnException;
Run Code Online (Sandbox Code Playgroud)

在我的application.yml我有这个设置:

hystrix:
  command:
    default:
      execution.isolation.thread.timeoutInMilliseconds: 1000
      fallback.enabled: false
Run Code Online (Sandbox Code Playgroud)

现在,如果getResourceA超时,即完成时间超过一秒,我得到这个:

com.netflix.hystrix.exception.HystrixRuntimeException: getResourceA timed-out and no fallback available
Run Code Online (Sandbox Code Playgroud)

或者,如果我定义了一个我自己抛出异常的后备,我得到这个:

com.netflix.hystrix.exception.HystrixRuntimeException: getResourceA timed-out and fallback failed.
Run Code Online (Sandbox Code Playgroud)

我不能从后备中抛出自己的异常吗?

如果我希望在服务停止时抛出自己的异常怎么办?我想没有后备(因为我没有合理的价值从回退中返回),而是抛出我自己的错误,我可以抓住并让程序恢复.有人可以帮我解决这个问题吗?

Ben回答后更新:

所以我尝试了捕获HysterixRuntimeException并检查导致它的原因的方法,但最终得到了这个丑陋的代码:

try {
    getResourceA();
} catch (HystrixRuntimeException e) {
    if (e.getFailureType().name().equals("TIMEOUT")) {
        throw new MyOwnException("Service timed out");
    }
    throw e;
}
Run Code Online (Sandbox Code Playgroud)

所有能够在超时时抛出MyOwnException的东西.肯定还有另一种方式吗?

java spring hystrix feign

13
推荐指数
1
解决办法
2029
查看次数

记录日志不起作用

我正在尝试为Feign rest客户端的每个请求进行日志记录.但是我无法使日志工作,而'标准'Slf4j日志记录确实有效.

我有以下内容:

public MyClient() {
        initConnectionProperties();

        this.service = Feign.builder()
                .contract(new JAXRSContract())
                .decoder(getJacksonDecoder())
                .encoder(getJacksonEncoder())


                .requestInterceptor(new BasicAuthRequestInterceptor(user, password))
                //.client(new OkHttpClient())
                .logger(new Slf4jLogger(MyClient.class)) //not working

                .logLevel(feign.Logger.Level.BASIC)
                .target(MyClient.class, this.url);
        logger.info("Connection parameters: url = " + url + ", user = " + user); //Is working
    }
Run Code Online (Sandbox Code Playgroud)

java feign

13
推荐指数
6
解决办法
2万
查看次数

spring feign 客户端异常处理

我有一些 fiegn 客户端发送请求其他微服务。

@FeignClient(name="userservice")
public interface UserClient {

    @RequestMapping(
            method= RequestMethod.GET,
                      path = "/userlist")
    String getUserByid(@RequestParam(value ="id") String id);

}
Run Code Online (Sandbox Code Playgroud)

现在我正在发送这样的请求

try {
    String responseData = userClient.getUserByid(id);
    return responseData;
    }

catch(FeignException e)
 {
 logger.error("Failed to get user", id);
}

catch (Exception e) 
{
 logger.error("Failed to get user", id);
}
Run Code Online (Sandbox Code Playgroud)

这里的问题是,如果发生任何 FeignException,我不会收到任何错误代码。

我需要在其他 APIS 中发送相应的错误代码以发送给调用方

那么如何提取错误代码呢?我想提取错误代码并构建一个 responseEntity

我得到了这段代码,但不知道如何在我的函数中使用。

exception spring-cloud-feign feign

12
推荐指数
4
解决办法
5万
查看次数

如何为特定客户端设置自定义 Feign RequestInterceptor?

我需要向一些新的假客户端添加自定义授权标头。所以我编写了一个 RequestInterceptor 并且它起作用了,但重点是我不希望这个自定义 RequestInterceptor 影响我的旧客户端。我尝试使用 template.url() 方法进行过滤,但它没有给我请求的整个 url,它只包含客户端方法 url(不是客户端类上方宣布的 url 和路径)。我的问题是如何瞄准拦截器?

这是我的配置:

@Configuration
open class FeignCustomConfiguration {

    private fun generateToken(): String { ... }

    @Bean
    open fun requestInterceptor(): RequestInterceptor {
        return RequestInterceptor {
            it.header("Authorization", generateToken())
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

kotlin spring-boot feign

12
推荐指数
1
解决办法
1万
查看次数

netflix.feign和openfeign之间的差异

介绍

我最近使用netflix假装和功能区非常有用.

一个例子是:

@FeignClient(name = "ldap-proxy")
public interface LdapProxyClient  { 
    @RequestMapping(path = "/ldap-proxy/v1/users/{userNameOrEMail}", produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.GET)
    LdapUser search(@PathVariable("userNameOrEMail") String userNameOrEMail);
}
Run Code Online (Sandbox Code Playgroud)

但是,在某些时候,我认为不必手动编写所有这些定义(对于现有的Web服务),我应该看看是否存在工具.

我偶然发现了https://github.com/swagger-api/swagger-codegen一些客户端生成的例子,例如https://github.com/swagger-api/swagger-codegen/tree/master/samples/client/petstore/java/feign.

但是,一旦我仔细查看了进口,我注意到以下情况:

import feign.Feign;

另一方面,Netflix的开源解决方案有包名: org.springframework.cloud.netflix.feign.

另外,我注意到两者都使用功能区(如果可用),但Netflix的表示法更加清晰,后台发生了很多事情.例如,@FeignClient注释类javadoc声明:

  • 接口的注释声明应该*创建具有该接口的REST客户端(例如,用于自动装配到另一个组件中).如果功能区可用,它将*用于对后端请求进行负载平衡,并且可以使用@RibbonClient与feign客户端具有相同名称(即值)的a来配置负载均衡器.

但是在Feign.feign文档中(https://github.com/OpenFeign/feign),我看到:

RibbonClient覆盖了Feign客户端的URL解析,添加了Ribbon提供的智能路由和弹性功能.

集成要求您将功能区客户端名称作为URL的主机部分传递,例如myAppProd.

> MyService api =
> Feign.builder().client(RibbonClient.create()).target(MyService.class,
> "https://myAppProd");
Run Code Online (Sandbox Code Playgroud)

所以我的问题是:

  1. 两者之间的历史/关系和差异是什么?
  2. 各自的优点和缺点是什么?

它们是完全不同的项目,没有关系,或者netflix只是分叉/利用OpenFeign并将其修改为在其集成云解决方案中?从本质上讲,netflix是否只是从开源项目中获取并集成了Discovery,Ribbon和feign等不同技术?

java spring-cloud netflix-feign spring-cloud-feign feign

10
推荐指数
2
解决办法
8758
查看次数

如何使用Spring Cloud Feign发布form-url编码的数据

使用spring-mvc注释,如何定义可以POST form-url-encoded的@FeignClient?

spring-mvc spring-cloud spring-cloud-feign feign

9
推荐指数
3
解决办法
9843
查看次数

如何向假装客户端添加请求拦截器?

每当我通过假装客户端发出请求时,我都希望为我的身份验证用户设置一个特定的标头.

这是我的过滤器,我从中获取身份验证并将其设置为spring安全上下文:

@EnableEurekaClient
@SpringBootApplication
@EnableFeignClients
public class PerformanceApplication {
    @Bean
    public Filter requestDetailsFilter() {
        return new RequestDetailsFilter();
    }

    public static void main(String[] args) {
        SpringApplication.run(PerformanceApplication.class, args);
    }

    private class RequestDetailsFilter implements Filter {
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {

        }

        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            String userName = ((HttpServletRequest)servletRequest).getHeader("Z-User-Details");
            String pass = ((HttpServletRequest)servletRequest).getHeader("X-User-Details");
            if (pass != null)
                pass = decrypt(pass);
            SecurityContext secure = new SecurityContextImpl();
            org.springframework.security.core.Authentication token = new UsernamePasswordAuthenticationToken(userName, …
Run Code Online (Sandbox Code Playgroud)

java authentication spring header feign

9
推荐指数
2
解决办法
2万
查看次数

@EnableFeignClients和@FeignClient在自动装配'FeignContext'时失败NoSuchBeanException

我正在编写的微服务需要与我们平台中的其他微服务进行通信.在那次尝试中,我们的理想解决方案是Spring Cloud Netflix Feign,实现了一个@FeignClient.

但是,当我尝试以下时,我正面临以下例外@Autowired ReviewProvider:

例外(原因)

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.cloud.netflix.feign.FeignContext' available
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:353)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:351)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:340)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1093)
    at org.springframework.cloud.netflix.feign.FeignClientFactoryBean.getObject(FeignClientFactoryBean.java:155)
    at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:168)
Run Code Online (Sandbox Code Playgroud)

ReviewProvider.java

@FeignClient("http://metadata-reviews")
public interface ReviewProvider {

    @RequestMapping(path = "sessions", method = POST)
    ReviewSessionDTO createSession();

}
Run Code Online (Sandbox Code Playgroud)

ReviewProvider.java

@RunWith(SpringRunner.class)
@ActiveProfiles(INTEGRATION)
@ContextConfiguration(classes = AppEntry.class)
@AutoConfigureTestDatabase(replace = Replace.NONE)
@DataJpaTest
public class ReviewProviderTest {

    @Autowired
    private ReviewProvider provider;
    private Class<? extends ReviewProvider> providerClass;

    @Before
    public void setup() {
        providerClass = …
Run Code Online (Sandbox Code Playgroud)

java spring-boot spring-cloud-feign feign spring-cloud-netflix

9
推荐指数
2
解决办法
2万
查看次数

使用新的请求拦截器来假设客户端重试程序?

我目前正在手动构建一个假装客户端并将拦截器传递给它进行授权.我想为一些响应代码提供更智能的Retryer.

public class myErrorEncoder extends ErrorDecoder.Default {

@Override
public Exception decode(final String methodKey, final Response response) {
    if (response.status() == 401) {
        String token = refreshToken();  // I would like to refresh the token and Edit the client
        return new RetryableException("Token Expired will retry it", null);
    } else {
        return super.decode(methodKey, response);
    }
}
Run Code Online (Sandbox Code Playgroud)

}

拦截器

@Bean public CustomInterceptor getInterceptor(String token) {
    return new CustomInterceptor(token);}
Run Code Online (Sandbox Code Playgroud)

假装建设者

 private <T> T feignBuild(final Class<T> clazz, final String uri, final String token) {
    return …
Run Code Online (Sandbox Code Playgroud)

java interceptor spring-cloud-feign feign

9
推荐指数
1
解决办法
923
查看次数