HttpClient
使用
- httpclient较为特殊
- sentinel本身不提供一些切面拦截能力,都是借助第三方sdk提供的能力
- httpclient需要在构建时由应用程序显示使用SentinelApacheHttpClientBuilder
HttpClientBuilder builder = new SentinelApacheHttpClientBuilder(config);
CloseableHttpClient httpClient = builder.build();
限流逻辑SentinelApacheHttpClientBuilder
- 执行限流逻辑
- 未限流执行http调用
- 限流执行Fallback逻辑
- sentinel工作现场清理
public class SentinelApacheHttpClientBuilder extends HttpClientBuilder {
...... 删除其他代码
@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) {
发生限流交由Fallback处理
return config.getFallback().handle(request, e);
} catch (Throwable t) {
Tracer.traceEntry(t, entry);
throw t;
} finally {
现场清理
if (entry != null) {
entry.exit();
}
}
}
};
}
}
OkHttp
使用
- OKHttp提供拦截器切入
- 通过拦截器和DefaultOkHttpFallback注入完成sentinel限流逻辑
private final OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new SentinelOkHttpInterceptor(new SentinelOkHttpConfig((request, connection) -> {
String regex = "/okhttp/back/";
String url = request.url().toString();
if (url.contains(regex)) {
url = url.substring(0, url.indexOf(regex) + regex.length()) + "{id}";
}
return request.method() + ":" + url;
}, new DefaultOkHttpFallback())))
.build();
限流逻辑
- 获取通过资源提取器提取资源名
- 限流处理
- 未限流执行请求
- 限流交由fallback处理
- 现场清理等工作
public class SentinelOkHttpInterceptor implements Interceptor {
...... 删除其他代码
@Override
public Response intercept(Chain chain) throws IOException {
Entry entry = null;
try {
获取通过资源提取器提取资源名
Request request = chain.request();
String name = config.getResourceExtractor().extract(request, chain.connection());
if (StringUtil.isNotBlank(config.getResourcePrefix())) {
name = config.getResourcePrefix() + name;
}
限流处理
entry = SphU.entry(name, ResourceTypeConstants.COMMON_WEB, EntryType.OUT);
未限流执行请求
return chain.proceed(request);
} catch (BlockException e) {
限流交由fallback处理
return config.getFallback().handle(chain.request(), chain.connection(), e);
} catch (IOException ex) {
错误记录
Tracer.traceEntry(ex, entry);
throw ex;
} finally {
现场清理
if (entry != null) {
entry.exit();
}
}
}
}
总结
- httpclient需要显示调用SentinelApacheHttpClientBuilder构建
- 通过显示构建完成sentinel对httpclient的织入增强
- OkHttpClient也需要显示构建,其通过拦截器注入完成增强