From 1fa15da598abb6688a9c75ebe9f4f89cc77bedff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E7=A6=B9=E5=85=89?= Date: Wed, 6 May 2020 10:17:08 +0800 Subject: [PATCH 1/5] wip --- sentinel-adapter/pom.xml | 1 + .../pom.xml | 57 ++++++++++ .../SentinelApacheHttpClientBuilder.java | 39 +++++++ .../SentinelApacheHttpRequestInterceptor.java | 46 ++++++++ ...SentinelApacheHttpResponseInterceptor.java | 40 +++++++ .../cleaner/ApacheHttpClientUrlCleaner.java | 27 +++++ .../DefaultApacheHttpClientUrlCleaner.java | 30 +++++ .../SentinelApacheHttpClientConfig.java | 60 ++++++++++ ...ntinelApacheHttpClientHandleException.java | 24 ++++ .../fallback/ApacheHttpClientFallback.java | 17 +++ .../DefaultApacheHttpClientFallback.java | 20 ++++ .../adapter/apache/httpclient/AAA.java | 8 ++ .../ApacheHttpClientUrlCleanerTest.java | 55 +++++++++ sentinel-demo/pom.xml | 1 + .../sentinel-demo-apache-httpclient/pom.xml | 57 ++++++++++ .../ApacheHttpClientDemoApplication.java | 39 +++++++ .../ApacheHttpClientTestController.java | 106 ++++++++++++++++++ .../src/main/resources/application.properties | 2 + 18 files changed, 629 insertions(+) create mode 100644 sentinel-adapter/sentinel-apache-httpclient-adapter/pom.xml create mode 100644 sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/SentinelApacheHttpClientBuilder.java create mode 100644 sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/SentinelApacheHttpRequestInterceptor.java create mode 100644 sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/SentinelApacheHttpResponseInterceptor.java create mode 100644 sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/cleaner/ApacheHttpClientUrlCleaner.java create mode 100644 sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/cleaner/DefaultApacheHttpClientUrlCleaner.java create mode 100644 sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/config/SentinelApacheHttpClientConfig.java create mode 100644 sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/exception/SentinelApacheHttpClientHandleException.java create mode 100644 sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/fallback/ApacheHttpClientFallback.java create mode 100644 sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/fallback/DefaultApacheHttpClientFallback.java create mode 100644 sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/AAA.java create mode 100644 sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/cleaner/ApacheHttpClientUrlCleanerTest.java create mode 100644 sentinel-demo/sentinel-demo-apache-httpclient/pom.xml create mode 100644 sentinel-demo/sentinel-demo-apache-httpclient/src/main/java/com/alibaba/csp/sentinel/demo/apache/httpclient/ApacheHttpClientDemoApplication.java create mode 100644 sentinel-demo/sentinel-demo-apache-httpclient/src/main/java/com/alibaba/csp/sentinel/demo/apache/httpclient/controller/ApacheHttpClientTestController.java create mode 100644 sentinel-demo/sentinel-demo-apache-httpclient/src/main/resources/application.properties diff --git a/sentinel-adapter/pom.xml b/sentinel-adapter/pom.xml index a8ef8810e7..fda5567e76 100755 --- a/sentinel-adapter/pom.xml +++ b/sentinel-adapter/pom.xml @@ -18,6 +18,7 @@ sentinel-web-servlet sentinel-dubbo-adapter sentinel-apache-dubbo-adapter + sentinel-apache-httpclient-adapter sentinel-sofa-rpc-adapter sentinel-grpc-adapter sentinel-zuul-adapter diff --git a/sentinel-adapter/sentinel-apache-httpclient-adapter/pom.xml b/sentinel-adapter/sentinel-apache-httpclient-adapter/pom.xml new file mode 100644 index 0000000000..d5be725457 --- /dev/null +++ b/sentinel-adapter/sentinel-apache-httpclient-adapter/pom.xml @@ -0,0 +1,57 @@ + + + + sentinel-adapter + com.alibaba.csp + 1.8.0-SNAPSHOT + + 4.0.0 + + sentinel-apache-httpclient-adapter + jar + + + 1.8 + 1.8 + 4.5.6 + 4.1.4 + + + + + com.alibaba.csp + sentinel-core + + + org.apache.httpcomponents + httpclient + ${apache.httpclient.version} + provided + + + org.apache.httpcomponents + httpasyncclient + ${apache.httpasyncclient.version} + provided + + + + junit + junit + test + + + + org.mockito + mockito-core + test + + + com.alibaba + fastjson + test + + + \ No newline at end of file diff --git a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/SentinelApacheHttpClientBuilder.java b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/SentinelApacheHttpClientBuilder.java new file mode 100644 index 0000000000..62ffa3b06a --- /dev/null +++ b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/SentinelApacheHttpClientBuilder.java @@ -0,0 +1,39 @@ +/* + * Copyright 1999-2019 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 + * + * https://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.apache.httpclient; + +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.impl.nio.client.HttpAsyncClientBuilder; +import org.apache.http.impl.nio.client.HttpAsyncClients; + +/** + * @author zhaoyuguang + */ +public class SentinelApacheHttpClientBuilder { + + public static HttpClientBuilder httpClientBuilder() { + return HttpClients.custom() + .addInterceptorFirst(new SentinelApacheHttpRequestInterceptor()) + .addInterceptorFirst(new SentinelApacheHttpResponseInterceptor()); + } + + public static HttpAsyncClientBuilder httpAsyncClientBuilder() { + return HttpAsyncClients.custom() + .addInterceptorFirst(new SentinelApacheHttpRequestInterceptor()) + .addInterceptorFirst(new SentinelApacheHttpResponseInterceptor()); + } +} diff --git a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/SentinelApacheHttpRequestInterceptor.java b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/SentinelApacheHttpRequestInterceptor.java new file mode 100644 index 0000000000..cf7a4fa158 --- /dev/null +++ b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/SentinelApacheHttpRequestInterceptor.java @@ -0,0 +1,46 @@ +/* + * Copyright 1999-2019 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 + * + * https://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.apache.httpclient; + +import com.alibaba.csp.sentinel.Entry; +import com.alibaba.csp.sentinel.EntryType; +import com.alibaba.csp.sentinel.ResourceTypeConstants; +import com.alibaba.csp.sentinel.SphU; +import com.alibaba.csp.sentinel.adapter.apache.httpclient.config.SentinelApacheHttpClientConfig; +import com.alibaba.csp.sentinel.slots.block.BlockException; +import org.apache.http.HttpException; +import org.apache.http.HttpRequest; +import org.apache.http.HttpRequestInterceptor; +import org.apache.http.protocol.HttpContext; + +import java.io.IOException; + +/** + * @author zhaoyuguang + */ +public class SentinelApacheHttpRequestInterceptor implements HttpRequestInterceptor { + + @Override + public void process(HttpRequest request, HttpContext context) throws HttpException, IOException { + try { + String name = SentinelApacheHttpClientConfig.getCleaner().clean(request, context); + Entry method = SphU.entry(name, ResourceTypeConstants.COMMON_WEB, EntryType.OUT); + context.setAttribute(SentinelApacheHttpClientConfig.getAttributeName(), method); + } catch (BlockException e) { + SentinelApacheHttpClientConfig.getFallback().handle(request, context, e); + } + } +} diff --git a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/SentinelApacheHttpResponseInterceptor.java b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/SentinelApacheHttpResponseInterceptor.java new file mode 100644 index 0000000000..c93d483cc6 --- /dev/null +++ b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/SentinelApacheHttpResponseInterceptor.java @@ -0,0 +1,40 @@ +/* + * Copyright 1999-2019 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 + * + * https://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.apache.httpclient; + +import com.alibaba.csp.sentinel.Entry; +import com.alibaba.csp.sentinel.adapter.apache.httpclient.config.SentinelApacheHttpClientConfig; +import org.apache.http.HttpException; +import org.apache.http.HttpResponse; +import org.apache.http.HttpResponseInterceptor; +import org.apache.http.protocol.HttpContext; + +import java.io.IOException; + +/** + * @author zhaoyuguang + */ +public class SentinelApacheHttpResponseInterceptor implements HttpResponseInterceptor { + + @Override + public void process(HttpResponse response, HttpContext context) throws HttpException, IOException { + Entry entry = ((Entry) context.getAttribute(SentinelApacheHttpClientConfig.getAttributeName())); + if (entry != null) { + entry.close(); + context.removeAttribute(SentinelApacheHttpClientConfig.getAttributeName()); + } + } +} diff --git a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/cleaner/ApacheHttpClientUrlCleaner.java b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/cleaner/ApacheHttpClientUrlCleaner.java new file mode 100644 index 0000000000..1eabdf36b0 --- /dev/null +++ b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/cleaner/ApacheHttpClientUrlCleaner.java @@ -0,0 +1,27 @@ +/* + * Copyright 1999-2019 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 + * + * https://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.apache.httpclient.cleaner; + +import org.apache.http.HttpRequest; +import org.apache.http.protocol.HttpContext; + +/** + * @author zhaoyuguang + */ +public interface ApacheHttpClientUrlCleaner { + + String clean(HttpRequest request, HttpContext context); +} diff --git a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/cleaner/DefaultApacheHttpClientUrlCleaner.java b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/cleaner/DefaultApacheHttpClientUrlCleaner.java new file mode 100644 index 0000000000..252cb2e281 --- /dev/null +++ b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/cleaner/DefaultApacheHttpClientUrlCleaner.java @@ -0,0 +1,30 @@ +/* + * Copyright 1999-2019 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 + * + * https://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.apache.httpclient.cleaner; + +import org.apache.http.HttpRequest; +import org.apache.http.protocol.HttpContext; + +/** + * @author zhaoyuguang + */ +public class DefaultApacheHttpClientUrlCleaner implements ApacheHttpClientUrlCleaner { + + @Override + public String clean(HttpRequest request, HttpContext context) { + return request.getRequestLine().getMethod() + ":" + request.getRequestLine().getUri(); + } +} diff --git a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/config/SentinelApacheHttpClientConfig.java b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/config/SentinelApacheHttpClientConfig.java new file mode 100644 index 0000000000..1a2154d27f --- /dev/null +++ b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/config/SentinelApacheHttpClientConfig.java @@ -0,0 +1,60 @@ +/* + * Copyright 1999-2019 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 + * + * https://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.apache.httpclient.config; + +import com.alibaba.csp.sentinel.adapter.apache.httpclient.cleaner.ApacheHttpClientUrlCleaner; +import com.alibaba.csp.sentinel.adapter.apache.httpclient.cleaner.DefaultApacheHttpClientUrlCleaner; +import com.alibaba.csp.sentinel.adapter.apache.httpclient.fallback.ApacheHttpClientFallback; +import com.alibaba.csp.sentinel.adapter.apache.httpclient.fallback.DefaultApacheHttpClientFallback; +import com.alibaba.csp.sentinel.util.AssertUtil; +import org.apache.http.protocol.HttpContext; + +/** + * @author zhaoyuguang + */ +public final class SentinelApacheHttpClientConfig { + + private static volatile String attributeName = HttpContext.RESERVED_PREFIX + "sentinel_apache_httpclient_entry_attr"; + private static volatile ApacheHttpClientUrlCleaner cleaner = new DefaultApacheHttpClientUrlCleaner(); + private static volatile ApacheHttpClientFallback fallback = new DefaultApacheHttpClientFallback(); + + public static String getAttributeName() { + return attributeName; + } + + public static void setAttributeName(String attributeName) { + AssertUtil.notNull(attributeName, "attributeName cannot be null"); + SentinelApacheHttpClientConfig.attributeName = attributeName; + } + + public static ApacheHttpClientUrlCleaner getCleaner() { + return cleaner; + } + + public static void setCleaner(ApacheHttpClientUrlCleaner cleaner) { + AssertUtil.notNull(cleaner, "cleaner cannot be null"); + SentinelApacheHttpClientConfig.cleaner = cleaner; + } + + public static ApacheHttpClientFallback getFallback() { + return fallback; + } + + public static void setFallback(ApacheHttpClientFallback fallback) { + AssertUtil.notNull(fallback, "fallback cannot be null"); + SentinelApacheHttpClientConfig.fallback = fallback; + } +} diff --git a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/exception/SentinelApacheHttpClientHandleException.java b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/exception/SentinelApacheHttpClientHandleException.java new file mode 100644 index 0000000000..b98aeabe7d --- /dev/null +++ b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/exception/SentinelApacheHttpClientHandleException.java @@ -0,0 +1,24 @@ +package com.alibaba.csp.sentinel.adapter.apache.httpclient.exception; + +import com.alibaba.csp.sentinel.Entry; +import com.alibaba.csp.sentinel.Tracer; +import com.alibaba.csp.sentinel.adapter.apache.httpclient.config.SentinelApacheHttpClientConfig; +import com.alibaba.csp.sentinel.util.AssertUtil; +import org.apache.http.protocol.HttpContext; + +/** + * @author zhaoyuguang + */ + +public class SentinelApacheHttpClientHandleException { + + public static void handle(HttpContext context, Exception ex){ + AssertUtil.notNull(context, "context cannot be null"); + Entry entry = ((Entry) context.getAttribute(SentinelApacheHttpClientConfig.getAttributeName())); + if (entry != null) { + Tracer.traceEntry(ex, entry); + entry.close(); + context.removeAttribute(SentinelApacheHttpClientConfig.getAttributeName()); + } + } +} diff --git a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/fallback/ApacheHttpClientFallback.java b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/fallback/ApacheHttpClientFallback.java new file mode 100644 index 0000000000..b60ddf77a1 --- /dev/null +++ b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/fallback/ApacheHttpClientFallback.java @@ -0,0 +1,17 @@ +package com.alibaba.csp.sentinel.adapter.apache.httpclient.fallback; + +import com.alibaba.csp.sentinel.slots.block.BlockException; +import org.apache.http.HttpException; +import org.apache.http.HttpRequest; +import org.apache.http.protocol.HttpContext; + +import java.io.IOException; + +/** + * @author zhaoyuguang + */ + +public interface ApacheHttpClientFallback { + + void handle(HttpRequest request, HttpContext context, BlockException e) throws HttpException, IOException; +} diff --git a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/fallback/DefaultApacheHttpClientFallback.java b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/fallback/DefaultApacheHttpClientFallback.java new file mode 100644 index 0000000000..2dd9910771 --- /dev/null +++ b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/fallback/DefaultApacheHttpClientFallback.java @@ -0,0 +1,20 @@ +package com.alibaba.csp.sentinel.adapter.apache.httpclient.fallback; + +import com.alibaba.csp.sentinel.slots.block.BlockException; +import org.apache.http.HttpException; +import org.apache.http.HttpRequest; +import org.apache.http.protocol.HttpContext; + +import java.io.IOException; + +/** + * @author zhaoyuguang + */ + +public class DefaultApacheHttpClientFallback implements ApacheHttpClientFallback { + + @Override + public void handle(HttpRequest request, HttpContext context, BlockException e) throws HttpException, IOException { + throw new HttpException(BlockException.class.getSimpleName()); + } +} diff --git a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/AAA.java b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/AAA.java new file mode 100644 index 0000000000..a8c5565fd4 --- /dev/null +++ b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/AAA.java @@ -0,0 +1,8 @@ +package com.alibaba.csp.sentinel.adapter.apache.httpclient; + +/** + * @author zhaoyuguang + */ + +public class AAA { +} diff --git a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/cleaner/ApacheHttpClientUrlCleanerTest.java b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/cleaner/ApacheHttpClientUrlCleanerTest.java new file mode 100644 index 0000000000..1f1babb0fc --- /dev/null +++ b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/cleaner/ApacheHttpClientUrlCleanerTest.java @@ -0,0 +1,55 @@ +/* + * Copyright 1999-2019 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 + * + * https://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.apache.httpclient.cleaner; + +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.apache.http.HttpRequest; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpRequestWrapper; +import org.apache.http.protocol.HttpContext; +import org.junit.Test; + +/** + * @author zhaoyuguang + */ +public class ApacheHttpClientUrlCleanerTest { + + @Test + public void testDefaultApacheHttpClientUrlCleaner() { + ApacheHttpClientUrlCleaner cleaner = new DefaultApacheHttpClientUrlCleaner(); + HttpGet httpGet = new HttpGet("http://localhost:8083/httpclient/back"); + cleaner.clean(httpGet, null); + System.out.println(cleaner.clean(httpGet, null)); + } + + @Test + public void testDefaultApacheHttpClientUrlCleaner2() { + ApacheHttpClientUrlCleaner cleaner = new ApacheHttpClientUrlCleaner() { + @Override + public String clean(HttpRequest request, HttpContext context) { + if (request.getRequestLine().getUri().startsWith("/httpclient/back/")) { + return request.getRequestLine().getMethod() + ":/httpclient/back/{id}"; + } + return request.getRequestLine().getMethod() + ":" + request.getRequestLine().getUri(); + } + }; + HttpGet httpGet = new HttpGet("http://localhost:8083/httpclient/back/1"); + cleaner.clean(httpGet, null); + System.out.println(cleaner.clean(httpGet, null)); + } +} diff --git a/sentinel-demo/pom.xml b/sentinel-demo/pom.xml index a5465da0c5..80da4ce684 100755 --- a/sentinel-demo/pom.xml +++ b/sentinel-demo/pom.xml @@ -32,6 +32,7 @@ sentinel-demo-command-handler sentinel-demo-spring-webflux sentinel-demo-apache-dubbo + sentinel-demo-apache-httpclient sentinel-demo-sofa-rpc sentinel-demo-spring-cloud-gateway sentinel-demo-zuul-gateway diff --git a/sentinel-demo/sentinel-demo-apache-httpclient/pom.xml b/sentinel-demo/sentinel-demo-apache-httpclient/pom.xml new file mode 100644 index 0000000000..8d20bbf16e --- /dev/null +++ b/sentinel-demo/sentinel-demo-apache-httpclient/pom.xml @@ -0,0 +1,57 @@ + + + + sentinel-demo + com.alibaba.csp + 1.8.0-SNAPSHOT + + 4.0.0 + + sentinel-demo-apache-httpclient + + + 2.1.3.RELEASE + 4.3 + + + + + com.alibaba.csp + sentinel-core + + + com.alibaba.csp + sentinel-transport-simple-http + + + com.alibaba.csp + sentinel-apache-httpclient-adapter + ${project.version} + + + org.springframework.boot + spring-boot-starter-web + ${spring.boot.version} + + + org.springframework.boot + spring-boot-starter-test + ${spring.boot.version} + + + + org.apache.httpcomponents + httpclient + 4.5.6 + + + + org.apache.httpcomponents + httpasyncclient + 4.1.4 + + + + \ No newline at end of file diff --git a/sentinel-demo/sentinel-demo-apache-httpclient/src/main/java/com/alibaba/csp/sentinel/demo/apache/httpclient/ApacheHttpClientDemoApplication.java b/sentinel-demo/sentinel-demo-apache-httpclient/src/main/java/com/alibaba/csp/sentinel/demo/apache/httpclient/ApacheHttpClientDemoApplication.java new file mode 100644 index 0000000000..24f97f2cc0 --- /dev/null +++ b/sentinel-demo/sentinel-demo-apache-httpclient/src/main/java/com/alibaba/csp/sentinel/demo/apache/httpclient/ApacheHttpClientDemoApplication.java @@ -0,0 +1,39 @@ +/* + * Copyright 1999-2019 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.apache.httpclient; + +import com.alibaba.csp.sentinel.adapter.apache.httpclient.config.SentinelApacheHttpClientConfig; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class ApacheHttpClientDemoApplication implements CommandLineRunner { + + public static void main(String[] args) { + SpringApplication.run(ApacheHttpClientDemoApplication.class); + } + + @Override + public void run(String... args) { + SentinelApacheHttpClientConfig.setCleaner((request, context) -> { + if (request.getRequestLine().getUri().startsWith("/httpclient/back/")) { + return request.getRequestLine().getMethod() + ":/httpclient/back/{id}"; + } + return request.getRequestLine().getMethod() + ":" + request.getRequestLine().getUri(); + }); + } +} diff --git a/sentinel-demo/sentinel-demo-apache-httpclient/src/main/java/com/alibaba/csp/sentinel/demo/apache/httpclient/controller/ApacheHttpClientTestController.java b/sentinel-demo/sentinel-demo-apache-httpclient/src/main/java/com/alibaba/csp/sentinel/demo/apache/httpclient/controller/ApacheHttpClientTestController.java new file mode 100644 index 0000000000..307f375e50 --- /dev/null +++ b/sentinel-demo/sentinel-demo-apache-httpclient/src/main/java/com/alibaba/csp/sentinel/demo/apache/httpclient/controller/ApacheHttpClientTestController.java @@ -0,0 +1,106 @@ +/* + * Copyright 1999-2019 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.apache.httpclient.controller; + +import com.alibaba.csp.sentinel.adapter.apache.httpclient.SentinelApacheHttpClientBuilder; +import com.alibaba.csp.sentinel.adapter.apache.httpclient.config.SentinelApacheHttpClientConfig; +import com.alibaba.csp.sentinel.adapter.apache.httpclient.exception.SentinelApacheHttpClientHandleException; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.nio.client.CloseableHttpAsyncClient; +import org.apache.http.protocol.BasicHttpContext; +import org.apache.http.protocol.HttpContext; +import org.apache.http.util.EntityUtils; +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; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; + +@RestController +public class ApacheHttpClientTestController { + + @Value("${server.port}") + private Integer port; + + @RequestMapping("/httpclient/back") + public String back() { + System.out.println("back"); + return "Welcome Back!"; + } + + @RequestMapping("/httpclient/back/{id}") + public String back(@PathVariable String id) { + System.out.println("back"); + return "Welcome Back! " + id; + } + + @RequestMapping("/httpclient/sync") + public String sync() throws Exception { + CloseableHttpClient httpclient = SentinelApacheHttpClientBuilder.httpClientBuilder().build(); + + HttpGet httpGet = new HttpGet("http://localhost:" + port + "/httpclient/back"); + return getRemoteString(httpclient, httpGet); + } + + @RequestMapping("/httpclient/sync/{id}") + public String sync(@PathVariable String id) throws Exception { + CloseableHttpClient httpclient = SentinelApacheHttpClientBuilder.httpClientBuilder().build(); + + HttpGet httpGet = new HttpGet("http://localhost:" + port + "/httpclient/back/" + id); + return getRemoteString(httpclient, httpGet); + } + + private String getRemoteString(CloseableHttpClient httpclient, HttpGet httpGet) throws IOException { + String result; + HttpContext context = new BasicHttpContext(); + CloseableHttpResponse response; + try { + response = httpclient.execute(httpGet, context); + } catch (Exception e){ + SentinelApacheHttpClientHandleException.handle(context, e); + throw e; + } + try { + HttpEntity entity = response.getEntity(); + result = EntityUtils.toString(entity, "utf-8"); + EntityUtils.consume(entity); + } finally { + response.close(); + } + httpclient.close(); + return result; + } + + @RequestMapping("/httpclient/async") + public String async() throws Exception { + CloseableHttpAsyncClient httpclient = SentinelApacheHttpClientBuilder.httpAsyncClientBuilder().build(); + httpclient.start(); + + HttpGet httpGet = new HttpGet("http://localhost:" + port + "/httpclient/back"); + Future future = httpclient.execute(httpGet, null); + HttpResponse response = future.get(100L, TimeUnit.MILLISECONDS); + httpclient.close(); + return EntityUtils.toString(response.getEntity(), "utf-8"); + } + +} diff --git a/sentinel-demo/sentinel-demo-apache-httpclient/src/main/resources/application.properties b/sentinel-demo/sentinel-demo-apache-httpclient/src/main/resources/application.properties new file mode 100644 index 0000000000..e3e4894977 --- /dev/null +++ b/sentinel-demo/sentinel-demo-apache-httpclient/src/main/resources/application.properties @@ -0,0 +1,2 @@ +spring.application.name=sentinel-demo-apache-httpclient +server.port=8083 \ No newline at end of file From acb80f7a583d0475078528564aa1c8645895f2d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E7=A6=B9=E5=85=89?= Date: Fri, 29 May 2020 18:15:33 +0800 Subject: [PATCH 2/5] fix --- .../pom.xml | 30 +++-- .../SentinelApacheHttpClientBuilder.java | 60 +++++++--- .../SentinelApacheHttpRequestInterceptor.java | 46 -------- ...SentinelApacheHttpResponseInterceptor.java | 40 ------- .../SentinelApacheHttpClientConfig.java | 33 +++--- ...ntinelApacheHttpClientHandleException.java | 24 ---- .../ApacheHttpClientResourceExtractor.java} | 13 +-- ...ultApacheHttpClientResourceExtractor.java} | 15 ++- .../fallback/ApacheHttpClientFallback.java | 20 +++- .../DefaultApacheHttpClientFallback.java | 24 +++- .../adapter/apache/httpclient/AAA.java | 8 -- .../SentinelApacheHttpClientTest.java | 107 ++++++++++++++++++ .../httpclient/app/TestApplication.java | 30 +++++ .../app/controller/TestController.java | 37 ++++++ .../ApacheHttpClientUrlCleanerTest.java | 55 --------- .../SentinelApacheHttpClientConfigTest.java | 39 +++++++ ...ApacheHttpClientResourceExtractorTest.java | 43 +++++++ .../ApacheHttpClientFallbackTest.java | 34 ++++++ .../sentinel-demo-apache-httpclient/pom.xml | 9 +- .../ApacheHttpClientDemoApplication.java | 20 +++- .../ApacheHttpClientTestController.java | 35 ++---- 21 files changed, 447 insertions(+), 275 deletions(-) delete mode 100644 sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/SentinelApacheHttpRequestInterceptor.java delete mode 100644 sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/SentinelApacheHttpResponseInterceptor.java delete mode 100644 sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/exception/SentinelApacheHttpClientHandleException.java rename sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/{cleaner/ApacheHttpClientUrlCleaner.java => extractor/ApacheHttpClientResourceExtractor.java} (60%) rename sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/{cleaner/DefaultApacheHttpClientUrlCleaner.java => extractor/DefaultApacheHttpClientResourceExtractor.java} (53%) delete mode 100644 sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/AAA.java create mode 100644 sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/SentinelApacheHttpClientTest.java create mode 100644 sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/app/TestApplication.java create mode 100644 sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/app/controller/TestController.java delete mode 100644 sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/cleaner/ApacheHttpClientUrlCleanerTest.java create mode 100644 sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/config/SentinelApacheHttpClientConfigTest.java create mode 100644 sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/extractor/ApacheHttpClientResourceExtractorTest.java create mode 100644 sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/fallback/ApacheHttpClientFallbackTest.java diff --git a/sentinel-adapter/sentinel-apache-httpclient-adapter/pom.xml b/sentinel-adapter/sentinel-apache-httpclient-adapter/pom.xml index d5be725457..3dde07bf41 100644 --- a/sentinel-adapter/sentinel-apache-httpclient-adapter/pom.xml +++ b/sentinel-adapter/sentinel-apache-httpclient-adapter/pom.xml @@ -13,10 +13,9 @@ jar - 1.8 - 1.8 4.5.6 - 4.1.4 + 2.1.3.RELEASE + 5.1.5.RELEASE @@ -30,12 +29,6 @@ ${apache.httpclient.version} provided - - org.apache.httpcomponents - httpasyncclient - ${apache.httpasyncclient.version} - provided - junit @@ -53,5 +46,24 @@ 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-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/SentinelApacheHttpClientBuilder.java b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/SentinelApacheHttpClientBuilder.java index 62ffa3b06a..e6b208462f 100644 --- a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/SentinelApacheHttpClientBuilder.java +++ b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/SentinelApacheHttpClientBuilder.java @@ -1,11 +1,11 @@ /* - * Copyright 1999-2019 Alibaba Group Holding Ltd. + * 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 * - * https://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -15,25 +15,53 @@ */ package com.alibaba.csp.sentinel.adapter.apache.httpclient; +import com.alibaba.csp.sentinel.*; +import com.alibaba.csp.sentinel.adapter.apache.httpclient.config.SentinelApacheHttpClientConfig; +import com.alibaba.csp.sentinel.slots.block.BlockException; +import com.alibaba.csp.sentinel.util.StringUtil; +import org.apache.http.HttpException; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpExecutionAware; +import org.apache.http.client.methods.HttpRequestWrapper; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.conn.routing.HttpRoute; import org.apache.http.impl.client.HttpClientBuilder; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.impl.nio.client.HttpAsyncClientBuilder; -import org.apache.http.impl.nio.client.HttpAsyncClients; +import org.apache.http.impl.execchain.ClientExecChain; + +import java.io.IOException; /** * @author zhaoyuguang */ -public class SentinelApacheHttpClientBuilder { - - public static HttpClientBuilder httpClientBuilder() { - return HttpClients.custom() - .addInterceptorFirst(new SentinelApacheHttpRequestInterceptor()) - .addInterceptorFirst(new SentinelApacheHttpResponseInterceptor()); - } +public class SentinelApacheHttpClientBuilder extends HttpClientBuilder { - public static HttpAsyncClientBuilder httpAsyncClientBuilder() { - return HttpAsyncClients.custom() - .addInterceptorFirst(new SentinelApacheHttpRequestInterceptor()) - .addInterceptorFirst(new SentinelApacheHttpResponseInterceptor()); + @Override + protected ClientExecChain decorateMainExec(final ClientExecChain mainExec) { + return new ClientExecChain() { + @Override + public CloseableHttpResponse execute(HttpRoute route, HttpRequestWrapper request, + HttpClientContext clientContext, HttpExecutionAware execAware) + throws IOException, HttpException { + Entry entry = null; + try { + String name = SentinelApacheHttpClientConfig.getExtractor().extractor(request.getMethod(), + request.getRequestLine().getUri(), request); + if (!StringUtil.isEmpty(SentinelApacheHttpClientConfig.getPrefix())) { + name = SentinelApacheHttpClientConfig.getPrefix() + name; + } + entry = SphU.entry(name, ResourceTypeConstants.COMMON_WEB, EntryType.OUT); + return mainExec.execute(route, request, clientContext, execAware); + } catch (BlockException e) { + return SentinelApacheHttpClientConfig.getFallback().handle(request, e); + } catch (Throwable t) { + Tracer.traceEntry(t, entry); + throw t; + } finally { + if (entry != null) { + entry.exit(); + } + } + } + }; } } diff --git a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/SentinelApacheHttpRequestInterceptor.java b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/SentinelApacheHttpRequestInterceptor.java deleted file mode 100644 index cf7a4fa158..0000000000 --- a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/SentinelApacheHttpRequestInterceptor.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 1999-2019 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 - * - * https://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.apache.httpclient; - -import com.alibaba.csp.sentinel.Entry; -import com.alibaba.csp.sentinel.EntryType; -import com.alibaba.csp.sentinel.ResourceTypeConstants; -import com.alibaba.csp.sentinel.SphU; -import com.alibaba.csp.sentinel.adapter.apache.httpclient.config.SentinelApacheHttpClientConfig; -import com.alibaba.csp.sentinel.slots.block.BlockException; -import org.apache.http.HttpException; -import org.apache.http.HttpRequest; -import org.apache.http.HttpRequestInterceptor; -import org.apache.http.protocol.HttpContext; - -import java.io.IOException; - -/** - * @author zhaoyuguang - */ -public class SentinelApacheHttpRequestInterceptor implements HttpRequestInterceptor { - - @Override - public void process(HttpRequest request, HttpContext context) throws HttpException, IOException { - try { - String name = SentinelApacheHttpClientConfig.getCleaner().clean(request, context); - Entry method = SphU.entry(name, ResourceTypeConstants.COMMON_WEB, EntryType.OUT); - context.setAttribute(SentinelApacheHttpClientConfig.getAttributeName(), method); - } catch (BlockException e) { - SentinelApacheHttpClientConfig.getFallback().handle(request, context, e); - } - } -} diff --git a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/SentinelApacheHttpResponseInterceptor.java b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/SentinelApacheHttpResponseInterceptor.java deleted file mode 100644 index c93d483cc6..0000000000 --- a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/SentinelApacheHttpResponseInterceptor.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 1999-2019 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 - * - * https://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.apache.httpclient; - -import com.alibaba.csp.sentinel.Entry; -import com.alibaba.csp.sentinel.adapter.apache.httpclient.config.SentinelApacheHttpClientConfig; -import org.apache.http.HttpException; -import org.apache.http.HttpResponse; -import org.apache.http.HttpResponseInterceptor; -import org.apache.http.protocol.HttpContext; - -import java.io.IOException; - -/** - * @author zhaoyuguang - */ -public class SentinelApacheHttpResponseInterceptor implements HttpResponseInterceptor { - - @Override - public void process(HttpResponse response, HttpContext context) throws HttpException, IOException { - Entry entry = ((Entry) context.getAttribute(SentinelApacheHttpClientConfig.getAttributeName())); - if (entry != null) { - entry.close(); - context.removeAttribute(SentinelApacheHttpClientConfig.getAttributeName()); - } - } -} diff --git a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/config/SentinelApacheHttpClientConfig.java b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/config/SentinelApacheHttpClientConfig.java index 1a2154d27f..f470fc4afe 100644 --- a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/config/SentinelApacheHttpClientConfig.java +++ b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/config/SentinelApacheHttpClientConfig.java @@ -1,11 +1,11 @@ /* - * Copyright 1999-2019 Alibaba Group Holding Ltd. + * 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 * - * https://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -15,38 +15,37 @@ */ package com.alibaba.csp.sentinel.adapter.apache.httpclient.config; -import com.alibaba.csp.sentinel.adapter.apache.httpclient.cleaner.ApacheHttpClientUrlCleaner; -import com.alibaba.csp.sentinel.adapter.apache.httpclient.cleaner.DefaultApacheHttpClientUrlCleaner; +import com.alibaba.csp.sentinel.adapter.apache.httpclient.extractor.ApacheHttpClientResourceExtractor; +import com.alibaba.csp.sentinel.adapter.apache.httpclient.extractor.DefaultApacheHttpClientResourceExtractor; import com.alibaba.csp.sentinel.adapter.apache.httpclient.fallback.ApacheHttpClientFallback; import com.alibaba.csp.sentinel.adapter.apache.httpclient.fallback.DefaultApacheHttpClientFallback; import com.alibaba.csp.sentinel.util.AssertUtil; -import org.apache.http.protocol.HttpContext; /** * @author zhaoyuguang */ public final class SentinelApacheHttpClientConfig { - private static volatile String attributeName = HttpContext.RESERVED_PREFIX + "sentinel_apache_httpclient_entry_attr"; - private static volatile ApacheHttpClientUrlCleaner cleaner = new DefaultApacheHttpClientUrlCleaner(); + private static volatile String prefix = "httpclient:"; + private static volatile ApacheHttpClientResourceExtractor extractor = new DefaultApacheHttpClientResourceExtractor(); private static volatile ApacheHttpClientFallback fallback = new DefaultApacheHttpClientFallback(); - public static String getAttributeName() { - return attributeName; + public static String getPrefix() { + return prefix; } - public static void setAttributeName(String attributeName) { - AssertUtil.notNull(attributeName, "attributeName cannot be null"); - SentinelApacheHttpClientConfig.attributeName = attributeName; + public static void setPrefix(String prefix) { + AssertUtil.notNull(prefix, "prefix cannot be null"); + SentinelApacheHttpClientConfig.prefix = prefix; } - public static ApacheHttpClientUrlCleaner getCleaner() { - return cleaner; + public static ApacheHttpClientResourceExtractor getExtractor() { + return extractor; } - public static void setCleaner(ApacheHttpClientUrlCleaner cleaner) { - AssertUtil.notNull(cleaner, "cleaner cannot be null"); - SentinelApacheHttpClientConfig.cleaner = cleaner; + public static void setExtractor(ApacheHttpClientResourceExtractor extractor) { + AssertUtil.notNull(extractor, "extractor cannot be null"); + SentinelApacheHttpClientConfig.extractor = extractor; } public static ApacheHttpClientFallback getFallback() { diff --git a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/exception/SentinelApacheHttpClientHandleException.java b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/exception/SentinelApacheHttpClientHandleException.java deleted file mode 100644 index b98aeabe7d..0000000000 --- a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/exception/SentinelApacheHttpClientHandleException.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.alibaba.csp.sentinel.adapter.apache.httpclient.exception; - -import com.alibaba.csp.sentinel.Entry; -import com.alibaba.csp.sentinel.Tracer; -import com.alibaba.csp.sentinel.adapter.apache.httpclient.config.SentinelApacheHttpClientConfig; -import com.alibaba.csp.sentinel.util.AssertUtil; -import org.apache.http.protocol.HttpContext; - -/** - * @author zhaoyuguang - */ - -public class SentinelApacheHttpClientHandleException { - - public static void handle(HttpContext context, Exception ex){ - AssertUtil.notNull(context, "context cannot be null"); - Entry entry = ((Entry) context.getAttribute(SentinelApacheHttpClientConfig.getAttributeName())); - if (entry != null) { - Tracer.traceEntry(ex, entry); - entry.close(); - context.removeAttribute(SentinelApacheHttpClientConfig.getAttributeName()); - } - } -} diff --git a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/cleaner/ApacheHttpClientUrlCleaner.java b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/extractor/ApacheHttpClientResourceExtractor.java similarity index 60% rename from sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/cleaner/ApacheHttpClientUrlCleaner.java rename to sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/extractor/ApacheHttpClientResourceExtractor.java index 1eabdf36b0..710e9e9655 100644 --- a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/cleaner/ApacheHttpClientUrlCleaner.java +++ b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/extractor/ApacheHttpClientResourceExtractor.java @@ -1,11 +1,11 @@ /* - * Copyright 1999-2019 Alibaba Group Holding Ltd. + * 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 * - * https://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -13,15 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.alibaba.csp.sentinel.adapter.apache.httpclient.cleaner; +package com.alibaba.csp.sentinel.adapter.apache.httpclient.extractor; -import org.apache.http.HttpRequest; -import org.apache.http.protocol.HttpContext; +import org.apache.http.client.methods.HttpRequestWrapper; /** * @author zhaoyuguang */ -public interface ApacheHttpClientUrlCleaner { +public interface ApacheHttpClientResourceExtractor { - String clean(HttpRequest request, HttpContext context); + String extractor(String method, String uri, HttpRequestWrapper request); } diff --git a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/cleaner/DefaultApacheHttpClientUrlCleaner.java b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/extractor/DefaultApacheHttpClientResourceExtractor.java similarity index 53% rename from sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/cleaner/DefaultApacheHttpClientUrlCleaner.java rename to sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/extractor/DefaultApacheHttpClientResourceExtractor.java index 252cb2e281..24cbc08698 100644 --- a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/cleaner/DefaultApacheHttpClientUrlCleaner.java +++ b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/extractor/DefaultApacheHttpClientResourceExtractor.java @@ -1,11 +1,11 @@ /* - * Copyright 1999-2019 Alibaba Group Holding Ltd. + * 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 * - * https://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -13,18 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.alibaba.csp.sentinel.adapter.apache.httpclient.cleaner; +package com.alibaba.csp.sentinel.adapter.apache.httpclient.extractor; -import org.apache.http.HttpRequest; -import org.apache.http.protocol.HttpContext; +import org.apache.http.client.methods.HttpRequestWrapper; /** * @author zhaoyuguang */ -public class DefaultApacheHttpClientUrlCleaner implements ApacheHttpClientUrlCleaner { +public class DefaultApacheHttpClientResourceExtractor implements ApacheHttpClientResourceExtractor { @Override - public String clean(HttpRequest request, HttpContext context) { - return request.getRequestLine().getMethod() + ":" + request.getRequestLine().getUri(); + public String extractor(String method, String uri, HttpRequestWrapper request) { + return method + ":" + uri; } } diff --git a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/fallback/ApacheHttpClientFallback.java b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/fallback/ApacheHttpClientFallback.java index b60ddf77a1..f670eca8a5 100644 --- a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/fallback/ApacheHttpClientFallback.java +++ b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/fallback/ApacheHttpClientFallback.java @@ -1,8 +1,25 @@ +/* + * 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.apache.httpclient.fallback; import com.alibaba.csp.sentinel.slots.block.BlockException; import org.apache.http.HttpException; import org.apache.http.HttpRequest; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpRequestWrapper; import org.apache.http.protocol.HttpContext; import java.io.IOException; @@ -10,8 +27,7 @@ /** * @author zhaoyuguang */ - public interface ApacheHttpClientFallback { - void handle(HttpRequest request, HttpContext context, BlockException e) throws HttpException, IOException; + CloseableHttpResponse handle(HttpRequestWrapper request, BlockException e); } diff --git a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/fallback/DefaultApacheHttpClientFallback.java b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/fallback/DefaultApacheHttpClientFallback.java index 2dd9910771..81994bfc00 100644 --- a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/fallback/DefaultApacheHttpClientFallback.java +++ b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/fallback/DefaultApacheHttpClientFallback.java @@ -1,8 +1,26 @@ +/* + * 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.apache.httpclient.fallback; import com.alibaba.csp.sentinel.slots.block.BlockException; +import com.alibaba.csp.sentinel.slots.block.SentinelRpcException; import org.apache.http.HttpException; import org.apache.http.HttpRequest; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpRequestWrapper; import org.apache.http.protocol.HttpContext; import java.io.IOException; @@ -10,11 +28,11 @@ /** * @author zhaoyuguang */ - public class DefaultApacheHttpClientFallback implements ApacheHttpClientFallback { @Override - public void handle(HttpRequest request, HttpContext context, BlockException e) throws HttpException, IOException { - throw new HttpException(BlockException.class.getSimpleName()); + public CloseableHttpResponse handle(HttpRequestWrapper request, BlockException e) { + // Just wrap and throw the exception. + throw new SentinelRpcException(e); } } diff --git a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/AAA.java b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/AAA.java deleted file mode 100644 index a8c5565fd4..0000000000 --- a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/AAA.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.alibaba.csp.sentinel.adapter.apache.httpclient; - -/** - * @author zhaoyuguang - */ - -public class AAA { -} diff --git a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/SentinelApacheHttpClientTest.java b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/SentinelApacheHttpClientTest.java new file mode 100644 index 0000000000..e24b8581c0 --- /dev/null +++ b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/SentinelApacheHttpClientTest.java @@ -0,0 +1,107 @@ +/* + * 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.apache.httpclient; + +import com.alibaba.csp.sentinel.Constants; +import com.alibaba.csp.sentinel.adapter.apache.httpclient.app.TestApplication; +import com.alibaba.csp.sentinel.adapter.apache.httpclient.config.SentinelApacheHttpClientConfig; +import com.alibaba.csp.sentinel.adapter.apache.httpclient.extractor.ApacheHttpClientResourceExtractor; +import com.alibaba.csp.sentinel.node.ClusterNode; +import com.alibaba.csp.sentinel.slots.clusterbuilder.ClusterBuilderSlot; +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpRequestWrapper; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.protocol.BasicHttpContext; +import org.apache.http.protocol.HttpContext; +import org.apache.http.util.EntityUtils; +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 java.io.IOException; + +import static org.junit.Assert.assertNotNull; + +/** + * @author zhaoyuguang + */ +@RunWith(SpringRunner.class) +@SpringBootTest(classes = TestApplication.class, + webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT, + properties = { + "server.port=8084" + }) +public class SentinelApacheHttpClientTest { + + @Value("${server.port}") + private Integer port; + + @Test + public void testSentinelOkHttpInterceptor0() throws Exception { + + CloseableHttpClient httpclient = new SentinelApacheHttpClientBuilder().build(); + + HttpGet httpGet = new HttpGet("http://localhost:" + port + "/httpclient/back"); + System.out.println(getRemoteString(httpclient, httpGet)); + ClusterNode cn = ClusterBuilderSlot.getClusterNode("httpclient:GET:/httpclient/back"); + assertNotNull(cn); + Constants.ROOT.removeChildList(); + ClusterBuilderSlot.getClusterNodeMap().clear(); + } + + @Test + public void testSentinelOkHttpInterceptor1() throws Exception { + SentinelApacheHttpClientConfig.setExtractor(new ApacheHttpClientResourceExtractor() { + + @Override + public String extractor(String method, String uri, HttpRequestWrapper request) { + String regex = "/httpclient/back/"; + if (uri.contains(regex)) { + uri = uri.substring(0, uri.indexOf(regex) + regex.length()) + "{id}"; + } + return method + ":" + uri; + } + }); + CloseableHttpClient httpclient = new SentinelApacheHttpClientBuilder().build(); + + HttpGet httpGet = new HttpGet("http://localhost:" + port + "/httpclient/back/1"); + System.out.println(getRemoteString(httpclient, httpGet)); + ClusterNode cn = ClusterBuilderSlot.getClusterNode("httpclient:GET:/httpclient/back/{id}"); + assertNotNull(cn); + Constants.ROOT.removeChildList(); + ClusterBuilderSlot.getClusterNodeMap().clear(); + } + + private String getRemoteString(CloseableHttpClient httpclient, HttpGet httpGet) throws IOException { + String result; + HttpContext context = new BasicHttpContext(); + CloseableHttpResponse response; + response = httpclient.execute(httpGet, context); + try { + HttpEntity entity = response.getEntity(); + result = EntityUtils.toString(entity, "utf-8"); + EntityUtils.consume(entity); + } finally { + response.close(); + } + httpclient.close(); + return result; + } +} diff --git a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/app/TestApplication.java b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/app/TestApplication.java new file mode 100644 index 0000000000..e073dda5ed --- /dev/null +++ b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/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.apache.httpclient.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-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/app/controller/TestController.java b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/app/controller/TestController.java new file mode 100644 index 0000000000..2ae4275f05 --- /dev/null +++ b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/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.apache.httpclient.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("/httpclient/back") + public String back() { + return "Welcome Back!"; + } + + @RequestMapping("/httpclient/back/{id}") + public String back(@PathVariable String id) { + return "Welcome Back! " + id; + } +} \ No newline at end of file diff --git a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/cleaner/ApacheHttpClientUrlCleanerTest.java b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/cleaner/ApacheHttpClientUrlCleanerTest.java deleted file mode 100644 index 1f1babb0fc..0000000000 --- a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/cleaner/ApacheHttpClientUrlCleanerTest.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 1999-2019 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 - * - * https://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.apache.httpclient.cleaner; - -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.apache.http.HttpRequest; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpRequestWrapper; -import org.apache.http.protocol.HttpContext; -import org.junit.Test; - -/** - * @author zhaoyuguang - */ -public class ApacheHttpClientUrlCleanerTest { - - @Test - public void testDefaultApacheHttpClientUrlCleaner() { - ApacheHttpClientUrlCleaner cleaner = new DefaultApacheHttpClientUrlCleaner(); - HttpGet httpGet = new HttpGet("http://localhost:8083/httpclient/back"); - cleaner.clean(httpGet, null); - System.out.println(cleaner.clean(httpGet, null)); - } - - @Test - public void testDefaultApacheHttpClientUrlCleaner2() { - ApacheHttpClientUrlCleaner cleaner = new ApacheHttpClientUrlCleaner() { - @Override - public String clean(HttpRequest request, HttpContext context) { - if (request.getRequestLine().getUri().startsWith("/httpclient/back/")) { - return request.getRequestLine().getMethod() + ":/httpclient/back/{id}"; - } - return request.getRequestLine().getMethod() + ":" + request.getRequestLine().getUri(); - } - }; - HttpGet httpGet = new HttpGet("http://localhost:8083/httpclient/back/1"); - cleaner.clean(httpGet, null); - System.out.println(cleaner.clean(httpGet, null)); - } -} diff --git a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/config/SentinelApacheHttpClientConfigTest.java b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/config/SentinelApacheHttpClientConfigTest.java new file mode 100644 index 0000000000..f5141308d4 --- /dev/null +++ b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/config/SentinelApacheHttpClientConfigTest.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.apache.httpclient.config; + +import org.junit.Test; + +/** + * @author zhaoyuguang + */ +public class SentinelApacheHttpClientConfigTest { + + @Test(expected = IllegalArgumentException.class) + public void testConfigSetPrefix() { + SentinelApacheHttpClientConfig.setPrefix(null); + } + + @Test(expected = IllegalArgumentException.class) + public void testConfigSetCleaner() { + SentinelApacheHttpClientConfig.setExtractor(null); + } + + @Test(expected = IllegalArgumentException.class) + public void testConfigSetFallback() { + SentinelApacheHttpClientConfig.setFallback(null); + } +} diff --git a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/extractor/ApacheHttpClientResourceExtractorTest.java b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/extractor/ApacheHttpClientResourceExtractorTest.java new file mode 100644 index 0000000000..b18bac076d --- /dev/null +++ b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/extractor/ApacheHttpClientResourceExtractorTest.java @@ -0,0 +1,43 @@ +/* + * 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.apache.httpclient.extractor; + +import org.apache.http.client.methods.HttpRequestWrapper; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * @author zhaoyuguang + */ +public class ApacheHttpClientResourceExtractorTest { + + @Test + public void testDefaultOkHttpResourceExtractor() { + ApacheHttpClientResourceExtractor extractor = new ApacheHttpClientResourceExtractor() { + @Override + public String extractor(String method, String uri, HttpRequestWrapper request) { + String regex = "/httpclient/back/"; + if (uri.contains(regex)) { + uri = uri.substring(0, uri.indexOf(regex) + regex.length()) + "{id}"; + } + return method + ":" + uri; + } + }; + System.out.println(extractor.extractor("GET", "/httpclient/back/1", null)); + assertEquals("GET:/httpclient/back/{id}", extractor.extractor("GET", "/httpclient/back/1", null)); + } +} \ No newline at end of file diff --git a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/fallback/ApacheHttpClientFallbackTest.java b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/fallback/ApacheHttpClientFallbackTest.java new file mode 100644 index 0000000000..56865918c2 --- /dev/null +++ b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/fallback/ApacheHttpClientFallbackTest.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.apache.httpclient.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 ApacheHttpClientFallbackTest { + + @Test(expected = SentinelRpcException.class) + public void testDefaultOkHttpFallback() { + BlockException e = new FlowException("xxx"); + ApacheHttpClientFallback fallback = new DefaultApacheHttpClientFallback(); + fallback.handle(null, e); + } +} diff --git a/sentinel-demo/sentinel-demo-apache-httpclient/pom.xml b/sentinel-demo/sentinel-demo-apache-httpclient/pom.xml index 8d20bbf16e..b83a5fafc2 100644 --- a/sentinel-demo/sentinel-demo-apache-httpclient/pom.xml +++ b/sentinel-demo/sentinel-demo-apache-httpclient/pom.xml @@ -14,6 +14,7 @@ 2.1.3.RELEASE 4.3 + 4.5.6 @@ -44,13 +45,7 @@ org.apache.httpcomponents httpclient - 4.5.6 - - - - org.apache.httpcomponents - httpasyncclient - 4.1.4 + ${apache.httpclient.version} diff --git a/sentinel-demo/sentinel-demo-apache-httpclient/src/main/java/com/alibaba/csp/sentinel/demo/apache/httpclient/ApacheHttpClientDemoApplication.java b/sentinel-demo/sentinel-demo-apache-httpclient/src/main/java/com/alibaba/csp/sentinel/demo/apache/httpclient/ApacheHttpClientDemoApplication.java index 24f97f2cc0..9be9df9088 100644 --- a/sentinel-demo/sentinel-demo-apache-httpclient/src/main/java/com/alibaba/csp/sentinel/demo/apache/httpclient/ApacheHttpClientDemoApplication.java +++ b/sentinel-demo/sentinel-demo-apache-httpclient/src/main/java/com/alibaba/csp/sentinel/demo/apache/httpclient/ApacheHttpClientDemoApplication.java @@ -1,5 +1,5 @@ /* - * Copyright 1999-2019 Alibaba Group Holding Ltd. + * 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. @@ -16,10 +16,15 @@ package com.alibaba.csp.sentinel.demo.apache.httpclient; import com.alibaba.csp.sentinel.adapter.apache.httpclient.config.SentinelApacheHttpClientConfig; +import com.alibaba.csp.sentinel.adapter.apache.httpclient.extractor.ApacheHttpClientResourceExtractor; +import org.apache.http.client.methods.HttpRequestWrapper; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +/** + * @author zhaoyuguang + */ @SpringBootApplication public class ApacheHttpClientDemoApplication implements CommandLineRunner { @@ -29,11 +34,16 @@ public static void main(String[] args) { @Override public void run(String... args) { - SentinelApacheHttpClientConfig.setCleaner((request, context) -> { - if (request.getRequestLine().getUri().startsWith("/httpclient/back/")) { - return request.getRequestLine().getMethod() + ":/httpclient/back/{id}"; + SentinelApacheHttpClientConfig.setExtractor(new ApacheHttpClientResourceExtractor() { + + @Override + public String extractor(String method, String uri, HttpRequestWrapper request) { + String regex = "/httpclient/back/"; + if (uri.contains(regex)) { + uri = uri.substring(0, uri.indexOf(regex) + regex.length()) + "{id}"; + } + return method + ":" + uri; } - return request.getRequestLine().getMethod() + ":" + request.getRequestLine().getUri(); }); } } diff --git a/sentinel-demo/sentinel-demo-apache-httpclient/src/main/java/com/alibaba/csp/sentinel/demo/apache/httpclient/controller/ApacheHttpClientTestController.java b/sentinel-demo/sentinel-demo-apache-httpclient/src/main/java/com/alibaba/csp/sentinel/demo/apache/httpclient/controller/ApacheHttpClientTestController.java index 307f375e50..c6aecedcd6 100644 --- a/sentinel-demo/sentinel-demo-apache-httpclient/src/main/java/com/alibaba/csp/sentinel/demo/apache/httpclient/controller/ApacheHttpClientTestController.java +++ b/sentinel-demo/sentinel-demo-apache-httpclient/src/main/java/com/alibaba/csp/sentinel/demo/apache/httpclient/controller/ApacheHttpClientTestController.java @@ -1,5 +1,5 @@ /* - * Copyright 1999-2019 Alibaba Group Holding Ltd. + * 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. @@ -16,14 +16,10 @@ package com.alibaba.csp.sentinel.demo.apache.httpclient.controller; import com.alibaba.csp.sentinel.adapter.apache.httpclient.SentinelApacheHttpClientBuilder; -import com.alibaba.csp.sentinel.adapter.apache.httpclient.config.SentinelApacheHttpClientConfig; -import com.alibaba.csp.sentinel.adapter.apache.httpclient.exception.SentinelApacheHttpClientHandleException; import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.nio.client.CloseableHttpAsyncClient; import org.apache.http.protocol.BasicHttpContext; import org.apache.http.protocol.HttpContext; import org.apache.http.util.EntityUtils; @@ -33,9 +29,10 @@ import org.springframework.web.bind.annotation.RestController; import java.io.IOException; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; +/** + * @author zhaoyuguang + */ @RestController public class ApacheHttpClientTestController { @@ -56,7 +53,7 @@ public String back(@PathVariable String id) { @RequestMapping("/httpclient/sync") public String sync() throws Exception { - CloseableHttpClient httpclient = SentinelApacheHttpClientBuilder.httpClientBuilder().build(); + CloseableHttpClient httpclient = new SentinelApacheHttpClientBuilder().build(); HttpGet httpGet = new HttpGet("http://localhost:" + port + "/httpclient/back"); return getRemoteString(httpclient, httpGet); @@ -64,7 +61,7 @@ public String sync() throws Exception { @RequestMapping("/httpclient/sync/{id}") public String sync(@PathVariable String id) throws Exception { - CloseableHttpClient httpclient = SentinelApacheHttpClientBuilder.httpClientBuilder().build(); + CloseableHttpClient httpclient = new SentinelApacheHttpClientBuilder().build(); HttpGet httpGet = new HttpGet("http://localhost:" + port + "/httpclient/back/" + id); return getRemoteString(httpclient, httpGet); @@ -74,12 +71,7 @@ private String getRemoteString(CloseableHttpClient httpclient, HttpGet httpGet) String result; HttpContext context = new BasicHttpContext(); CloseableHttpResponse response; - try { - response = httpclient.execute(httpGet, context); - } catch (Exception e){ - SentinelApacheHttpClientHandleException.handle(context, e); - throw e; - } + response = httpclient.execute(httpGet, context); try { HttpEntity entity = response.getEntity(); result = EntityUtils.toString(entity, "utf-8"); @@ -90,17 +82,4 @@ private String getRemoteString(CloseableHttpClient httpclient, HttpGet httpGet) httpclient.close(); return result; } - - @RequestMapping("/httpclient/async") - public String async() throws Exception { - CloseableHttpAsyncClient httpclient = SentinelApacheHttpClientBuilder.httpAsyncClientBuilder().build(); - httpclient.start(); - - HttpGet httpGet = new HttpGet("http://localhost:" + port + "/httpclient/back"); - Future future = httpclient.execute(httpGet, null); - HttpResponse response = future.get(100L, TimeUnit.MILLISECONDS); - httpclient.close(); - return EntityUtils.toString(response.getEntity(), "utf-8"); - } - } From 4501ae832d7677def1d504fdb630d8a7c2cd2e82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E7=A6=B9=E5=85=89?= Date: Fri, 29 May 2020 18:24:13 +0800 Subject: [PATCH 3/5] add md --- .../README.md | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100755 sentinel-adapter/sentinel-apache-httpclient-adapter/README.md diff --git a/sentinel-adapter/sentinel-apache-httpclient-adapter/README.md b/sentinel-adapter/sentinel-apache-httpclient-adapter/README.md new file mode 100755 index 0000000000..ea0eddfd9b --- /dev/null +++ b/sentinel-adapter/sentinel-apache-httpclient-adapter/README.md @@ -0,0 +1,64 @@ +# Sentinel Apache Httpclient 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-apache-httpclient-adapter + x.y.z + +``` + +We can use the `SentinelApacheHttpClientBuilder` when `CloseableHttpClient` at initialization, for example: + +```java +CloseableHttpClient httpclient = new SentinelApacheHttpClientBuilder().build(); +``` + +## Configuration + +- `SentinelApacheHttpClientConfig` configuration: + +| name | description | type | default value | +|------|------------|------|-------| +| prefix | custom resource prefix | `String` | `httpclient:` | +| extractor | custom resource extractor | `ApacheHttpClientResourceExtractor` | `DefaultApacheHttpClientResourceExtractor` | +| fallback | handle request when it is blocked | `ApacheHttpClientFallback` | `DefaultApacheHttpClientFallback` | + +### extractor (resource extractor) + +We can define `ApacheHttpClientResourceExtractor` to custom resource extractor replace `DefaultApacheHttpClientResourceExtractor`, for example: httpclient:GET:/httpclient/back/1 ==> httpclient:GET:/httpclient/back/{id} + +```java +SentinelApacheHttpClientConfig.setExtractor(new ApacheHttpClientResourceExtractor() { + + @Override + public String extractor(String method, String uri, HttpRequestWrapper request) { + String regex = "/httpclient/back/"; + if (uri.contains(regex)) { + uri = uri.substring(0, uri.indexOf(regex) + regex.length()) + "{id}"; + } + return method + ":" + uri; + } +}); +``` + +### fallback (Block handling) + +We can define `ApacheHttpClientFallback` to handle request is blocked according to the actual scenario, for example: + +```java +public class DefaultApacheHttpClientFallback implements ApacheHttpClientFallback { + + @Override + public CloseableHttpResponse handle(HttpRequestWrapper request, BlockException e) { + // Just wrap and throw the exception. + throw new SentinelRpcException(e); + } +} +``` \ No newline at end of file From 068dcd83dc51a5cc5e629d69a0cf5d2e42988dd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E7=A6=B9=E5=85=89?= Date: Thu, 9 Jul 2020 12:05:29 +0800 Subject: [PATCH 4/5] fix --- .../README.md | 33 +++++++++----- .../SentinelApacheHttpClientBuilder.java | 19 +++++--- .../SentinelApacheHttpClientConfig.java | 26 +++++------ .../ApacheHttpClientResourceExtractor.java | 2 +- ...aultApacheHttpClientResourceExtractor.java | 4 +- .../SentinelApacheHttpClientTest.java | 18 ++++---- .../SentinelApacheHttpClientConfigTest.java | 9 ++-- ...ApacheHttpClientResourceExtractorTest.java | 43 ------------------- .../ApacheHttpClientDemoApplication.java | 14 ------ .../ApacheHttpClientTestController.java | 33 +++++++++++++- 10 files changed, 100 insertions(+), 101 deletions(-) delete mode 100644 sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/extractor/ApacheHttpClientResourceExtractorTest.java diff --git a/sentinel-adapter/sentinel-apache-httpclient-adapter/README.md b/sentinel-adapter/sentinel-apache-httpclient-adapter/README.md index ea0eddfd9b..46a592b0ea 100755 --- a/sentinel-adapter/sentinel-apache-httpclient-adapter/README.md +++ b/sentinel-adapter/sentinel-apache-httpclient-adapter/README.md @@ -20,37 +20,50 @@ We can use the `SentinelApacheHttpClientBuilder` when `CloseableHttpClient` at i CloseableHttpClient httpclient = new SentinelApacheHttpClientBuilder().build(); ``` +If we want to add some additional configurations, we can refer to the following code + +```java +HttpClientBuilder builder = new SentinelApacheHttpClientBuilder(); +//builder Other Definitions +CloseableHttpClient httpclient = builder.build(); +``` + +If we + ## Configuration - `SentinelApacheHttpClientConfig` configuration: | name | description | type | default value | |------|------------|------|-------| -| prefix | custom resource prefix | `String` | `httpclient:` | -| extractor | custom resource extractor | `ApacheHttpClientResourceExtractor` | `DefaultApacheHttpClientResourceExtractor` | +| prefix | customize resource prefix | `String` | `httpclient:` | +| extractor | customize resource extractor | `ApacheHttpClientResourceExtractor` | `DefaultApacheHttpClientResourceExtractor` | | fallback | handle request when it is blocked | `ApacheHttpClientFallback` | `DefaultApacheHttpClientFallback` | ### extractor (resource extractor) -We can define `ApacheHttpClientResourceExtractor` to custom resource extractor replace `DefaultApacheHttpClientResourceExtractor`, for example: httpclient:GET:/httpclient/back/1 ==> httpclient:GET:/httpclient/back/{id} +We can define `ApacheHttpClientResourceExtractor` to customize resource extractor replace `DefaultApacheHttpClientResourceExtractor` at `SentinelApacheHttpClientBuilder` default config, for example: httpclient:GET:/httpclient/back/1 ==> httpclient:GET:/httpclient/back/{id} ```java -SentinelApacheHttpClientConfig.setExtractor(new ApacheHttpClientResourceExtractor() { +SentinelApacheHttpClientConfig config = new SentinelApacheHttpClientConfig(); +config.setExtractor(new ApacheHttpClientResourceExtractor() { @Override - public String extractor(String method, String uri, HttpRequestWrapper request) { - String regex = "/httpclient/back/"; - if (uri.contains(regex)) { - uri = uri.substring(0, uri.indexOf(regex) + regex.length()) + "{id}"; + public String extractor(HttpRequestWrapper request) { + String contains = "/httpclient/back/"; + String uri = request.getRequestLine().getUri(); + if (uri.startsWith(contains)) { + uri = uri.substring(0, uri.indexOf(contains) + contains.length()) + "{id}"; } - return method + ":" + uri; + return request.getMethod() + ":" + uri; } }); +CloseableHttpClient httpclient = new SentinelApacheHttpClientBuilder(config).build(); ``` ### fallback (Block handling) -We can define `ApacheHttpClientFallback` to handle request is blocked according to the actual scenario, for example: +We can define `ApacheHttpClientFallback` at `SentinelApacheHttpClientBuilder` default config, to handle request is blocked according to the actual scenario, for example: ```java public class DefaultApacheHttpClientFallback implements ApacheHttpClientFallback { diff --git a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/SentinelApacheHttpClientBuilder.java b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/SentinelApacheHttpClientBuilder.java index e6b208462f..4b6aad3789 100644 --- a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/SentinelApacheHttpClientBuilder.java +++ b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/SentinelApacheHttpClientBuilder.java @@ -35,6 +35,16 @@ */ public class SentinelApacheHttpClientBuilder extends HttpClientBuilder { + private final SentinelApacheHttpClientConfig config; + + public SentinelApacheHttpClientBuilder(){ + this.config = new SentinelApacheHttpClientConfig(); + } + + public SentinelApacheHttpClientBuilder(SentinelApacheHttpClientConfig config){ + this.config = config; + } + @Override protected ClientExecChain decorateMainExec(final ClientExecChain mainExec) { return new ClientExecChain() { @@ -44,15 +54,14 @@ public CloseableHttpResponse execute(HttpRoute route, HttpRequestWrapper request throws IOException, HttpException { Entry entry = null; try { - String name = SentinelApacheHttpClientConfig.getExtractor().extractor(request.getMethod(), - request.getRequestLine().getUri(), request); - if (!StringUtil.isEmpty(SentinelApacheHttpClientConfig.getPrefix())) { - name = SentinelApacheHttpClientConfig.getPrefix() + name; + String name = config.getExtractor().extractor(request); + if (!StringUtil.isEmpty(config.getPrefix())) { + name = config.getPrefix() + name; } entry = SphU.entry(name, ResourceTypeConstants.COMMON_WEB, EntryType.OUT); return mainExec.execute(route, request, clientContext, execAware); } catch (BlockException e) { - return SentinelApacheHttpClientConfig.getFallback().handle(request, e); + return config.getFallback().handle(request, e); } catch (Throwable t) { Tracer.traceEntry(t, entry); throw t; diff --git a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/config/SentinelApacheHttpClientConfig.java b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/config/SentinelApacheHttpClientConfig.java index f470fc4afe..9dbc1520ff 100644 --- a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/config/SentinelApacheHttpClientConfig.java +++ b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/config/SentinelApacheHttpClientConfig.java @@ -24,36 +24,36 @@ /** * @author zhaoyuguang */ -public final class SentinelApacheHttpClientConfig { +public class SentinelApacheHttpClientConfig { - private static volatile String prefix = "httpclient:"; - private static volatile ApacheHttpClientResourceExtractor extractor = new DefaultApacheHttpClientResourceExtractor(); - private static volatile ApacheHttpClientFallback fallback = new DefaultApacheHttpClientFallback(); + private String prefix = "httpclient:"; + private ApacheHttpClientResourceExtractor extractor = new DefaultApacheHttpClientResourceExtractor(); + private ApacheHttpClientFallback fallback = new DefaultApacheHttpClientFallback(); - public static String getPrefix() { + public String getPrefix() { return prefix; } - public static void setPrefix(String prefix) { + public void setPrefix(String prefix) { AssertUtil.notNull(prefix, "prefix cannot be null"); - SentinelApacheHttpClientConfig.prefix = prefix; + this.prefix = prefix; } - public static ApacheHttpClientResourceExtractor getExtractor() { + public ApacheHttpClientResourceExtractor getExtractor() { return extractor; } - public static void setExtractor(ApacheHttpClientResourceExtractor extractor) { + public void setExtractor(ApacheHttpClientResourceExtractor extractor) { AssertUtil.notNull(extractor, "extractor cannot be null"); - SentinelApacheHttpClientConfig.extractor = extractor; + this.extractor = extractor; } - public static ApacheHttpClientFallback getFallback() { + public ApacheHttpClientFallback getFallback() { return fallback; } - public static void setFallback(ApacheHttpClientFallback fallback) { + public void setFallback(ApacheHttpClientFallback fallback) { AssertUtil.notNull(fallback, "fallback cannot be null"); - SentinelApacheHttpClientConfig.fallback = fallback; + this.fallback = fallback; } } diff --git a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/extractor/ApacheHttpClientResourceExtractor.java b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/extractor/ApacheHttpClientResourceExtractor.java index 710e9e9655..ab494d67d3 100644 --- a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/extractor/ApacheHttpClientResourceExtractor.java +++ b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/extractor/ApacheHttpClientResourceExtractor.java @@ -22,5 +22,5 @@ */ public interface ApacheHttpClientResourceExtractor { - String extractor(String method, String uri, HttpRequestWrapper request); + String extractor(HttpRequestWrapper request); } diff --git a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/extractor/DefaultApacheHttpClientResourceExtractor.java b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/extractor/DefaultApacheHttpClientResourceExtractor.java index 24cbc08698..02ccf697a8 100644 --- a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/extractor/DefaultApacheHttpClientResourceExtractor.java +++ b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/extractor/DefaultApacheHttpClientResourceExtractor.java @@ -23,7 +23,7 @@ public class DefaultApacheHttpClientResourceExtractor implements ApacheHttpClientResourceExtractor { @Override - public String extractor(String method, String uri, HttpRequestWrapper request) { - return method + ":" + uri; + public String extractor(HttpRequestWrapper request) { + return request.getRequestLine().getUri(); } } diff --git a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/SentinelApacheHttpClientTest.java b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/SentinelApacheHttpClientTest.java index e24b8581c0..882edafe0c 100644 --- a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/SentinelApacheHttpClientTest.java +++ b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/SentinelApacheHttpClientTest.java @@ -60,7 +60,7 @@ public void testSentinelOkHttpInterceptor0() throws Exception { HttpGet httpGet = new HttpGet("http://localhost:" + port + "/httpclient/back"); System.out.println(getRemoteString(httpclient, httpGet)); - ClusterNode cn = ClusterBuilderSlot.getClusterNode("httpclient:GET:/httpclient/back"); + ClusterNode cn = ClusterBuilderSlot.getClusterNode("httpclient:/httpclient/back"); assertNotNull(cn); Constants.ROOT.removeChildList(); ClusterBuilderSlot.getClusterNodeMap().clear(); @@ -68,18 +68,20 @@ public void testSentinelOkHttpInterceptor0() throws Exception { @Test public void testSentinelOkHttpInterceptor1() throws Exception { - SentinelApacheHttpClientConfig.setExtractor(new ApacheHttpClientResourceExtractor() { + SentinelApacheHttpClientConfig config = new SentinelApacheHttpClientConfig(); + config.setExtractor(new ApacheHttpClientResourceExtractor() { @Override - public String extractor(String method, String uri, HttpRequestWrapper request) { - String regex = "/httpclient/back/"; - if (uri.contains(regex)) { - uri = uri.substring(0, uri.indexOf(regex) + regex.length()) + "{id}"; + public String extractor(HttpRequestWrapper request) { + String contains = "/httpclient/back/"; + String uri = request.getRequestLine().getUri(); + if (uri.startsWith(contains)) { + uri = uri.substring(0, uri.indexOf(contains) + contains.length()) + "{id}"; } - return method + ":" + uri; + return request.getMethod() + ":" + uri; } }); - CloseableHttpClient httpclient = new SentinelApacheHttpClientBuilder().build(); + CloseableHttpClient httpclient = new SentinelApacheHttpClientBuilder(config).build(); HttpGet httpGet = new HttpGet("http://localhost:" + port + "/httpclient/back/1"); System.out.println(getRemoteString(httpclient, httpGet)); diff --git a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/config/SentinelApacheHttpClientConfigTest.java b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/config/SentinelApacheHttpClientConfigTest.java index f5141308d4..414322b79f 100644 --- a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/config/SentinelApacheHttpClientConfigTest.java +++ b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/config/SentinelApacheHttpClientConfigTest.java @@ -24,16 +24,19 @@ public class SentinelApacheHttpClientConfigTest { @Test(expected = IllegalArgumentException.class) public void testConfigSetPrefix() { - SentinelApacheHttpClientConfig.setPrefix(null); + SentinelApacheHttpClientConfig config = new SentinelApacheHttpClientConfig(); + config.setPrefix(null); } @Test(expected = IllegalArgumentException.class) public void testConfigSetCleaner() { - SentinelApacheHttpClientConfig.setExtractor(null); + SentinelApacheHttpClientConfig config = new SentinelApacheHttpClientConfig(); + config.setExtractor(null); } @Test(expected = IllegalArgumentException.class) public void testConfigSetFallback() { - SentinelApacheHttpClientConfig.setFallback(null); + SentinelApacheHttpClientConfig config = new SentinelApacheHttpClientConfig(); + config.setFallback(null); } } diff --git a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/extractor/ApacheHttpClientResourceExtractorTest.java b/sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/extractor/ApacheHttpClientResourceExtractorTest.java deleted file mode 100644 index b18bac076d..0000000000 --- a/sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/extractor/ApacheHttpClientResourceExtractorTest.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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.apache.httpclient.extractor; - -import org.apache.http.client.methods.HttpRequestWrapper; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -/** - * @author zhaoyuguang - */ -public class ApacheHttpClientResourceExtractorTest { - - @Test - public void testDefaultOkHttpResourceExtractor() { - ApacheHttpClientResourceExtractor extractor = new ApacheHttpClientResourceExtractor() { - @Override - public String extractor(String method, String uri, HttpRequestWrapper request) { - String regex = "/httpclient/back/"; - if (uri.contains(regex)) { - uri = uri.substring(0, uri.indexOf(regex) + regex.length()) + "{id}"; - } - return method + ":" + uri; - } - }; - System.out.println(extractor.extractor("GET", "/httpclient/back/1", null)); - assertEquals("GET:/httpclient/back/{id}", extractor.extractor("GET", "/httpclient/back/1", null)); - } -} \ No newline at end of file diff --git a/sentinel-demo/sentinel-demo-apache-httpclient/src/main/java/com/alibaba/csp/sentinel/demo/apache/httpclient/ApacheHttpClientDemoApplication.java b/sentinel-demo/sentinel-demo-apache-httpclient/src/main/java/com/alibaba/csp/sentinel/demo/apache/httpclient/ApacheHttpClientDemoApplication.java index 9be9df9088..797e8e1b91 100644 --- a/sentinel-demo/sentinel-demo-apache-httpclient/src/main/java/com/alibaba/csp/sentinel/demo/apache/httpclient/ApacheHttpClientDemoApplication.java +++ b/sentinel-demo/sentinel-demo-apache-httpclient/src/main/java/com/alibaba/csp/sentinel/demo/apache/httpclient/ApacheHttpClientDemoApplication.java @@ -15,9 +15,6 @@ */ package com.alibaba.csp.sentinel.demo.apache.httpclient; -import com.alibaba.csp.sentinel.adapter.apache.httpclient.config.SentinelApacheHttpClientConfig; -import com.alibaba.csp.sentinel.adapter.apache.httpclient.extractor.ApacheHttpClientResourceExtractor; -import org.apache.http.client.methods.HttpRequestWrapper; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @@ -34,16 +31,5 @@ public static void main(String[] args) { @Override public void run(String... args) { - SentinelApacheHttpClientConfig.setExtractor(new ApacheHttpClientResourceExtractor() { - - @Override - public String extractor(String method, String uri, HttpRequestWrapper request) { - String regex = "/httpclient/back/"; - if (uri.contains(regex)) { - uri = uri.substring(0, uri.indexOf(regex) + regex.length()) + "{id}"; - } - return method + ":" + uri; - } - }); } } diff --git a/sentinel-demo/sentinel-demo-apache-httpclient/src/main/java/com/alibaba/csp/sentinel/demo/apache/httpclient/controller/ApacheHttpClientTestController.java b/sentinel-demo/sentinel-demo-apache-httpclient/src/main/java/com/alibaba/csp/sentinel/demo/apache/httpclient/controller/ApacheHttpClientTestController.java index c6aecedcd6..3b1bf8970b 100644 --- a/sentinel-demo/sentinel-demo-apache-httpclient/src/main/java/com/alibaba/csp/sentinel/demo/apache/httpclient/controller/ApacheHttpClientTestController.java +++ b/sentinel-demo/sentinel-demo-apache-httpclient/src/main/java/com/alibaba/csp/sentinel/demo/apache/httpclient/controller/ApacheHttpClientTestController.java @@ -16,9 +16,12 @@ package com.alibaba.csp.sentinel.demo.apache.httpclient.controller; import com.alibaba.csp.sentinel.adapter.apache.httpclient.SentinelApacheHttpClientBuilder; +import com.alibaba.csp.sentinel.adapter.apache.httpclient.config.SentinelApacheHttpClientConfig; +import com.alibaba.csp.sentinel.adapter.apache.httpclient.extractor.ApacheHttpClientResourceExtractor; import org.apache.http.HttpEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpRequestWrapper; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.protocol.BasicHttpContext; import org.apache.http.protocol.HttpContext; @@ -53,7 +56,20 @@ public String back(@PathVariable String id) { @RequestMapping("/httpclient/sync") public String sync() throws Exception { - CloseableHttpClient httpclient = new SentinelApacheHttpClientBuilder().build(); + SentinelApacheHttpClientConfig config = new SentinelApacheHttpClientConfig(); + config.setExtractor(new ApacheHttpClientResourceExtractor() { + + @Override + public String extractor(HttpRequestWrapper request) { + String contains = "/httpclient/back/"; + String uri = request.getRequestLine().getUri(); + if (uri.startsWith(contains)) { + uri = uri.substring(0, uri.indexOf(contains) + contains.length()) + "{id}"; + } + return request.getMethod() + ":" + uri; + } + }); + CloseableHttpClient httpclient = new SentinelApacheHttpClientBuilder(config).build(); HttpGet httpGet = new HttpGet("http://localhost:" + port + "/httpclient/back"); return getRemoteString(httpclient, httpGet); @@ -61,7 +77,20 @@ public String sync() throws Exception { @RequestMapping("/httpclient/sync/{id}") public String sync(@PathVariable String id) throws Exception { - CloseableHttpClient httpclient = new SentinelApacheHttpClientBuilder().build(); + SentinelApacheHttpClientConfig config = new SentinelApacheHttpClientConfig(); + config.setExtractor(new ApacheHttpClientResourceExtractor() { + + @Override + public String extractor(HttpRequestWrapper request) { + String contains = "/httpclient/back/"; + String uri = request.getRequestLine().getUri(); + if (uri.startsWith(contains)) { + uri = uri.substring(0, uri.indexOf(contains) + contains.length()) + "{id}"; + } + return request.getMethod() + ":" + uri; + } + }); + CloseableHttpClient httpclient = new SentinelApacheHttpClientBuilder(config).build(); HttpGet httpGet = new HttpGet("http://localhost:" + port + "/httpclient/back/" + id); return getRemoteString(httpclient, httpGet); From 24f09bf0b0efa5eb52da15ffed61a5cdd04ccf65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E7=A6=B9=E5=85=89?= Date: Thu, 9 Jul 2020 12:52:43 +0800 Subject: [PATCH 5/5] fix md --- sentinel-adapter/sentinel-apache-httpclient-adapter/README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/sentinel-adapter/sentinel-apache-httpclient-adapter/README.md b/sentinel-adapter/sentinel-apache-httpclient-adapter/README.md index 46a592b0ea..3ec548d2f6 100755 --- a/sentinel-adapter/sentinel-apache-httpclient-adapter/README.md +++ b/sentinel-adapter/sentinel-apache-httpclient-adapter/README.md @@ -28,8 +28,6 @@ HttpClientBuilder builder = new SentinelApacheHttpClientBuilder(); CloseableHttpClient httpclient = builder.build(); ``` -If we - ## Configuration - `SentinelApacheHttpClientConfig` configuration: