From 85617c675748083ea4ca023491d0d36340631a8b Mon Sep 17 00:00:00 2001 From: xiejiashuai <707094980@qq.com> Date: Tue, 13 Aug 2019 10:59:50 +0800 Subject: [PATCH 1/2] fix g sentinel-feign contextid bug --- .../alibaba/cloud/sentinel/feign/SentinelFeign.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/spring-cloud-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelFeign.java b/spring-cloud-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelFeign.java index b869f844..3dbc00ad 100644 --- a/spring-cloud-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelFeign.java +++ b/spring-cloud-alibaba-sentinel/src/main/java/com/alibaba/cloud/sentinel/feign/SentinelFeign.java @@ -26,6 +26,7 @@ import org.springframework.cloud.openfeign.FeignContext; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.util.ReflectionUtils; +import org.springframework.util.StringUtils; import feign.Contract; import feign.Feign; @@ -82,20 +83,24 @@ public class SentinelFeign { "fallback"); Class fallbackFactory = (Class) getFieldValue(feignClientFactoryBean, "fallbackFactory"); - String name = (String) getFieldValue(feignClientFactoryBean, "name"); + String beanName = (String) getFieldValue(feignClientFactoryBean, + "contextId"); + if (!StringUtils.hasText(beanName)) { + beanName = (String) getFieldValue(feignClientFactoryBean, "name"); + } Object fallbackInstance; FallbackFactory fallbackFactoryInstance; // check fallback and fallbackFactory properties if (void.class != fallback) { - fallbackInstance = getFromContext(name, "fallback", fallback, + fallbackInstance = getFromContext(beanName, "fallback", fallback, target.type()); return new SentinelInvocationHandler(target, dispatch, new FallbackFactory.Default(fallbackInstance)); } if (void.class != fallbackFactory) { - fallbackFactoryInstance = (FallbackFactory) getFromContext(name, - "fallbackFactory", fallbackFactory, + fallbackFactoryInstance = (FallbackFactory) getFromContext( + beanName, "fallbackFactory", fallbackFactory, FallbackFactory.class); return new SentinelInvocationHandler(target, dispatch, fallbackFactoryInstance); From 9872ffea77979b34db4bf8cd4cad51578f748724 Mon Sep 17 00:00:00 2001 From: xiejiashuai <707094980@qq.com> Date: Tue, 13 Aug 2019 12:03:02 +0800 Subject: [PATCH 2/2] Add contextId unit test --- .../sentinel/ContextIdSentinelFeignTests.java | 137 ++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 spring-cloud-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/ContextIdSentinelFeignTests.java diff --git a/spring-cloud-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/ContextIdSentinelFeignTests.java b/spring-cloud-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/ContextIdSentinelFeignTests.java new file mode 100644 index 00000000..e6c581de --- /dev/null +++ b/spring-cloud-alibaba-sentinel/src/test/java/com/alibaba/cloud/sentinel/ContextIdSentinelFeignTests.java @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.cloud.sentinel; + +import static org.junit.Assert.*; + +import java.util.Arrays; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.ImportAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.openfeign.EnableFeignClients; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.junit4.SpringRunner; +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.RequestParam; + +import com.alibaba.cloud.sentinel.feign.SentinelFeignAutoConfiguration; +import com.alibaba.csp.sentinel.slots.block.RuleConstant; +import com.alibaba.csp.sentinel.slots.block.flow.FlowRule; +import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager; + +/** + * Add this unit test to verify https://github.com/alibaba/spring-cloud-alibaba/pull/838 + * + * @author Jim + */ +@RunWith(SpringRunner.class) +@SpringBootTest(classes = { ContextIdSentinelFeignTests.TestConfig.class }, properties = { + "feign.sentinel.enabled=true" }) +public class ContextIdSentinelFeignTests { + + @Autowired + private EchoService echoService; + + @Autowired + private FooService fooService; + + @Test + public void testFeignClient() { + assertEquals("Sentinel Feign Client fallback success", "echo fallback", + echoService.echo("test")); + assertEquals("Sentinel Feign Client fallbackFactory success", "foo fallback", + fooService.echo("test")); + assertNotEquals("ToString method invoke was not in SentinelInvocationHandler", + echoService.toString(), fooService.toString()); + assertNotEquals("HashCode method invoke was not in SentinelInvocationHandler", + echoService.hashCode(), fooService.hashCode()); + assertFalse("Equals method invoke was not in SentinelInvocationHandler", + echoService.equals(fooService)); + } + + @Configuration + @EnableAutoConfiguration + @ImportAutoConfiguration({ SentinelFeignAutoConfiguration.class }) + @EnableFeignClients + public static class TestConfig { + + } + + @FeignClient(contextId = "echoService", name = "service-provider", fallback = EchoServiceFallback.class, configuration = FeignConfiguration.class) + public interface EchoService { + @GetMapping(value = "/echo/{str}") + String echo(@PathVariable("str") String str); + } + + @FeignClient(contextId = "fooService", value = "foo-service", fallbackFactory = CustomFallbackFactory.class, configuration = FeignConfiguration.class) + public interface FooService { + @RequestMapping(path = "echo/{str}") + String echo(@RequestParam("str") String param); + } + + public static class FeignConfiguration { + + @Bean + public EchoServiceFallback echoServiceFallback() { + return new EchoServiceFallback(); + } + + @Bean + public CustomFallbackFactory customFallbackFactory() { + return new CustomFallbackFactory(); + } + + } + + public static class EchoServiceFallback implements EchoService { + + @Override + public String echo(@RequestParam("str") String param) { + return "echo fallback"; + } + + } + + public static class FooServiceFallback implements FooService { + + @Override + public String echo(@RequestParam("str") String param) { + return "foo fallback"; + } + } + + public static class CustomFallbackFactory + implements feign.hystrix.FallbackFactory { + + private FooService fooService = new FooServiceFallback(); + + @Override + public FooService create(Throwable throwable) { + return fooService; + } + } + +}