话不多说,上来就干
职责链模式
这一篇来了解一下soul网关中的插件设计机制,职责链模式是面向编程设计模式中的经典模式,具体可以参考职责链模式,职责链简单来说,就是每个接收者都包含另一个接收者的引用,这样在处理请求时,如果自己无法处理该请求时就会把请求,传递给下一个接收者,依次类推直到最后。
类图示例
职责链在soul网关中的应用
加载插件
在soul-web中初始化插件处理器
@Bean("webHandler")
public SoulWebHandler soulWebHandler(final ObjectProvider<List<SoulPlugin>> plugins) {
// 获取可用的插件列表
List<SoulPlugin> pluginList = plugins.getIfAvailable(Collections::emptyList);
// 通过order属性进行排序
final List<SoulPlugin> soulPlugins = pluginList.stream()
.sorted(Comparator.comparingInt(SoulPlugin::getOrder)).collect(Collectors.toList());
// 日志
soulPlugins.forEach(soulPlugin -> log.info("load plugin:[{}] [{}]", soulPlugin.named(), soulPlugin.getClass().getName()));
//初始化插件链
return new SoulWebHandler(soulPlugins);
}
SoulWebHandler
实现了spring的WebHandler
接口,接口类WebHandler
就是插件职责链中顶级接口,只有一个处理方法handle()
public interface WebHandler {
Mono<Void> handle(ServerWebExchange var1);
}
soul的handle()
,调用DefaultSoulPluginChain
的execute()
public Mono<Void> handle(@NonNull final ServerWebExchange exchange) {
MetricsTrackerFacade.getInstance().counterInc(MetricsLabelEnum.REQUEST_TOTAL.getName());
Optional<HistogramMetricsTrackerDelegate> startTimer = MetricsTrackerFacade.getInstance().histogramStartTimer(MetricsLabelEnum.REQUEST_LATENCY.getName());
return new DefaultSoulPluginChain(plugins).execute(exchange).subscribeOn(scheduler)
.doOnSuccess(t -> startTimer.ifPresent(time -> MetricsTrackerFacade.getInstance().histogramObserveDuration(time)));
}
我们可以先参考一下spring通过filter.chain方式调用自己的chain处理
public Mono<Void> filter(ServerWebExchange exchange) {
return Mono.defer(() ->
this.currentFilter != null && this.chain != null ?
invokeFilter(this.currentFilter, this.chain, exchange) :
this.handler.handle(exchange));
}
soul自己定义了插件链处理了接口SoulPluginChain
,通过DefaultSoulPluginChain
实现execute()
public Mono<Void> execute(final ServerWebExchange exchange) {
return Mono.defer(() -> {
if (this.index < plugins.size()) {
// index计数
SoulPlugin plugin = plugins.get(this.index++);
// 判断是否需要调过该插件
Boolean skip = plugin.skip(exchange);
if (skip) {
// 直接再次调用execute(),调用下一个index++的插件
return this.execute(exchange);
}
// 直接执行插件逻辑
return plugin.execute(exchange, this);
}
return Mono.empty();
});
}
优点
职责链模式提高soul插件机制的灵活性,实现解耦
虽然职责链设计本身采用递归调用,在性能上有所损耗,但是soul采用了响应式编程,
/**
* Process the Web request and (optionally) delegate to the next
* {@code WebFilter} through the given {@link SoulPluginChain}.
*
* @param exchange the current server exchange
* @param chain provides a way to delegate to the next filter
* @return {@code Mono<Void>} to indicate when request processing is complete
*/
Mono<Void> execute(ServerWebExchange exchange, SoulPluginChain chain);
响应式编程最大的优点就是摒除了同步阻塞的问题,直接采用异步非阻塞处理机制,大大弥补了责任链递归调用的性能损耗