有一阵子没有更新源码解析了,最近关注了一个微服务框架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 registryConfigs = new ArrayList();
registryConfigs.add(registryConfig);
registryConfigs.add(registryConfig1);
// 2、构建ServerConfig 服务配置
List serverConfigs = new ArrayList();
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 providerConfig = new ProviderConfig()
.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 registryConfigs = new ArrayList();
首先是构建RegistryConfig注册配置,这个主要是用来注册服务使用的,可以支持多个协议:
文中举例使用了sofa 和 zookeeper 的注册中心,我们点进去源码发现是这样的:
public class RegistryConfig extends AbstractIdConfig implements Serializable
...
发现它是空构造方法,那它真的什么都没做吗?不是!它继承了AbstractIdConfig这个类,我们点进去这个类是这样的:
public abstract class 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 loader = ExtensionLoaderFactory.getExtensionLoader(Module.class);
// 获取需要加载的模块配置
String moduleLoadList = RpcConfigs.getStringValue(RpcOptions.MODULE_LOAD_LIST);
for (Map.Entry> 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 接口类型
* @return 发布启动类
*/
public static ProviderBootstrap from(ProviderConfig 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) 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 hasExportedInCurrent = new ConcurrentHashMap();
// 将处理器注册到server
List 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 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 methodsLimit = new ConcurrentHashMap();
// 获取代理类以及父类或者父接口中所有的公共方法(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 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 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 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 unmodifiableMap
*/
public synchronized Map getConfigValueCache(boolean rebuild) {
// 第一次进来 configValueCache 是空的
if (configValueCache != null && !rebuild) {
return configValueCache;
}
Map context = new HashMap(32);
// providerParams 也是空的
Map providerParams = getParameters();
if (providerParams != null) {
context.putAll(providerParams); // 复制接口的自定义参数
}
// methodConfigs 也是空的
Map methodConfigs = getMethods();
if (CommonUtils.isNotEmpty(methodConfigs)) {
for (MethodConfig methodConfig : methodConfigs.values()) {
String prefix = RpcConstants.HIDE_KEY_PREFIX + methodConfig.getName()
+ RpcConstants.HIDE_KEY_PREFIX;
Map methodparam = methodConfig.getParameters();
if (methodparam != null) { // 复制方法级自定义参数
for (Map.Entry 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 selectActualFilters(AbstractInterfaceConfig config,
Map> 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 customFilters = config.getFilterRef() == null ?
new ArrayList() : new CopyOnWriteArrayList(config.getFilterRef());
// 先解析是否有特殊处理
HashSet excludes = parseExcludeFilter(customFilters);
// 准备数据:用户通过别名的方式注入的filter,需要解析
List> extensionFilters = new ArrayList>();
List filterAliases = config.getFilter(); //
if (CommonUtils.isNotEmpty(filterAliases)) {
for (String filterAlias : filterAliases) {
if (startsWithExcludePrefix(filterAlias)) { // 排除用的特殊字符
excludes.add(filterAlias.substring(1));
} else {
ExtensionClass filter = EXTENSION_LOADER.getExtensionClass(filterAlias);
if (filter != null) {
extensionFilters.add(filter);
}
}
}
}
// 解析自动加载的过滤器,配了-*和-default表示不加载内置
if (!excludes.contains(StringUtils.ALL) && !excludes.contains(StringUtils.DEFAULT)) {
for (Map.Entry> entry : autoActiveFilters.entrySet()) {
if (!excludes.contains(entry.getKey())) {
extensionFilters.add(entry.getValue());
}
}
}
// 按order从小到大排序
if (extensionFilters.size() > 1) {
Collections.sort(extensionFilters, new OrderedComparator>());
}
List actualFilters = new ArrayList();
for (ExtensionClass extensionFilter : extensionFilters) {
actualFilters.add(extensionFilter.getExtInstance());
}
// 加入自定义的过滤器
actualFilters.addAll(customFilters);
return actualFilters;
}
这个获取filterchain注释写的比较清楚,我这里就不再补充了,看下一段
// 初始化注册中心
if (providerConfig.isRegister()) {
// 获取我们配置的registryConfigs
List 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 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 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 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方法调用。