Просмотр исходного кода

Adapter: Support Apache HttpClient (#1455)

Introduce support through a customized client builder `SentinelApacheHttpClientBuilder`.
master
于玉桔 GitHub 4 лет назад
Родитель
Сommit
38911c5ec1
Не найден GPG ключ соответствующий данной подписи Идентификатор GPG ключа: 4AEE18F83AFDEB23
19 измененных файлов: 862 добавлений и 0 удалений
  1. +1
    -0
      sentinel-adapter/pom.xml
  2. +75
    -0
      sentinel-adapter/sentinel-apache-httpclient-adapter/README.md
  3. +69
    -0
      sentinel-adapter/sentinel-apache-httpclient-adapter/pom.xml
  4. +76
    -0
      sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/SentinelApacheHttpClientBuilder.java
  5. +59
    -0
      sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/config/SentinelApacheHttpClientConfig.java
  6. +26
    -0
      sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/extractor/ApacheHttpClientResourceExtractor.java
  7. +29
    -0
      sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/extractor/DefaultApacheHttpClientResourceExtractor.java
  8. +33
    -0
      sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/fallback/ApacheHttpClientFallback.java
  9. +38
    -0
      sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/fallback/DefaultApacheHttpClientFallback.java
  10. +109
    -0
      sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/SentinelApacheHttpClientTest.java
  11. +30
    -0
      sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/app/TestApplication.java
  12. +37
    -0
      sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/app/controller/TestController.java
  13. +42
    -0
      sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/config/SentinelApacheHttpClientConfigTest.java
  14. +34
    -0
      sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/fallback/ApacheHttpClientFallbackTest.java
  15. +1
    -0
      sentinel-demo/pom.xml
  16. +52
    -0
      sentinel-demo/sentinel-demo-apache-httpclient/pom.xml
  17. +35
    -0
      sentinel-demo/sentinel-demo-apache-httpclient/src/main/java/com/alibaba/csp/sentinel/demo/apache/httpclient/ApacheHttpClientDemoApplication.java
  18. +114
    -0
      sentinel-demo/sentinel-demo-apache-httpclient/src/main/java/com/alibaba/csp/sentinel/demo/apache/httpclient/controller/ApacheHttpClientTestController.java
  19. +2
    -0
      sentinel-demo/sentinel-demo-apache-httpclient/src/main/resources/application.properties

+ 1
- 0
sentinel-adapter/pom.xml Просмотреть файл

@@ -18,6 +18,7 @@
<module>sentinel-web-servlet</module>
<module>sentinel-dubbo-adapter</module>
<module>sentinel-apache-dubbo-adapter</module>
<module>sentinel-apache-httpclient-adapter</module>
<module>sentinel-sofa-rpc-adapter</module>
<module>sentinel-grpc-adapter</module>
<module>sentinel-zuul-adapter</module>


+ 75
- 0
sentinel-adapter/sentinel-apache-httpclient-adapter/README.md Просмотреть файл

@@ -0,0 +1,75 @@
# 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
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-apache-httpclient-adapter</artifactId>
<version>x.y.z</version>
</dependency>
```

We can use the `SentinelApacheHttpClientBuilder` when `CloseableHttpClient` at initialization, for example:

```java
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();
```

## Configuration

- `SentinelApacheHttpClientConfig` configuration:

| name | description | type | default value |
|------|------------|------|-------|
| 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 customize resource extractor replace `DefaultApacheHttpClientResourceExtractor` at `SentinelApacheHttpClientBuilder` default config, for example: httpclient:GET:/httpclient/back/1 ==> httpclient:GET:/httpclient/back/{id}

```java
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();
```

### fallback (Block handling)

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 {

@Override
public CloseableHttpResponse handle(HttpRequestWrapper request, BlockException e) {
// Just wrap and throw the exception.
throw new SentinelRpcException(e);
}
}
```

+ 69
- 0
sentinel-adapter/sentinel-apache-httpclient-adapter/pom.xml Просмотреть файл

@@ -0,0 +1,69 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>sentinel-adapter</artifactId>
<groupId>com.alibaba.csp</groupId>
<version>1.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>sentinel-apache-httpclient-adapter</artifactId>
<packaging>jar</packaging>

<properties>
<apache.httpclient.version>4.5.6</apache.httpclient.version>
<spring.boot.version>2.1.3.RELEASE</spring.boot.version>
<spring-test.version>5.1.5.RELEASE</spring-test.version>
</properties>

<dependencies>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>${apache.httpclient.version}</version>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${spring.boot.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
<version>${spring.boot.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring-test.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

+ 76
- 0
sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/SentinelApacheHttpClientBuilder.java Просмотреть файл

@@ -0,0 +1,76 @@
/*
* 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.*;
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.execchain.ClientExecChain;

import java.io.IOException;

/**
* @author zhaoyuguang
*/
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() {
@Override
public CloseableHttpResponse execute(HttpRoute route, HttpRequestWrapper request,
HttpClientContext clientContext, HttpExecutionAware execAware)
throws IOException, HttpException {
Entry entry = null;
try {
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 config.getFallback().handle(request, e);
} catch (Throwable t) {
Tracer.traceEntry(t, entry);
throw t;
} finally {
if (entry != null) {
entry.exit();
}
}
}
};
}
}

+ 59
- 0
sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/config/SentinelApacheHttpClientConfig.java Просмотреть файл

@@ -0,0 +1,59 @@
/*
* Copyright 1999-2020 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.csp.sentinel.adapter.apache.httpclient.config;

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;

/**
* @author zhaoyuguang
*/
public class SentinelApacheHttpClientConfig {

private String prefix = "httpclient:";
private ApacheHttpClientResourceExtractor extractor = new DefaultApacheHttpClientResourceExtractor();
private ApacheHttpClientFallback fallback = new DefaultApacheHttpClientFallback();

public String getPrefix() {
return prefix;
}

public void setPrefix(String prefix) {
AssertUtil.notNull(prefix, "prefix cannot be null");
this.prefix = prefix;
}

public ApacheHttpClientResourceExtractor getExtractor() {
return extractor;
}

public void setExtractor(ApacheHttpClientResourceExtractor extractor) {
AssertUtil.notNull(extractor, "extractor cannot be null");
this.extractor = extractor;
}

public ApacheHttpClientFallback getFallback() {
return fallback;
}

public void setFallback(ApacheHttpClientFallback fallback) {
AssertUtil.notNull(fallback, "fallback cannot be null");
this.fallback = fallback;
}
}

+ 26
- 0
sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/extractor/ApacheHttpClientResourceExtractor.java Просмотреть файл

@@ -0,0 +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.extractor;

import org.apache.http.client.methods.HttpRequestWrapper;

/**
* @author zhaoyuguang
*/
public interface ApacheHttpClientResourceExtractor {

String extractor(HttpRequestWrapper request);
}

+ 29
- 0
sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/extractor/DefaultApacheHttpClientResourceExtractor.java Просмотреть файл

@@ -0,0 +1,29 @@
/*
* Copyright 1999-2020 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.csp.sentinel.adapter.apache.httpclient.extractor;

import org.apache.http.client.methods.HttpRequestWrapper;

/**
* @author zhaoyuguang
*/
public class DefaultApacheHttpClientResourceExtractor implements ApacheHttpClientResourceExtractor {

@Override
public String extractor(HttpRequestWrapper request) {
return request.getRequestLine().getUri();
}
}

+ 33
- 0
sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/fallback/ApacheHttpClientFallback.java Просмотреть файл

@@ -0,0 +1,33 @@
/*
* 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;

/**
* @author zhaoyuguang
*/
public interface ApacheHttpClientFallback {

CloseableHttpResponse handle(HttpRequestWrapper request, BlockException e);
}

+ 38
- 0
sentinel-adapter/sentinel-apache-httpclient-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/fallback/DefaultApacheHttpClientFallback.java Просмотреть файл

@@ -0,0 +1,38 @@
/*
* 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;

/**
* @author zhaoyuguang
*/
public class DefaultApacheHttpClientFallback implements ApacheHttpClientFallback {

@Override
public CloseableHttpResponse handle(HttpRequestWrapper request, BlockException e) {
// Just wrap and throw the exception.
throw new SentinelRpcException(e);
}
}

+ 109
- 0
sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/SentinelApacheHttpClientTest.java Просмотреть файл

@@ -0,0 +1,109 @@
/*
* 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:/httpclient/back");
assertNotNull(cn);
Constants.ROOT.removeChildList();
ClusterBuilderSlot.getClusterNodeMap().clear();
}

@Test
public void testSentinelOkHttpInterceptor1() throws Exception {
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/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;
}
}

+ 30
- 0
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);
}
}

+ 37
- 0
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;
}
}

+ 42
- 0
sentinel-adapter/sentinel-apache-httpclient-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/apache/httpclient/config/SentinelApacheHttpClientConfigTest.java Просмотреть файл

@@ -0,0 +1,42 @@
/*
* 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 config = new SentinelApacheHttpClientConfig();
config.setPrefix(null);
}

@Test(expected = IllegalArgumentException.class)
public void testConfigSetCleaner() {
SentinelApacheHttpClientConfig config = new SentinelApacheHttpClientConfig();
config.setExtractor(null);
}

@Test(expected = IllegalArgumentException.class)
public void testConfigSetFallback() {
SentinelApacheHttpClientConfig config = new SentinelApacheHttpClientConfig();
config.setFallback(null);
}
}

+ 34
- 0
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);
}
}

+ 1
- 0
sentinel-demo/pom.xml Просмотреть файл

@@ -32,6 +32,7 @@
<module>sentinel-demo-command-handler</module>
<module>sentinel-demo-spring-webflux</module>
<module>sentinel-demo-apache-dubbo</module>
<module>sentinel-demo-apache-httpclient</module>
<module>sentinel-demo-sofa-rpc</module>
<module>sentinel-demo-spring-cloud-gateway</module>
<module>sentinel-demo-zuul-gateway</module>


+ 52
- 0
sentinel-demo/sentinel-demo-apache-httpclient/pom.xml Просмотреть файл

@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>sentinel-demo</artifactId>
<groupId>com.alibaba.csp</groupId>
<version>1.8.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>sentinel-demo-apache-httpclient</artifactId>

<properties>
<spring.boot.version>2.1.3.RELEASE</spring.boot.version>
<test.framework.version>4.3</test.framework.version>
<apache.httpclient.version>4.5.6</apache.httpclient.version>
</properties>

<dependencies>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-apache-httpclient-adapter</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${spring.boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${spring.boot.version}</version>
</dependency>

<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>${apache.httpclient.version}</version>
</dependency>
</dependencies>

</project>

+ 35
- 0
sentinel-demo/sentinel-demo-apache-httpclient/src/main/java/com/alibaba/csp/sentinel/demo/apache/httpclient/ApacheHttpClientDemoApplication.java Просмотреть файл

@@ -0,0 +1,35 @@
/*
* Copyright 1999-2020 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.csp.sentinel.demo.apache.httpclient;

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
* @author zhaoyuguang
*/
@SpringBootApplication
public class ApacheHttpClientDemoApplication implements CommandLineRunner {

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

@Override
public void run(String... args) {
}
}

+ 114
- 0
sentinel-demo/sentinel-demo-apache-httpclient/src/main/java/com/alibaba/csp/sentinel/demo/apache/httpclient/controller/ApacheHttpClientTestController.java Просмотреть файл

@@ -0,0 +1,114 @@
/*
* Copyright 1999-2020 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.csp.sentinel.demo.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;
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;

/**
* @author zhaoyuguang
*/
@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 {
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);
}

@RequestMapping("/httpclient/sync/{id}")
public String sync(@PathVariable String id) throws Exception {
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);
}

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;
}
}

+ 2
- 0
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

Загрузка…
Отмена
Сохранить