1.SOFA RPC源码解析
1.1 FilterChain
在SOFA RPC设计中,FilterChain是比较有新意的。它没有采用常用的List列表模式,即在List列表中存储Filter实现,然后按照Filter在列表中的顺序依次调用各Filter接口的filter方法,完成过滤器功能。
FilterChain简化类图如下:
首先,FilterChain实现了调用器com.alipay.sofa.rpc.invoke.Invoker接口;
其次,Filter为抽象类,非单例模式,其子类需要实现invoke(FilterInvoker invoker, SofaRequest request)方法,实现具体的过滤功能。在此需要注意,invoke方法除了request参数外,还需要invoker方法,表示下一个Filter的调用对象,这点不同于常见的List列表实现方式。
然后,引入新的FilterInvoker,该类实现了Invoker接口,为Filter的封装类,用作把过滤器包装成Invoker对象。另外,FilterInvoker采用链表节点设计方式,通过其构造函数FilterInvoker(Filter nextFilter, FilterInvoker invoker,AbstractInterfaceConfig config)可以看出,FilterInvoker包括两个主要属性:Filter类型的nextFilter,表示下一层过滤器;FilterInvoker类型的invoker,表示下一层Invoker。这种设计方式解耦了Filter和Service。同时,以FilterInvoker为链表节点,可以构造一个Filter执行链。
再看一下FilterChain,它也有一个比较重要的属性:FilterInvoker类型的invokerChain,表示filter调用链的第一个节点,在FilterChain类的invoke方法中调用该节点的invoke方法,启动整个执行链。
最后,看一下FilterChain的构造函数:
1. protected FilterChain(List<Filter>filters, FilterInvoker lastInvoker, AbstractInterfaceConfig config) {
2. // 调用过程外面包装多层自定义filter
3. // 前面的过滤器在最外层
4. invokerChain = lastInvoker;
5. if (CommonUtils.isNotEmpty(filters)) {
6. loadedFilters = newArrayList<Filter>();
7. for (int i = filters.size() - 1; i >= 0;i--) {
8. try {
9. Filter filter = filters.get(i);
10. if(filter.needToLoad(invokerChain)) {
11. invokerChain = new FilterInvoker(filter,invokerChain, config);
12. // cache this forfilter when async respond
13. loadedFilters.add(filter);
14. }
15. } catch (Exception e) {
16. LOGGER.error("Errorwhen build filter chain", e);
17. throw newSofaRpcRuntimeException("Error when build filter chain", e);
18. }
19. }
20. }
21. }
FilterChain构造函数有三个参数:
1. filters:过滤器列表;
2. lastInvoker:最后一个调用器;
3. config:接口配置;
从这段代码可以看出:
首先,设置FilterChain的属性invokerChain为最后一个调用器lastInvoker;
其次,倒序遍历过滤器列表filters,依次为每个filter做如下处理:
1. 构造FilterInvoker,其参数依次为filter、invokerChain、config;
2. 把invokerChain设置为新创建的FilterChain;
当遍历完filters中所有的过滤器,FilterChain执行链也就创建完成。整个执行链的开始节点invokerChain为处于filters列表中第一位置的过滤器的FilterInvoker对象,最后一个节点为lastInvoker。
这样,当调用FilterChain类invoke方法时,该方法调用invokerChain的invoke方法,启动整个执行链。依次调用执行链上每个节点FilterInvoker的invoke方法,完成整个执行链的过滤功能和服务功能。
1. public SofaResponse invoke(SofaRequestrequest) throws SofaRpcException {
2. if (nextFilter == null &&invoker == null) {
3. throw newSofaRpcException(RpcErrorType.SERVER_FILTER, "Next filter or invoker isnull!");
4. }
5. return nextFilter == null ?
6. invoker.invoke(request) :
7. nextFilter.invoke(invoker,request);
8. }
每个节点FilterInvoker的invoke方法的执行流程如下:
1. 如果该节点的nextFilter不为null,表示此节点为由过滤器封装成的Invoker对象,则调用nextFilter的invoke方法,参数为下一层调用器invoker和SOFA RPC请求。