有一阵子没有更新源码解析了,最近关注了一个微服务框架SOFA RPC这是蚂蚁金服的一个开源框架,地址在:https://github.com/sofastack/sofa-rpc, 这个框架还是一个朋友推荐的,看了第一部分它的发布流程没想到代码写的很精简易懂,封装性也很好,更大的激发了我看它的乐趣,那我们就一起一步步去学习下它的整个微服务框架的构成和实现吧!
一、 首先我们先从github fork下SOFA RPC这个项目,作者使用的是5.5版本,环境搭建及整体模型介绍参考:https://www.jianshu.com/p/1eeee833bd5d, 本地编译好那就准备工作都完成了,开始分析吧!服务发布现在有两种方式,一种是SOFA RPC发布方式,还有一种是使用SOFA BOOT,本系列文章都使用SOFA RPC方式分析,SOFA BOOT我们后面开专栏讲解是怎么封装SPRING BOOT的,OK 贴发布代码:
/** 需要发布的接口 **/ public interface HelloService { public String sayHello(String name); } /** 发布接口的实现类 **/ public class HelloServiceImpl implements HelloService { public String sayHello(String name) { return "hello , "+name; } } /** SOFA RPC 发布流程 **/ public class RpcServer { public static void main(String[] args) { //1、 构建RegistryConfig 注册配置 RegistryConfig registryConfig = new RegistryConfig().setProtocol("sofa").setAddress("127.0.0.1:8080"); RegistryConfig registryConfig1 = new RegistryConfig().setProtocol("zookeeper").setAddress("127.0.0.1:2181"); List<RegistryConfig> registryConfigs = new ArrayList<RegistryConfig>(); registryConfigs.add(registryConfig); registryConfigs.add(registryConfig1); // 2、构建ServerConfig 服务配置 List<ServerConfig> serverConfigs = new ArrayList<ServerConfig>(); ServerConfig serverConfig = new ServerConfig().setProtocol("bolt").setPort(12200).setDaemon(false); ServerConfig serverConfig1 = new ServerConfig().setProtocol("rest").setPort(12200).setDaemon(false); serverConfigs.add(serverConfig); serverConfigs.add(serverConfig1); // 3、构建发布配置 ProviderConfig<HelloService> providerConfig = new ProviderConfig<HelloService>() .setApplication(new ApplicationConfig() .setAppName("paul")) .setInterfaceId(HelloService.class.getName()) .setRef(new HelloServiceImpl()) .setServer(serverConfigs) .setRegistry(registryConfig); // 4、正式发布 providerConfig.export(); } }
前面接口类和实现类我们不必要多说,我们主要讲它怎么发布的,那我们进一步看下发布流程做了哪几件事
1、构建RegistryConfig 注册配置
RegistryConfig registryConfig = new RegistryConfig().setProtocol("sofa").setAddress("127.0.0.1:8080"); RegistryConfig registryConfig1 = new RegistryConfig().setProtocol("zookeeper").setAddress("127.0.0.1:2181"); List<RegistryConfig> registryConfigs = new ArrayList<RegistryConfig>();
首先是构建RegistryConfig注册配置,这个主要是用来注册服务使用的,可以支持多个协议:
文中举例使用了sofa 和 zookeeper 的注册中心,我们点进去源码发现是这样的:
public class RegistryConfig extends AbstractIdConfig implements Serializable ...
发现它是空构造方法,那它真的什么都没做吗?不是!它继承了AbstractIdConfig这个类,我们点进去这个类是这样的:
public abstract class AbstractIdConfig<S extends AbstractIdConfig> implements Serializable { private static final long serialVersionUID = -1932911135229369183L; /** * Id生成器 */ private final static AtomicInteger ID_GENERATOR = new AtomicInteger(0); static { RpcRuntimeContext.now(); } ...
这里我们就发现了,它有一个静态方法,那我们看看这个静态方法干了些什么:
这个也是啥都没做但是我们又发现RpcRuntimeContext又有一个静态方法,点进去看看,终于在这里我们看到它还是做了些事的
static { if (LOGGER.isInfoEnabled()) { LOGGER.info("Welcome! Loading SOFA RPC Framework : {}, PID is:{}", Version.BUILD_VERSION, PID); } // 放入当前的sofa版本号 put(RpcConstants.CONFIG_KEY_RPC_VERSION, Version.RPC_VERSION); // 初始化一些上下文 initContext(); // 初始化其它模块 ModuleFactory.installModules(); // 增加jvm关闭事件 if (RpcConfigs.getOrDefaultValue(RpcOptions.JVM_SHUTDOWN_HOOK, true)) { Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { @Override public void run() { if (LOGGER.isWarnEnabled()) { LOGGER.warn("SOFA RPC Framework catch JVM shutdown event, Run shutdown hook now."); } destroy(false); } }, "SOFA-RPC-ShutdownHook")); } }
那我们来一步步看看这个到底做了些什么
首先是 放入当前的sofa版本号,这个没啥说的,都是写死的版本,其次是初始化一些上下文,这里就是设置了全局运行时上下文类RpcRuntimeContext首先初始化上下文自动部署的appId、appName、appInsId以及当前所在文件夹地址appPath信息:
/** * 初始化一些上下文 */ private static void initContext() { putIfAbsent(KEY_APPID, RpcConfigs.getOrDefaultValue(APP_ID, null)); putIfAbsent(KEY_APPNAME, RpcConfigs.getOrDefaultValue(APP_NAME, null)); putIfAbsent(KEY_APPINSID, RpcConfigs.getOrDefaultValue(INSTANCE_ID, null)); putIfAbsent(KEY_APPAPTH, System.getProperty("user.dir")); }
其中通过配置加载器和操作入口RpcConfigs静态代码块在类加载的时候加载rpc-config-default.json、sofa-rpc/rpc-config.json、META-INF/sofa-rpc/rpc-config.json配置文件获取默认配置、自定义配置信息自定义配置信息存储在全部配置CFG:
static { init(); // 加载配置文件 } private static void init() { try { // loadDefault String json = FileUtils.file2String(RpcConfigs.class, "rpc-config-default.json", "UTF-8"); Map map = JSON.parseObject(json, Map.class); CFG.putAll(map); // loadCustom loadCustom("sofa-rpc/rpc-config.json"); loadCustom("META-INF/sofa-rpc/rpc-config.json"); // load system properties CFG.putAll(new HashMap(System.getProperties())); // 注意部分属性可能被覆盖为字符串 } catch (Exception e) { throw new SofaRpcRuntimeException("Catch Exception when load RpcConfigs", e); } }
接下来就是初始化其它模块了,这个模块我简单写了两个注释,这个不影响阅读,因为里面涉及到SPI,为减少篇幅,会单独写一篇文章来介绍
/** * 加载全部模块 */ public static void installModules() { // 使用ExtensionLoaderFactory获取传入class的ExtensionLoader ExtensionLoader<Module> loader = ExtensionLoaderFactory.getExtensionLoader(Module.class); // 获取需要加载的模块配置 String moduleLoadList = RpcConfigs.getStringValue(RpcOptions.MODULE_LOAD_LIST); for (Map.Entry<String, ExtensionClass<Module>> o : loader.getAllExtensions().entrySet()) { String moduleName = o.getKey(); Module module = o.getValue().getExtInstance(); // judge need load from rpc option if (needLoad(moduleLoadList, moduleName)) { // judge need load from implement if (module.needLoad()) { if (LOGGER.isInfoEnabled()) { LOGGER.info("Install Module: {}", moduleName); } module.install(); INSTALLED_MODULES.put(moduleName, module); } else { if (LOGGER.isInfoEnabled()) { LOGGER.info("The module " + moduleName + " does not need to be loaded."); } } } else { if (LOGGER.isInfoEnabled()) { LOGGER.info("The module " + moduleName + " is not in the module load list."); } } } }
接下来是增加jvm关闭事件了,这里面涉及到优雅停机,篇幅较大,后续我补充一篇优雅停机的文章
// 增加jvm关闭事件 if (RpcConfigs.getOrDefaultValue(RpcOptions.JVM_SHUTDOWN_HOOK, true)) { Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { @Override public void run() { if (LOGGER.isWarnEnabled()) { LOGGER.warn("SOFA RPC Framework catch JVM shutdown event, Run shutdown hook now."); } destroy(false); } }, "SOFA-RPC-ShutdownHook")); }
2、讲到这里我们的构建RegistryConfig 注册配置就讲完啦,接下来是构建ServerConfig 服务配置,这个主要是服务发布的协议配置,支持多种协议,比如说rest、bolt、等
我们点进源码会发现实际上它是跟前面我们讲的RegistryConfig是继承的同一个类,那我们这里就不赘述了,进入下一步构建发布配置,这个代码相对简单,主要就是将前面两步的配置放进ProviderConfig,那我们就愉快的进入最后一步,也是这篇文章的重点:服务发布!
// 4、正式发布 providerConfig.export(); /** * 发布服务 */ public synchronized void export() { if (providerBootstrap == null) { // 获取执行的 providerBootstrap providerBootstrap = Bootstraps.from(this); } // 使用获取的 providerBootstrap 执行发布 providerBootstrap.export(); } /** * 发布一个服务 * * @param providerConfig 服务发布者配置 * @param <T> 接口类型 * @return 发布启动类 */ public static <T> ProviderBootstrap<T> from(ProviderConfig<T> providerConfig) { // 如果我们没有设置bootstrap那就会使用默认的bootstrap String bootstrap = providerConfig.getBootstrap(); if (StringUtils.isEmpty(bootstrap)) { // Use default provider bootstrap,read from rpcconfigs,默认是 sofa bootstrap = RpcConfigs.getStringValue(RpcOptions.DEFAULT_PROVIDER_BOOTSTRAP); providerConfig.setBootstrap(bootstrap); } //获取执行的 export providerBootstrap默认是DefaultProviderBootstrap,这里有SPI的东西,等我补了直接看那篇文章即可 ProviderBootstrap providerBootstrap = ExtensionLoaderFactory.getExtensionLoader(ProviderBootstrap.class) .getExtension(bootstrap, new Class[] { ProviderConfig.class }, new Object[] { providerConfig }); return (ProviderBootstrap<T>) providerBootstrap; } // DefaultProviderBootstrap里面的export()方法 @Override public void export() { if (providerConfig.getDelay() > 0) { // 延迟加载,单位毫秒 Thread thread = factory.newThread(new Runnable() { @Override public void run() { try { Thread.sleep(providerConfig.getDelay()); } catch (Throwable ignore) { // NOPMD } doExport(); } }); thread.start(); } else { doExport(); } } private void doExport() { // 已经发布则直接retrurn if (exported) { return; } // 检查参数 checkParameters(); // 设置发布应用名称,比如我的设置就是 setApplication(new ApplicationConfig().setAppName("paul")) String appName = providerConfig.getAppName(); //key is the protocol of server,for concurrent safe Map<String, Boolean> hasExportedInCurrent = new ConcurrentHashMap<String, Boolean>(); // 将处理器注册到server List<ServerConfig> serverConfigs = providerConfig.getServer(); for (ServerConfig serverConfig : serverConfigs) { String protocol = serverConfig.getProtocol(); String key = providerConfig.buildKey() + ":" + protocol; if (LOGGER.isInfoEnabled(appName)) { LOGGER.infoWithApp(appName, "Export provider config : {} with bean id {}", key, providerConfig.getId()); } // 注意同一interface,同一uniqueId,不同server情况 AtomicInteger cnt = EXPORTED_KEYS.get(key); // 计数器 if (cnt == null) { // 没有发布过 cnt = CommonUtils.putToConcurrentMap(EXPORTED_KEYS, key, new AtomicInteger(0)); } int c = cnt.incrementAndGet(); hasExportedInCurrent.put(serverConfig.getProtocol(), true); int maxProxyCount = providerConfig.getRepeatedExportLimit(); if (maxProxyCount > 0) { if (c > maxProxyCount) { decrementCounter(hasExportedInCurrent); // 超过最大数量,直接抛出异常 throw new SofaRpcRuntimeException("Duplicate provider config with key " + key + " has been exported more than " + maxProxyCount + " times!" + " Maybe it's wrong config, please check it." + " Ignore this if you did that on purpose!"); } else if (c > 1) { if (LOGGER.isInfoEnabled(appName)) { LOGGER.infoWithApp(appName, "Duplicate provider config with key {} has been exported!" + " Maybe it's wrong config, please check it." + " Ignore this if you did that on purpose!", key); } } } } try { // 构造请求调用器 providerProxyInvoker = new ProviderProxyInvoker(providerConfig); // 初始化注册中心 if (providerConfig.isRegister()) { List<RegistryConfig> registryConfigs = providerConfig.getRegistry(); if (CommonUtils.isNotEmpty(registryConfigs)) { for (RegistryConfig registryConfig : registryConfigs) { RegistryFactory.getRegistry(registryConfig); // 提前初始化Registry } } } // 将处理器注册到server for (ServerConfig serverConfig : serverConfigs) { try { Server server = serverConfig.buildIfAbsent(); // 注册请求调用器 server.registerProcessor(providerConfig, providerProxyInvoker); if (serverConfig.isAutoStart()) { server.start(); } } catch (SofaRpcRuntimeException e) { throw e; } catch (Exception e) { LOGGER.errorWithApp(appName, "Catch exception when register processor to server: " + serverConfig.getId(), e); } } // 注册到注册中心 providerConfig.setConfigListener(new ProviderAttributeListener()); register(); } catch (Exception e) { decrementCounter(hasExportedInCurrent); if (e instanceof SofaRpcRuntimeException) { throw (SofaRpcRuntimeException) e; } else { throw new SofaRpcRuntimeException("Build provider proxy error!", e); } } // 记录一些缓存数据 RpcRuntimeContext.cacheProviderConfig(this); exported = true; }
我们先看看他主要做了哪些事情:
1、检查参数和方法
2、将处理器保存到ConcurrentMap
3、构造请求调用器,初始化注册中心
4、将处理器注册到server,注册请求调用器,注册到注册中心
5、记录一些缓存数据
开始分析:
1、检查参数和方法
/** * for check fields and parameters of consumer config */ protected void checkParameters() { // 检查注入的ref是否接口实现类 Class proxyClass = providerConfig.getProxyClass(); // key = interfaceId + CFG 默认配置的 uniqueId (为空) String key = providerConfig.buildKey(); T ref = providerConfig.getRef(); // 自身类.class.isInstance(自身实例或子类实例) 才返回true if (!proxyClass.isInstance(ref)) { throw ExceptionUtils.buildRuntime("provider.ref", ref == null ? "null" : ref.getClass().getName(), "This is not an instance of " + providerConfig.getInterfaceId() + " in provider config with key " + key + " !"); } // server 不能为空 if (CommonUtils.isEmpty(providerConfig.getServer())) { throw ExceptionUtils.buildRuntime("server", "NULL", "Value of \"server\" is not specified in provider" + " config with key " + key + " !"); } checkMethods(proxyClass); } /** * Gets proxy class. * * @return the proxyClass */ @Override public Class<?> getProxyClass() { if (proxyClass != null) { return proxyClass; } try { // 如果设置的interfaceId不为空 if (StringUtils.isNotBlank(interfaceId)) { // 反射拿到代理类 this.proxyClass = ClassUtils.forName(interfaceId); if (!proxyClass.isInterface()) { throw ExceptionUtils.buildRuntime("service.interfaceId", interfaceId, "interfaceId must set interface class, not implement class"); } } else { throw ExceptionUtils.buildRuntime("service.interfaceId", "null", "interfaceId must be not null"); } } catch (SofaRpcRuntimeException e) { throw e; } catch (Throwable e) { throw new SofaRpcRuntimeException(e.getMessage(), e); } return proxyClass; } /** * 检查方法,例如方法名、多态(重载)方法 * * @param itfClass 接口类 */ protected void checkMethods(Class<?> itfClass) { ConcurrentHashMap<String, Boolean> methodsLimit = new ConcurrentHashMap<String, Boolean>(); // 获取代理类以及父类或者父接口中所有的公共方法(public修饰符修饰的) for (Method method : itfClass.getMethods()) { String methodName = method.getName(); // 重载的方法会提示warn,sofa rpc不建议一个服务里使用多个同名方法 if (methodsLimit.containsKey(methodName)) { // 重名的方法 if (LOGGER.isWarnEnabled(providerConfig.getAppName())) { LOGGER.warnWithApp(providerConfig.getAppName(), "Method with same name \"" + itfClass.getName() + "." + methodName + "\" exists ! The usage of overloading method in rpc is deprecated."); } } // 判断服务下方法的黑白名单 Boolean include = methodsLimit.get(methodName); if (include == null) { // 检查是否在黑白名单中,黑白名单这两个都是在配置文件配置的 include = inList(providerConfig.getInclude(), providerConfig.getExclude(), methodName); methodsLimit.putIfAbsent(methodName, include); } } providerConfig.setMethodsLimit(methodsLimit); }
2、将处理器保存到ConcurrentMap
List<ServerConfig> serverConfigs = providerConfig.getServer(); for (ServerConfig serverConfig : serverConfigs) { // 获取发布协议,比如我们就配置了bolt 和rest 两个协议 String protocol = serverConfig.getProtocol(); // key = interfaceId + uniqueId + ":" + protocol String key = providerConfig.buildKey() + ":" + protocol; if (LOGGER.isInfoEnabled(appName)) { LOGGER.infoWithApp(appName, "Export provider config : {} with bean id {}", key, providerConfig.getId()); } // 注意同一interface,同一uniqueId,不同server情况 AtomicInteger cnt = EXPORTED_KEYS.get(key); // 计数器 if (cnt == null) { // 没有发布过 cnt = CommonUtils.putToConcurrentMap(EXPORTED_KEYS, key, new AtomicInteger(0)); } // 原子性自增 int c = cnt.incrementAndGet(); // 将发布过的协议放入hasExportedInCurrent hasExportedInCurrent.put(serverConfig.getProtocol(), true); // 获取最大可重复发布数,读取配置文件的,默认是 1 int maxProxyCount = providerConfig.getRepeatedExportLimit(); if (maxProxyCount > 0) { if (c > maxProxyCount) { // 超过最大数量,decrementCounter,里面就是将EXPORTED_KEYS.get(key)大于0的decrementAndGet decrementCounter(hasExportedInCurrent); // 超过最大数量,直接抛出异常 throw new SofaRpcRuntimeException("Duplicate provider config with key " + key + " has been exported more than " + maxProxyCount + " times!" + " Maybe it's wrong config, please check it." + " Ignore this if you did that on purpose!"); } else if (c > 1) { if (LOGGER.isInfoEnabled(appName)) { LOGGER.infoWithApp(appName, "Duplicate provider config with key {} has been exported!" + " Maybe it's wrong config, please check it." + " Ignore this if you did that on purpose!", key); } } } }
3、构造请求调用器,初始化注册中心
4、将处理器注册到server,注册请求调用器,注册到注册中心
5、记录一些缓存数据
这三点我们放一起讲吧:
try { // 构造请求调用器 providerProxyInvoker = new ProviderProxyInvoker(providerConfig); // 初始化注册中心 if (providerConfig.isRegister()) { List<RegistryConfig> registryConfigs = providerConfig.getRegistry(); if (CommonUtils.isNotEmpty(registryConfigs)) { for (RegistryConfig registryConfig : registryConfigs) { RegistryFactory.getRegistry(registryConfig); // 提前初始化Registry } } } // 将处理器注册到server for (ServerConfig serverConfig : serverConfigs) { try { Server server = serverConfig.buildIfAbsent(); // 注册请求调用器 server.registerProcessor(providerConfig, providerProxyInvoker); if (serverConfig.isAutoStart()) { server.start(); } } catch (SofaRpcRuntimeException e) { throw e; } catch (Exception e) { LOGGER.errorWithApp(appName, "Catch exception when register processor to server: " + serverConfig.getId(), e); } } // 注册到注册中心 providerConfig.setConfigListener(new ProviderAttributeListener()); register(); } catch (Exception e) { // 捕获异常先对发布服务数decrement一下 decrementCounter(hasExportedInCurrent); if (e instanceof SofaRpcRuntimeException) { throw (SofaRpcRuntimeException) e; } else { throw new SofaRpcRuntimeException("Build provider proxy error!", e); } } // 记录一些缓存数据 RpcRuntimeContext.cacheProviderConfig(this); exported = true;
首先来看下构造请求调用器
/** * 构造执行链 * * @param providerConfig 服务端配置 */ public ProviderProxyInvoker(ProviderConfig providerConfig) { this.providerConfig = providerConfig; // 最底层是调用过滤器 this.filterChain = FilterChain.buildProviderChain(providerConfig, new ProviderInvoker(providerConfig)); }
我们就来看下最底层是调用过滤器这里做了些什么:
/** * Instantiates a new Provider invoke filter. * * @param providerConfig the provider config */ public ProviderInvoker(ProviderConfig<T> providerConfig) { // 调用父类构造方法 super(providerConfig); this.providerConfig = providerConfig; } /** * 如果无需下一层过滤器 * * @param config 过滤器所在的接口配置 */ protected FilterInvoker(AbstractInterfaceConfig config) { this.config = config; if (config != null) { this.configContext = config.getConfigValueCache(false); } } /** * 接口属性和方法属性加载配置到缓存 * * @param rebuild 是否重建 * @return Map<String Object> unmodifiableMap */ public synchronized Map<String, Object> getConfigValueCache(boolean rebuild) { // 第一次进来 configValueCache 是空的 if (configValueCache != null && !rebuild) { return configValueCache; } Map<String, Object> context = new HashMap<String, Object>(32); // providerParams 也是空的 Map<String, String> providerParams = getParameters(); if (providerParams != null) { context.putAll(providerParams); // 复制接口的自定义参数 } // methodConfigs 也是空的 Map<String, MethodConfig> methodConfigs = getMethods(); if (CommonUtils.isNotEmpty(methodConfigs)) { for (MethodConfig methodConfig : methodConfigs.values()) { String prefix = RpcConstants.HIDE_KEY_PREFIX + methodConfig.getName() + RpcConstants.HIDE_KEY_PREFIX; Map<String, String> methodparam = methodConfig.getParameters(); if (methodparam != null) { // 复制方法级自定义参数 for (Map.Entry<String, String> entry : methodparam.entrySet()) { context.put(prefix + entry.getKey(), entry.getValue()); } } // 复制方法级参数属性 BeanUtils.copyPropertiesToMap(methodConfig, prefix, context); } } // 复制接口级参数属性,可以看出第一次初始化时直接把providerConfig的属性配置都赋值到了context上 BeanUtils.copyPropertiesToMap(this, StringUtils.EMPTY, context); // 这里的configValueCache 的值实际上就是providerConfig的,并且使用unmodifiableMap保存 configValueCache = Collections.unmodifiableMap(context); return configValueCache; }
然后就只剩下这个方法啦:FilterChain.buildProviderChain(providerConfig,new ProviderInvoker(providerConfig));点进去
/** * 构造服务端的执行链 * * @param providerConfig provider配置 * @param lastFilter 最后一个filter * @return filter执行链 */ public static FilterChain buildProviderChain(ProviderConfig<?> providerConfig, FilterInvoker lastFilter) { return new FilterChain(selectActualFilters(providerConfig, PROVIDER_AUTO_ACTIVES), lastFilter, providerConfig); } /** * 获取真正的过滤器列表 * * @param config provider配置或者consumer配置 * @param autoActiveFilters 系统自动激活的过滤器映射 * @return 真正的过滤器列表 */ private static List<Filter> selectActualFilters(AbstractInterfaceConfig config, Map<String, ExtensionClass<Filter>> autoActiveFilters) { /* * 例如自动装载扩展 A(a),B(b),C(c) filter=[-a,d] filterRef=[new E, new Exclude(b)] * 逻辑如下: * 1.解析config.getFilterRef(),记录E和-b * 2.解析config.getFilter()字符串,记录 d 和 -a,-b * 3.再解析自动装载扩展,a,b被排除了,所以拿到c,d * 4.对c d进行排序 * 5.拿到C、D实现类 * 6.加上自定义,返回C、D、E */ // 用户通过自己new实例的方式注入的filter,优先级高 List<Filter> customFilters = config.getFilterRef() == null ? new ArrayList<Filter>() : new CopyOnWriteArrayList<Filter>(config.getFilterRef()); // 先解析是否有特殊处理 HashSet<String> excludes = parseExcludeFilter(customFilters); // 准备数据:用户通过别名的方式注入的filter,需要解析 List<ExtensionClass<Filter>> extensionFilters = new ArrayList<ExtensionClass<Filter>>(); List<String> filterAliases = config.getFilter(); // if (CommonUtils.isNotEmpty(filterAliases)) { for (String filterAlias : filterAliases) { if (startsWithExcludePrefix(filterAlias)) { // 排除用的特殊字符 excludes.add(filterAlias.substring(1)); } else { ExtensionClass<Filter> filter = EXTENSION_LOADER.getExtensionClass(filterAlias); if (filter != null) { extensionFilters.add(filter); } } } } // 解析自动加载的过滤器,配了-*和-default表示不加载内置 if (!excludes.contains(StringUtils.ALL) && !excludes.contains(StringUtils.DEFAULT)) { for (Map.Entry<String, ExtensionClass<Filter>> entry : autoActiveFilters.entrySet()) { if (!excludes.contains(entry.getKey())) { extensionFilters.add(entry.getValue()); } } } // 按order从小到大排序 if (extensionFilters.size() > 1) { Collections.sort(extensionFilters, new OrderedComparator<ExtensionClass<Filter>>()); } List<Filter> actualFilters = new ArrayList<Filter>(); for (ExtensionClass<Filter> extensionFilter : extensionFilters) { actualFilters.add(extensionFilter.getExtInstance()); } // 加入自定义的过滤器 actualFilters.addAll(customFilters); return actualFilters; }
这个获取filterchain注释写的比较清楚,我这里就不再补充了,看下一段
// 初始化注册中心 if (providerConfig.isRegister()) { // 获取我们配置的registryConfigs List<RegistryConfig> registryConfigs = providerConfig.getRegistry(); if (CommonUtils.isNotEmpty(registryConfigs)) { for (RegistryConfig registryConfig : registryConfigs) { // 提前初始化Registry RegistryFactory.getRegistry(registryConfig); } } } /** * 得到注册中心对象 * * @param registryConfig RegistryConfig类 * @return Registry实现 */ public static synchronized Registry getRegistry(RegistryConfig registryConfig) { if (ALL_REGISTRIES.size() > 3) { // 超过3次 是不是配错了? if (LOGGER.isWarnEnabled()) { LOGGER.warn("Size of registry is greater than 3, Please check it!"); } } try { // 注意:RegistryConfig重写了equals方法,如果多个RegistryConfig属性一样,则认为是一个对象 Registry registry = ALL_REGISTRIES.get(registryConfig); if (registry == null) { // spi 根据配置的协议找对应的扩展类加载,这里会加载所有的Registry扩展类 sofa,zookeeper ExtensionClass<Registry> ext = ExtensionLoaderFactory.getExtensionLoader(Registry.class) .getExtensionClass(registryConfig.getProtocol()); if (ext == null) { throw ExceptionUtils.buildRuntime("registry.protocol", registryConfig.getProtocol(), "Unsupported protocol of registry config !"); } // 实例化扩展类 registry = ext.getExtInstance(new Class[] { RegistryConfig.class }, new Object[] { registryConfig }); // 放入ALL_REGISTRIES供后面register使用 ALL_REGISTRIES.put(registryConfig, registry); } return registry; } catch (SofaRpcRuntimeException e) { throw e; } catch (Throwable e) { throw new SofaRpcRuntimeException(e.getMessage(), e); } }
下一段:
// 将处理器注册到server for (ServerConfig serverConfig : serverConfigs) { try { // 循环构建server Server server = serverConfig.buildIfAbsent(); // 注册请求调用器 server.registerProcessor(providerConfig, providerProxyInvoker); if (serverConfig.isAutoStart()) { server.start(); } } catch (SofaRpcRuntimeException e) { throw e; } catch (Exception e) { LOGGER.errorWithApp(appName, "Catch exception when register processor to server: " + serverConfig.getId(), e); } } /** * 启动服务 * * @return the server */ public synchronized Server buildIfAbsent() { if (server != null) { return server; } // 提前检查协议+序列化方式 // ConfigValueHelper.check(ProtocolType.valueOf(getProtocol()), // SerializationType.valueOf(getSerialization())); // 使用serverFactory初始化server server = ServerFactory.getServer(this); return server; } /** * 初始化Server实例 * * @param serverConfig 服务端配置 * @return Server */ public synchronized static Server getServer(ServerConfig serverConfig) { try { Server server = SERVER_MAP.get(Integer.toString(serverConfig.getPort())); if (server == null) { // 绑定网卡和端口,下面有详细分析 resolveServerConfig(serverConfig); // SPI加载server扩展类,比如说BoltServer,RestServer ExtensionClass<Server> ext = ExtensionLoaderFactory.getExtensionLoader(Server.class) .getExtensionClass(serverConfig.getProtocol()); if (ext == null) { throw ExceptionUtils.buildRuntime("server.protocol", serverConfig.getProtocol(), "Unsupported protocol of server!"); } // 获取server实例 server = ext.getExtInstance(); // 初始化server,这里面主要是初始化业务线程池和初始化配置协议的ServerProcessor,比如我们用bolt协议就是 // BoltServer 和 BoltServerProcessor server.init(serverConfig); SERVER_MAP.put(serverConfig.getPort() + "", server); } return server; } catch (SofaRpcRuntimeException e) { throw e; } catch (Throwable e) { throw new SofaRpcRuntimeException(e.getMessage(), e); } } /** * 确定下Server的host和port * * @param serverConfig 服务器配置 */ private static void resolveServerConfig(ServerConfig serverConfig) { // 绑定到指定网卡 或全部网卡 String boundHost = serverConfig.getBoundHost(); // 我们没有配置boundHost if (boundHost == null) { // 我们也没配置host String host = serverConfig.getHost(); if (StringUtils.isBlank(host)) { // 获取系统本地host host = SystemInfo.getLocalHost(); serverConfig.setHost(host); // windows绑定到0.0.0.0的某个端口以后,其它进程还能绑定到该端口 boundHost = SystemInfo.isWindows() ? host : NetUtils.ANYHOST; } else { boundHost = host; } serverConfig.setBoundHost(boundHost); } // 绑定的端口 if (serverConfig.isAdaptivePort()) { int oriPort = serverConfig.getPort(); int port = NetUtils.getAvailablePort(boundHost, oriPort, RpcConfigs.getIntValue(RpcOptions.SERVER_PORT_END)); if (port != oriPort) { if (LOGGER.isInfoEnabled()) { LOGGER.info("Changed port from {} to {} because the config port is disabled", oriPort, port); } serverConfig.setPort(port); } } } 接下来就是 // 注册请求调用器,BoltServer server.registerProcessor(providerConfig, providerProxyInvoker); @Override public void registerProcessor(ProviderConfig providerConfig, Invoker instance) { // 获取唯一名字key String key = ConfigUniqueNameGenerator.getUniqueName(providerConfig); // 缓存Invoker对象 invokerMap.put(key, instance); // 放入回收失效缓存中 ReflectCache.registerServiceClassLoader(key, providerConfig.getProxyClass().getClassLoader()); // 缓存接口的方法,这里主要是将每个代理接口的方法和参数缓存起来 for (Method m : providerConfig.getProxyClass().getMethods()) { ReflectCache.putOverloadMethodCache(key, m); } } 好了,到下一段: if (serverConfig.isAutoStart()) { server.start(); } @Override public void start() { if (started) { return; } synchronized (this) { if (started) { return; } // 生成Server对象,这里调用的阿里的另外一个开源框架 SOFA BOLT,传入绑定绑定host和port remotingServer = initRemotingServer(); try { if (remotingServer.start()) { if (LOGGER.isInfoEnabled()) { LOGGER.info("Bolt server has been bind to {}:{}", serverConfig.getBoundHost(), serverConfig.getPort()); } } else { throw new SofaRpcRuntimeException("Failed to start bolt server, see more detail from bolt log."); } started = true; // 是否开启服务启动消息总线 if (EventBus.isEnable(ServerStartedEvent.class)) { // 发布f服务启动事件 EventBus.post(new ServerStartedEvent(serverConfig, bizThreadPool)); } } catch (SofaRpcRuntimeException e) { throw e; } catch (Exception e) { throw new SofaRpcRuntimeException("Failed to start bolt server!", e); } } }
到这里服务发布已经完成,但是我们前面讲了只是初始化注册,提前暴露注册中心的配置或者其他问题,并没有真的注册,那么就到了最后一段代码了:
// 添加监听器 providerConfig.setConfigListener(new ProviderAttributeListener()); // 注册到注册中心 register(); /** * 注册服务 */ protected void register() { if (providerConfig.isRegister()) { List<RegistryConfig> registryConfigs = providerConfig.getRegistry(); if (registryConfigs != null) { for (RegistryConfig registryConfig : registryConfigs) { // 老规矩还是根据registryConfig加载扩展类registry,但是我们上面初始化已经分析了这里就跳过 Registry registry = RegistryFactory.getRegistry(registryConfig); // 初始化配置,拿zookeeper打比方就是初始化zkClient,添加认证信息等 registry.init(); // 连接至zk registry.start(); try { // 注册和订阅服务 registry.register(providerConfig); } catch (SofaRpcRuntimeException e) { throw e; } catch (Throwable e) { String appName = providerConfig.getAppName(); if (LOGGER.isWarnEnabled(appName)) { LOGGER.warnWithApp(appName, "Catch exception when register to registry: " + registryConfig.getId(), e); } } } } } }
SOFARPC服务发布流程概括为SOFARPC服务需要创建服务运行容器配置ServerConfig,自定义设置基础配置并且通过配置文件加载服务端默认配置;创建服务发布配置ProviderConfig,自定义设置接口名称、接口实现类引用以及指定服务端配置;服务发布启动类ProviderBootstrap发布服务:构造请求调用器ProviderProxyInvoker(最底层调用过滤器执行链FilterChain),提前初始化注册中心,创建服务端Server包括启动业务线程池bizThreadPool 、创建BoltServerProcessor处理器,服务端Server注册服务提供者配置ProviderConfig、服务端调用实现ProviderProxyInvoker,服务端Server启动服务创建RpcServer,将BoltServerProcessor处理器缓存到userProcessors,初始化服务启动ServerBootstrap,根据userProcessors创建RpcHandler处理器添加到ChannelPipeline,创建RPC服务连接完成启动服务链路。RPC服务请求调用RpcHandler的channelRead()方法获取UserProcessor执行handlerRequest()方法查找服务调用器Invoker实施调用过滤器执行链FilterChain方法调用。