Skip to content

Commit 2b68a6c

Browse files
authored
Add OkHttp integration (#1456)
1 parent 99d4355 commit 2b68a6c

File tree

20 files changed

+829
-0
lines changed

20 files changed

+829
-0
lines changed

sentinel-adapter/pom.xml

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
<module>sentinel-spring-cloud-gateway-adapter</module>
2828
<module>sentinel-spring-webmvc-adapter</module>
2929
<module>sentinel-zuul2-adapter</module>
30+
<module>sentinel-okhttp-adapter</module>
3031
<module>sentinel-jax-rs-adapter</module>
3132
</modules>
3233

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Sentinel OkHttp Adapter
2+
3+
## Introduction
4+
5+
Sentinel provides integration for OkHttp client to enable flow control for web requests.
6+
7+
Add the following dependency in `pom.xml` (if you are using Maven):
8+
9+
```xml
10+
<dependency>
11+
<groupId>com.alibaba.csp</groupId>
12+
<artifactId>sentinel-okhttp-adapter</artifactId>
13+
<version>x.y.z</version>
14+
</dependency>
15+
```
16+
17+
We can add the `SentinelOkHttpInterceptor` interceptor when `OkHttpClient` at initialization, for example:
18+
19+
```java
20+
OkHttpClient client = new OkHttpClient.Builder()
21+
.addInterceptor(new SentinelOkHttpInterceptor())
22+
.build();
23+
```
24+
25+
## Configuration
26+
27+
- `SentinelOkHttpConfig` configuration:
28+
29+
| name | description | type | default value |
30+
|------|------------|------|-------|
31+
| extractor | custom resource extractor | `OkHttpResourceExtractor` | `DefaultOkHttpResourceExtractor` |
32+
| fallback | handle request when it is blocked | `OkHttpFallback` | `DefaultOkHttpFallback` |
33+
34+
### extractor (resource extractor)
35+
36+
We can define `OkHttpResourceExtractor` to custom resource extractor replace `DefaultOkHttpResourceExtractor`, for example: okhttp:GET:ip:port/okhttp/back/1 ==> /okhttp/back/{id}
37+
38+
```java
39+
OkHttpResourceExtractor extractor = (request, connection) -> {
40+
String resource = request.url().toString();
41+
String regex = "/okhttp/back/";
42+
if (resource.contains(regex)) {
43+
resource = resource.substring(0, resource.indexOf(regex) + regex.length()) + "{id}";
44+
}
45+
return resource;
46+
};
47+
SentinelOkHttpConfig.setExtractor(extractor);
48+
```
49+
50+
### fallback (Block handling)
51+
52+
We can define `OkHttpFallback` to handle request is blocked according to the actual scenario, for example:
53+
54+
```java
55+
public class DefaultOkHttpFallback implements OkHttpFallback {
56+
57+
@Override
58+
public Response handle(Request request, Connection connection, BlockException e) {
59+
// Just wrap and throw the exception.
60+
throw new SentinelRpcException(e);
61+
}
62+
}
63+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<parent>
6+
<artifactId>sentinel-adapter</artifactId>
7+
<groupId>com.alibaba.csp</groupId>
8+
<version>1.8.0-SNAPSHOT</version>
9+
</parent>
10+
<modelVersion>4.0.0</modelVersion>
11+
12+
<artifactId>sentinel-okhttp-adapter</artifactId>
13+
<packaging>jar</packaging>
14+
15+
<properties>
16+
<okhttp.version>3.6.0</okhttp.version>
17+
<spring.boot.version>2.1.3.RELEASE</spring.boot.version>
18+
<spring-test.version>5.1.5.RELEASE</spring-test.version>
19+
</properties>
20+
21+
<dependencies>
22+
<dependency>
23+
<groupId>com.alibaba.csp</groupId>
24+
<artifactId>sentinel-core</artifactId>
25+
</dependency>
26+
27+
<dependency>
28+
<groupId>com.squareup.okhttp3</groupId>
29+
<artifactId>okhttp</artifactId>
30+
<version>${okhttp.version}</version>
31+
<scope>provided</scope>
32+
</dependency>
33+
34+
<dependency>
35+
<groupId>junit</groupId>
36+
<artifactId>junit</artifactId>
37+
<scope>test</scope>
38+
</dependency>
39+
<dependency>
40+
<groupId>org.mockito</groupId>
41+
<artifactId>mockito-core</artifactId>
42+
<scope>test</scope>
43+
</dependency>
44+
<dependency>
45+
<groupId>com.alibaba</groupId>
46+
<artifactId>fastjson</artifactId>
47+
<scope>test</scope>
48+
</dependency>
49+
<dependency>
50+
<groupId>org.springframework.boot</groupId>
51+
<artifactId>spring-boot-starter-web</artifactId>
52+
<version>${spring.boot.version}</version>
53+
<scope>test</scope>
54+
</dependency>
55+
<dependency>
56+
<groupId>org.springframework.boot</groupId>
57+
<artifactId>spring-boot-test</artifactId>
58+
<version>${spring.boot.version}</version>
59+
<scope>test</scope>
60+
</dependency>
61+
<dependency>
62+
<groupId>org.springframework</groupId>
63+
<artifactId>spring-test</artifactId>
64+
<version>${spring-test.version}</version>
65+
<scope>test</scope>
66+
</dependency>
67+
</dependencies>
68+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright 1999-2020 Alibaba Group Holding Ltd.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.alibaba.csp.sentinel.adapter.okhttp;
17+
18+
import com.alibaba.csp.sentinel.*;
19+
import com.alibaba.csp.sentinel.adapter.okhttp.config.SentinelOkHttpConfig;
20+
import com.alibaba.csp.sentinel.slots.block.BlockException;
21+
import com.alibaba.csp.sentinel.util.StringUtil;
22+
import okhttp3.Interceptor;
23+
import okhttp3.Request;
24+
import okhttp3.Response;
25+
26+
import java.io.IOException;
27+
28+
/**
29+
* @author zhaoyuguang
30+
*/
31+
public class SentinelOkHttpInterceptor implements Interceptor {
32+
33+
@Override
34+
public Response intercept(Chain chain) throws IOException {
35+
Entry entry = null;
36+
try {
37+
Request request = chain.request();
38+
String name = SentinelOkHttpConfig.getExtractor().extract(request.url().toString(), request, chain.connection());
39+
if (!StringUtil.isEmpty(SentinelOkHttpConfig.getPrefix())) {
40+
name = SentinelOkHttpConfig.getPrefix() + name;
41+
}
42+
entry = SphU.entry(name, ResourceTypeConstants.COMMON_WEB, EntryType.OUT);
43+
return chain.proceed(request);
44+
} catch (BlockException e) {
45+
return SentinelOkHttpConfig.getFallback().handle(chain.request(), chain.connection(), e);
46+
} catch (Throwable t) {
47+
Tracer.traceEntry(t, entry);
48+
throw t;
49+
} finally {
50+
if (entry != null) {
51+
entry.exit();
52+
}
53+
}
54+
}
55+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Copyright 1999-2020 Alibaba Group Holding Ltd.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.alibaba.csp.sentinel.adapter.okhttp.config;
17+
18+
import com.alibaba.csp.sentinel.adapter.okhttp.extractor.DefaultOkHttpResourceExtractor;
19+
import com.alibaba.csp.sentinel.adapter.okhttp.extractor.OkHttpResourceExtractor;
20+
import com.alibaba.csp.sentinel.adapter.okhttp.fallback.DefaultOkHttpFallback;
21+
import com.alibaba.csp.sentinel.adapter.okhttp.fallback.OkHttpFallback;
22+
import com.alibaba.csp.sentinel.util.AssertUtil;
23+
24+
/**
25+
* @author zhaoyuguang
26+
*/
27+
public final class SentinelOkHttpConfig {
28+
29+
private static volatile String prefix = "okhttp:";
30+
private static volatile OkHttpResourceExtractor extractor = new DefaultOkHttpResourceExtractor();
31+
private static volatile OkHttpFallback fallback = new DefaultOkHttpFallback();
32+
33+
public static String getPrefix() {
34+
return prefix;
35+
}
36+
37+
public static void setPrefix(String prefix) {
38+
AssertUtil.notNull(prefix, "prefix cannot be null");
39+
SentinelOkHttpConfig.prefix = prefix;
40+
}
41+
42+
public static OkHttpResourceExtractor getExtractor() {
43+
return extractor;
44+
}
45+
46+
public static void setExtractor(OkHttpResourceExtractor extractor) {
47+
AssertUtil.notNull(extractor, "extractor cannot be null");
48+
SentinelOkHttpConfig.extractor = extractor;
49+
}
50+
51+
public static OkHttpFallback getFallback() {
52+
return fallback;
53+
}
54+
55+
public static void setFallback(OkHttpFallback fallback) {
56+
AssertUtil.notNull(fallback, "fallback cannot be null");
57+
SentinelOkHttpConfig.fallback = fallback;
58+
}
59+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Copyright 1999-2020 Alibaba Group Holding Ltd.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.alibaba.csp.sentinel.adapter.okhttp.extractor;
17+
18+
import okhttp3.Connection;
19+
import okhttp3.Request;
20+
21+
/**
22+
* @author zhaoyuguang
23+
*/
24+
public class DefaultOkHttpResourceExtractor implements OkHttpResourceExtractor {
25+
26+
@Override
27+
public String extract(String url, Request request, Connection connection) {
28+
return request.method() + ":" + request.url().toString();
29+
}
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright 1999-2020 Alibaba Group Holding Ltd.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.alibaba.csp.sentinel.adapter.okhttp.extractor;
17+
18+
import okhttp3.Connection;
19+
import okhttp3.Request;
20+
21+
/**
22+
* @author zhaoyuguang
23+
*/
24+
public interface OkHttpResourceExtractor {
25+
26+
String extract(String url, Request request, Connection connection);
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright 1999-2020 Alibaba Group Holding Ltd.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.alibaba.csp.sentinel.adapter.okhttp.fallback;
17+
18+
import com.alibaba.csp.sentinel.slots.block.BlockException;
19+
import com.alibaba.csp.sentinel.slots.block.SentinelRpcException;
20+
import okhttp3.Connection;
21+
import okhttp3.Request;
22+
import okhttp3.Response;
23+
24+
/**
25+
* @author zhaoyuguang
26+
*/
27+
public class DefaultOkHttpFallback implements OkHttpFallback {
28+
29+
@Override
30+
public Response handle(Request request, Connection connection, BlockException e) {
31+
// Just wrap and throw the exception.
32+
throw new SentinelRpcException(e);
33+
}
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright 1999-2020 Alibaba Group Holding Ltd.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.alibaba.csp.sentinel.adapter.okhttp.fallback;
17+
18+
import com.alibaba.csp.sentinel.slots.block.BlockException;
19+
import okhttp3.Connection;
20+
import okhttp3.Request;
21+
import okhttp3.Response;
22+
23+
/**
24+
* @author zhaoyuguang
25+
*/
26+
public interface OkHttpFallback {
27+
28+
Response handle(Request request, Connection connection, BlockException e);
29+
}

0 commit comments

Comments
 (0)