diff --git a/sentinel-adapter/pom.xml b/sentinel-adapter/pom.xml index a8ef8810..32965816 100755 --- a/sentinel-adapter/pom.xml +++ b/sentinel-adapter/pom.xml @@ -27,6 +27,7 @@ sentinel-spring-cloud-gateway-adapter sentinel-spring-webmvc-adapter sentinel-zuul2-adapter + sentinel-okhttp-adapter sentinel-jax-rs-adapter diff --git a/sentinel-adapter/sentinel-okhttp-adapter/README.md b/sentinel-adapter/sentinel-okhttp-adapter/README.md new file mode 100755 index 00000000..6b5e61d5 --- /dev/null +++ b/sentinel-adapter/sentinel-okhttp-adapter/README.md @@ -0,0 +1,63 @@ +# Sentinel OkHttp Adapter + +## Introduction + +Sentinel provides integration for OkHttp client to enable flow control for web requests. + +Add the following dependency in `pom.xml` (if you are using Maven): + +```xml + + com.alibaba.csp + sentinel-okhttp-adapter + x.y.z + +``` + +We can add the `SentinelOkHttpInterceptor` interceptor when `OkHttpClient` at initialization, for example: + +```java +OkHttpClient client = new OkHttpClient.Builder() + .addInterceptor(new SentinelOkHttpInterceptor()) + .build(); +``` + +## Configuration + +- `SentinelOkHttpConfig` configuration: + +| name | description | type | default value | +|------|------------|------|-------| +| extractor | custom resource extractor | `OkHttpResourceExtractor` | `DefaultOkHttpResourceExtractor` | +| fallback | handle request when it is blocked | `OkHttpFallback` | `DefaultOkHttpFallback` | + +### extractor (resource extractor) + +We can define `OkHttpResourceExtractor` to custom resource extractor replace `DefaultOkHttpResourceExtractor`, for example: okhttp:GET:ip:port/okhttp/back/1 ==> /okhttp/back/{id} + +```java +OkHttpResourceExtractor extractor = (request, connection) -> { + String resource = request.url().toString(); + String regex = "/okhttp/back/"; + if (resource.contains(regex)) { + resource = resource.substring(0, resource.indexOf(regex) + regex.length()) + "{id}"; + } + return resource; +}; +SentinelOkHttpConfig.setExtractor(extractor); +``` + +### fallback (Block handling) + +We can define `OkHttpFallback` to handle request is blocked according to the actual scenario, for example: + +```java +public class DefaultOkHttpFallback implements OkHttpFallback { + + @Override + public Response handle(Request request, Connection connection, BlockException e) { + // Just wrap and throw the exception. + throw new SentinelRpcException(e); + } +} +``` \ No newline at end of file diff --git a/sentinel-adapter/sentinel-okhttp-adapter/pom.xml b/sentinel-adapter/sentinel-okhttp-adapter/pom.xml new file mode 100644 index 00000000..658d4e41 --- /dev/null +++ b/sentinel-adapter/sentinel-okhttp-adapter/pom.xml @@ -0,0 +1,68 @@ + + + + sentinel-adapter + com.alibaba.csp + 1.8.0-SNAPSHOT + + 4.0.0 + + sentinel-okhttp-adapter + jar + + + 3.6.0 + 2.1.3.RELEASE + 5.1.5.RELEASE + + + + + com.alibaba.csp + sentinel-core + + + + com.squareup.okhttp3 + okhttp + ${okhttp.version} + provided + + + + junit + junit + test + + + org.mockito + mockito-core + test + + + com.alibaba + fastjson + test + + + org.springframework.boot + spring-boot-starter-web + ${spring.boot.version} + test + + + org.springframework.boot + spring-boot-test + ${spring.boot.version} + test + + + org.springframework + spring-test + ${spring-test.version} + test + + + \ No newline at end of file diff --git a/sentinel-adapter/sentinel-okhttp-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/okhttp/SentinelOkHttpInterceptor.java b/sentinel-adapter/sentinel-okhttp-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/okhttp/SentinelOkHttpInterceptor.java new file mode 100644 index 00000000..0e8f54a3 --- /dev/null +++ b/sentinel-adapter/sentinel-okhttp-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/okhttp/SentinelOkHttpInterceptor.java @@ -0,0 +1,55 @@ +/* + * Copyright 1999-2020 Alibaba Group Holding Ltd. + * + * 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.csp.sentinel.adapter.okhttp; + +import com.alibaba.csp.sentinel.*; +import com.alibaba.csp.sentinel.adapter.okhttp.config.SentinelOkHttpConfig; +import com.alibaba.csp.sentinel.slots.block.BlockException; +import com.alibaba.csp.sentinel.util.StringUtil; +import okhttp3.Interceptor; +import okhttp3.Request; +import okhttp3.Response; + +import java.io.IOException; + +/** + * @author zhaoyuguang + */ +public class SentinelOkHttpInterceptor implements Interceptor { + + @Override + public Response intercept(Chain chain) throws IOException { + Entry entry = null; + try { + Request request = chain.request(); + String name = SentinelOkHttpConfig.getExtractor().extract(request.url().toString(), request, chain.connection()); + if (!StringUtil.isEmpty(SentinelOkHttpConfig.getPrefix())) { + name = SentinelOkHttpConfig.getPrefix() + name; + } + entry = SphU.entry(name, ResourceTypeConstants.COMMON_WEB, EntryType.OUT); + return chain.proceed(request); + } catch (BlockException e) { + return SentinelOkHttpConfig.getFallback().handle(chain.request(), chain.connection(), e); + } catch (Throwable t) { + Tracer.traceEntry(t, entry); + throw t; + } finally { + if (entry != null) { + entry.exit(); + } + } + } +} \ No newline at end of file diff --git a/sentinel-adapter/sentinel-okhttp-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/okhttp/config/SentinelOkHttpConfig.java b/sentinel-adapter/sentinel-okhttp-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/okhttp/config/SentinelOkHttpConfig.java new file mode 100644 index 00000000..48e986f7 --- /dev/null +++ b/sentinel-adapter/sentinel-okhttp-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/okhttp/config/SentinelOkHttpConfig.java @@ -0,0 +1,59 @@ +/* + * Copyright 1999-2020 Alibaba Group Holding Ltd. + * + * 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.csp.sentinel.adapter.okhttp.config; + +import com.alibaba.csp.sentinel.adapter.okhttp.extractor.DefaultOkHttpResourceExtractor; +import com.alibaba.csp.sentinel.adapter.okhttp.extractor.OkHttpResourceExtractor; +import com.alibaba.csp.sentinel.adapter.okhttp.fallback.DefaultOkHttpFallback; +import com.alibaba.csp.sentinel.adapter.okhttp.fallback.OkHttpFallback; +import com.alibaba.csp.sentinel.util.AssertUtil; + +/** + * @author zhaoyuguang + */ +public final class SentinelOkHttpConfig { + + private static volatile String prefix = "okhttp:"; + private static volatile OkHttpResourceExtractor extractor = new DefaultOkHttpResourceExtractor(); + private static volatile OkHttpFallback fallback = new DefaultOkHttpFallback(); + + public static String getPrefix() { + return prefix; + } + + public static void setPrefix(String prefix) { + AssertUtil.notNull(prefix, "prefix cannot be null"); + SentinelOkHttpConfig.prefix = prefix; + } + + public static OkHttpResourceExtractor getExtractor() { + return extractor; + } + + public static void setExtractor(OkHttpResourceExtractor extractor) { + AssertUtil.notNull(extractor, "extractor cannot be null"); + SentinelOkHttpConfig.extractor = extractor; + } + + public static OkHttpFallback getFallback() { + return fallback; + } + + public static void setFallback(OkHttpFallback fallback) { + AssertUtil.notNull(fallback, "fallback cannot be null"); + SentinelOkHttpConfig.fallback = fallback; + } +} diff --git a/sentinel-adapter/sentinel-okhttp-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/okhttp/extractor/DefaultOkHttpResourceExtractor.java b/sentinel-adapter/sentinel-okhttp-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/okhttp/extractor/DefaultOkHttpResourceExtractor.java new file mode 100644 index 00000000..1a7cc2bc --- /dev/null +++ b/sentinel-adapter/sentinel-okhttp-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/okhttp/extractor/DefaultOkHttpResourceExtractor.java @@ -0,0 +1,30 @@ +/* + * Copyright 1999-2020 Alibaba Group Holding Ltd. + * + * 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.csp.sentinel.adapter.okhttp.extractor; + +import okhttp3.Connection; +import okhttp3.Request; + +/** + * @author zhaoyuguang + */ +public class DefaultOkHttpResourceExtractor implements OkHttpResourceExtractor { + + @Override + public String extract(String url, Request request, Connection connection) { + return request.method() + ":" + request.url().toString(); + } +} diff --git a/sentinel-adapter/sentinel-okhttp-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/okhttp/extractor/OkHttpResourceExtractor.java b/sentinel-adapter/sentinel-okhttp-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/okhttp/extractor/OkHttpResourceExtractor.java new file mode 100644 index 00000000..2a376d41 --- /dev/null +++ b/sentinel-adapter/sentinel-okhttp-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/okhttp/extractor/OkHttpResourceExtractor.java @@ -0,0 +1,27 @@ +/* + * Copyright 1999-2020 Alibaba Group Holding Ltd. + * + * 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.csp.sentinel.adapter.okhttp.extractor; + +import okhttp3.Connection; +import okhttp3.Request; + +/** + * @author zhaoyuguang + */ +public interface OkHttpResourceExtractor { + + String extract(String url, Request request, Connection connection); +} diff --git a/sentinel-adapter/sentinel-okhttp-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/okhttp/fallback/DefaultOkHttpFallback.java b/sentinel-adapter/sentinel-okhttp-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/okhttp/fallback/DefaultOkHttpFallback.java new file mode 100644 index 00000000..6ece854f --- /dev/null +++ b/sentinel-adapter/sentinel-okhttp-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/okhttp/fallback/DefaultOkHttpFallback.java @@ -0,0 +1,34 @@ +/* + * Copyright 1999-2020 Alibaba Group Holding Ltd. + * + * 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.csp.sentinel.adapter.okhttp.fallback; + +import com.alibaba.csp.sentinel.slots.block.BlockException; +import com.alibaba.csp.sentinel.slots.block.SentinelRpcException; +import okhttp3.Connection; +import okhttp3.Request; +import okhttp3.Response; + +/** + * @author zhaoyuguang + */ +public class DefaultOkHttpFallback implements OkHttpFallback { + + @Override + public Response handle(Request request, Connection connection, BlockException e) { + // Just wrap and throw the exception. + throw new SentinelRpcException(e); + } +} diff --git a/sentinel-adapter/sentinel-okhttp-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/okhttp/fallback/OkHttpFallback.java b/sentinel-adapter/sentinel-okhttp-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/okhttp/fallback/OkHttpFallback.java new file mode 100644 index 00000000..4127c195 --- /dev/null +++ b/sentinel-adapter/sentinel-okhttp-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/okhttp/fallback/OkHttpFallback.java @@ -0,0 +1,29 @@ +/* + * Copyright 1999-2020 Alibaba Group Holding Ltd. + * + * 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.csp.sentinel.adapter.okhttp.fallback; + +import com.alibaba.csp.sentinel.slots.block.BlockException; +import okhttp3.Connection; +import okhttp3.Request; +import okhttp3.Response; + +/** + * @author zhaoyuguang + */ +public interface OkHttpFallback { + + Response handle(Request request, Connection connection, BlockException e); +} diff --git a/sentinel-adapter/sentinel-okhttp-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/okhttp/SentinelOkHttpInterceptorTest.java b/sentinel-adapter/sentinel-okhttp-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/okhttp/SentinelOkHttpInterceptorTest.java new file mode 100644 index 00000000..4f831b9b --- /dev/null +++ b/sentinel-adapter/sentinel-okhttp-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/okhttp/SentinelOkHttpInterceptorTest.java @@ -0,0 +1,97 @@ +/* + * Copyright 1999-2020 Alibaba Group Holding Ltd. + * + * 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.csp.sentinel.adapter.okhttp; + +import com.alibaba.csp.sentinel.Constants; +import com.alibaba.csp.sentinel.adapter.okhttp.app.TestApplication; +import com.alibaba.csp.sentinel.adapter.okhttp.config.SentinelOkHttpConfig; +import com.alibaba.csp.sentinel.adapter.okhttp.extractor.OkHttpResourceExtractor; +import com.alibaba.csp.sentinel.node.ClusterNode; +import com.alibaba.csp.sentinel.slots.clusterbuilder.ClusterBuilderSlot; +import okhttp3.Connection; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.junit.Assert.assertNotNull; + +/** + * @author zhaoyuguang + */ +@RunWith(SpringRunner.class) +@SpringBootTest(classes = TestApplication.class, + webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT, + properties = { + "server.port=8086" + }) +public class SentinelOkHttpInterceptorTest { + + @Value("${server.port}") + private Integer port; + + @Test + public void testSentinelOkHttpInterceptor0() throws Exception { + + String url0 = "http://localhost:" + port + "/okhttp/back"; + SentinelOkHttpConfig.setPrefix("okhttp:"); + OkHttpClient client = new OkHttpClient.Builder() + .addInterceptor(new SentinelOkHttpInterceptor()) + .build(); + Request request = new Request.Builder() + .url(url0) + .build(); + System.out.println(client.newCall(request).execute().body().string()); + ClusterNode cn = ClusterBuilderSlot.getClusterNode(SentinelOkHttpConfig.getPrefix() + "GET:" + url0); + assertNotNull(cn); + + Constants.ROOT.removeChildList(); + ClusterBuilderSlot.getClusterNodeMap().clear(); + } + + @Test + public void testSentinelOkHttpInterceptor1() throws Exception { + + String url0 = "http://localhost:" + port + "/okhttp/back/1"; + SentinelOkHttpConfig.setExtractor(new OkHttpResourceExtractor() { + @Override + public String extract(String url, Request request, Connection connection) { + String regex = "/okhttp/back/"; + if (url.contains(regex)) { + url = url.substring(0, url.indexOf(regex) + regex.length()) + "{id}"; + } + return request.method() + ":" + url; + } + }); + OkHttpClient client = new OkHttpClient.Builder() + .addInterceptor(new SentinelOkHttpInterceptor()) + .build(); + Request request = new Request.Builder() + .url(url0) + .build(); + System.out.println(client.newCall(request).execute().body().string()); + + String url1 = SentinelOkHttpConfig.getPrefix() + "GET:http://localhost:" + port + "/okhttp/back/{id}"; + ClusterNode cn = ClusterBuilderSlot.getClusterNode(url1); + assertNotNull(cn); + + Constants.ROOT.removeChildList(); + ClusterBuilderSlot.getClusterNodeMap().clear(); + } +} diff --git a/sentinel-adapter/sentinel-okhttp-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/okhttp/app/TestApplication.java b/sentinel-adapter/sentinel-okhttp-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/okhttp/app/TestApplication.java new file mode 100644 index 00000000..8eef5893 --- /dev/null +++ b/sentinel-adapter/sentinel-okhttp-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/okhttp/app/TestApplication.java @@ -0,0 +1,30 @@ +/* + * Copyright 1999-2020 Alibaba Group Holding Ltd. + * + * 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.csp.sentinel.adapter.okhttp.app; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * @author zhaoyuguang + */ +@SpringBootApplication +public class TestApplication { + + public static void main(String[] args) { + SpringApplication.run(TestApplication.class); + } +} diff --git a/sentinel-adapter/sentinel-okhttp-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/okhttp/app/controller/TestController.java b/sentinel-adapter/sentinel-okhttp-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/okhttp/app/controller/TestController.java new file mode 100644 index 00000000..96dd3674 --- /dev/null +++ b/sentinel-adapter/sentinel-okhttp-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/okhttp/app/controller/TestController.java @@ -0,0 +1,37 @@ +/* + * Copyright 1999-2020 Alibaba Group Holding Ltd. + * + * 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.csp.sentinel.adapter.okhttp.app.controller; + +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author zhaoyuguang + */ +@RestController +public class TestController { + + @RequestMapping("/okhttp/back") + public String back() { + return "Welcome Back!"; + } + + @RequestMapping("/okhttp/back/{id}") + public String back(@PathVariable String id) { + return "Welcome Back! " + id; + } +} \ No newline at end of file diff --git a/sentinel-adapter/sentinel-okhttp-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/okhttp/config/SentinelOkHttpConfigTest.java b/sentinel-adapter/sentinel-okhttp-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/okhttp/config/SentinelOkHttpConfigTest.java new file mode 100644 index 00000000..b9f60553 --- /dev/null +++ b/sentinel-adapter/sentinel-okhttp-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/okhttp/config/SentinelOkHttpConfigTest.java @@ -0,0 +1,39 @@ +/* + * Copyright 1999-2020 Alibaba Group Holding Ltd. + * + * 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.csp.sentinel.adapter.okhttp.config; + +import org.junit.Test; + +/** + * @author zhaoyuguang + */ +public class SentinelOkHttpConfigTest { + + @Test(expected = IllegalArgumentException.class) + public void testConfigSetPrefix() { + SentinelOkHttpConfig.setPrefix(null); + } + + @Test(expected = IllegalArgumentException.class) + public void testConfigSetCleaner() { + SentinelOkHttpConfig.setExtractor(null); + } + + @Test(expected = IllegalArgumentException.class) + public void testConfigSetFallback() { + SentinelOkHttpConfig.setFallback(null); + } +} diff --git a/sentinel-adapter/sentinel-okhttp-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/okhttp/extractor/OkHttpResourceExtractorTest.java b/sentinel-adapter/sentinel-okhttp-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/okhttp/extractor/OkHttpResourceExtractorTest.java new file mode 100644 index 00000000..c414dad9 --- /dev/null +++ b/sentinel-adapter/sentinel-okhttp-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/okhttp/extractor/OkHttpResourceExtractorTest.java @@ -0,0 +1,61 @@ +/* + * Copyright 1999-2020 Alibaba Group Holding Ltd. + * + * 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.csp.sentinel.adapter.okhttp.extractor; + +import com.alibaba.csp.sentinel.adapter.okhttp.config.SentinelOkHttpConfig; +import okhttp3.Connection; +import okhttp3.Request; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * @author zhaoyuguang + */ +public class OkHttpResourceExtractorTest { + + @Test + public void testDefaultOkHttpResourceExtractor() { + OkHttpResourceExtractor extractor = new DefaultOkHttpResourceExtractor(); + String url = "http://localhost:8083/okhttp/back"; + Request request = new Request.Builder() + .url(url) + .build(); + extractor.extract(url, request, null); + System.out.println(extractor.extract(url, request, null)); + assertEquals("GET:"+url, extractor.extract(url, request, null)); + } + + @Test + public void testCustomizeOkHttpUrlCleaner() { + OkHttpResourceExtractor extractor = new OkHttpResourceExtractor() { + @Override + public String extract(String url, Request request, Connection connection) { + String regex = "/okhttp/back/"; + if (url.contains(regex)) { + url = url.substring(0, url.indexOf(regex) + regex.length()) + "{id}"; + } + return request.method() + ":" + url; + } + }; + String url = "http://localhost:8083/okhttp/back/abc"; + Request request = new Request.Builder() + .url(url) + .build(); + extractor.extract(url, request, null); + assertEquals("GET:http://localhost:8083/okhttp/back/{id}", extractor.extract(url, request, null)); + } +} \ No newline at end of file diff --git a/sentinel-adapter/sentinel-okhttp-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/okhttp/fallback/OkHttpFallbackTest.java b/sentinel-adapter/sentinel-okhttp-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/okhttp/fallback/OkHttpFallbackTest.java new file mode 100644 index 00000000..f3552753 --- /dev/null +++ b/sentinel-adapter/sentinel-okhttp-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/okhttp/fallback/OkHttpFallbackTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 1999-2020 Alibaba Group Holding Ltd. + * + * 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.csp.sentinel.adapter.okhttp.fallback; + +import com.alibaba.csp.sentinel.slots.block.BlockException; +import com.alibaba.csp.sentinel.slots.block.SentinelRpcException; +import com.alibaba.csp.sentinel.slots.block.flow.FlowException; +import org.junit.Test; + +/** + * @author zhaoyuguang + */ +public class OkHttpFallbackTest { + + @Test(expected = SentinelRpcException.class) + public void testDefaultOkHttpFallback() { + BlockException e = new FlowException("xxx"); + OkHttpFallback fallback = new DefaultOkHttpFallback(); + fallback.handle(null, null, e); + } +} diff --git a/sentinel-demo/pom.xml b/sentinel-demo/pom.xml index a5465da0..65076415 100755 --- a/sentinel-demo/pom.xml +++ b/sentinel-demo/pom.xml @@ -39,6 +39,7 @@ sentinel-demo-spring-webmvc sentinel-demo-zuul2-gateway sentinel-demo-log-logback + sentinel-demo-okhttp sentinel-demo-jax-rs diff --git a/sentinel-demo/sentinel-demo-okhttp/pom.xml b/sentinel-demo/sentinel-demo-okhttp/pom.xml new file mode 100644 index 00000000..25897f60 --- /dev/null +++ b/sentinel-demo/sentinel-demo-okhttp/pom.xml @@ -0,0 +1,45 @@ + + + + sentinel-demo + com.alibaba.csp + 1.8.0-SNAPSHOT + + 4.0.0 + + sentinel-demo-okhttp + + + 2.1.3.RELEASE + 3.6.0 + + + + + com.alibaba.csp + sentinel-transport-simple-http + + + com.alibaba.csp + sentinel-okhttp-adapter + ${project.version} + + + org.springframework.boot + spring-boot-starter-web + ${spring.boot.version} + + + org.springframework.boot + spring-boot-starter-test + ${spring.boot.version} + + + com.squareup.okhttp3 + okhttp + ${okhttp.version} + + + \ No newline at end of file diff --git a/sentinel-demo/sentinel-demo-okhttp/src/main/java/com/alibaba/csp/sentinel/demo/okhttp/OkHttpDemoApplication.java b/sentinel-demo/sentinel-demo-okhttp/src/main/java/com/alibaba/csp/sentinel/demo/okhttp/OkHttpDemoApplication.java new file mode 100644 index 00000000..182a62a8 --- /dev/null +++ b/sentinel-demo/sentinel-demo-okhttp/src/main/java/com/alibaba/csp/sentinel/demo/okhttp/OkHttpDemoApplication.java @@ -0,0 +1,49 @@ +/* + * Copyright 1999-2020 Alibaba Group Holding Ltd. + * + * 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.csp.sentinel.demo.okhttp; + +import com.alibaba.csp.sentinel.adapter.okhttp.config.SentinelOkHttpConfig; +import com.alibaba.csp.sentinel.adapter.okhttp.extractor.OkHttpResourceExtractor; +import okhttp3.Connection; +import okhttp3.Request; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * @author zhaoyuguang + */ +@SpringBootApplication +public class OkHttpDemoApplication implements CommandLineRunner { + + public static void main(String[] args) { + SpringApplication.run(OkHttpDemoApplication.class); + } + + @Override + public void run(String... args) { + SentinelOkHttpConfig.setExtractor(new OkHttpResourceExtractor() { + @Override + public String extract(String url, Request request, Connection connection) { + String regex = "/okhttp/back/"; + if (url.contains(regex)) { + url = url.substring(0, url.indexOf(regex) + regex.length()) + "{id}"; + } + return request.method() + ":" + url; + } + }); + } +} \ No newline at end of file diff --git a/sentinel-demo/sentinel-demo-okhttp/src/main/java/com/alibaba/csp/sentinel/demo/okhttp/controller/OkHttpTestController.java b/sentinel-demo/sentinel-demo-okhttp/src/main/java/com/alibaba/csp/sentinel/demo/okhttp/controller/OkHttpTestController.java new file mode 100644 index 00000000..a0da1bac --- /dev/null +++ b/sentinel-demo/sentinel-demo-okhttp/src/main/java/com/alibaba/csp/sentinel/demo/okhttp/controller/OkHttpTestController.java @@ -0,0 +1,68 @@ +/* + * Copyright 1999-2020 Alibaba Group Holding Ltd. + * + * 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.csp.sentinel.demo.okhttp.controller; + +import com.alibaba.csp.sentinel.adapter.okhttp.SentinelOkHttpInterceptor; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.io.IOException; + +/** + * @author zhaoyuguang + */ +@RestController +public class OkHttpTestController { + + @Value("${server.port}") + private Integer port; + + @RequestMapping("/okhttp/back") + public String back() { + return "Welcome Back!"; + } + + @RequestMapping("/okhttp/back/{id}") + public String back(@PathVariable String id) { + return "Welcome Back! " + id; + } + + @RequestMapping("/okhttp/testcase/{id}") + public String testcase(@PathVariable String id) throws Exception { + return getRemoteString(id); + } + + @RequestMapping("/okhttp/testcase") + public String testcase() throws Exception { + return getRemoteString(null); + } + + private String getRemoteString(String id) throws IOException { + OkHttpClient client = new OkHttpClient.Builder() + .addInterceptor(new SentinelOkHttpInterceptor()) + .build(); + Request request = new Request.Builder() + .url("http://localhost:" + port + "/okhttp/back" + (id == null ? "" : "/" + id)) + .build(); + Response response = client.newCall(request).execute(); + return response.body().string(); + } +} \ No newline at end of file diff --git a/sentinel-demo/sentinel-demo-okhttp/src/main/resources/application.properties b/sentinel-demo/sentinel-demo-okhttp/src/main/resources/application.properties new file mode 100644 index 00000000..973e6c25 --- /dev/null +++ b/sentinel-demo/sentinel-demo-okhttp/src/main/resources/application.properties @@ -0,0 +1,2 @@ +spring.application.name=sentinel-demo-okhttp +server.port=8085 \ No newline at end of file