Dubboサービス起動プロセス(一)
9962 ワード
以前はいくつかのDubboのソースコードを読んだことがありますが、一つの問題はしばらくしてから見に行くととても見慣れていないことです.そして、自分が最後にどの位置まで読んだのか分からないことがよくあります.そして、自分が以前蓄積した内容も記録の場所がないので、今回から記録をして、自分が勉強したノートだと思っています.
ガイド人
Dubboの起動は主にサービスを公開するプロセスであり、核心的な役割を果たすのはServiceConfig(ServiceConfigは私たちがDubboのプロファイルで構成したdubbo:serviceなどの構成項目に対応するエンティティクラス)である.サービスの開始初期位置も基本的にここにありますが、具体的な実装内容を見てみましょう.基本的な内容を話す前に、まずいくつかの名詞概念を明らかにします:Invoker:Invokerの概念私たちはダイナミックエージェントの時に接触したことがあります.中国語の意味はたぶん実行者で、ここでは実際に具体的な方法の実行者と理解することができます.その核心内容は大体以下の通りである. Class getInterface(); Result invoke(Invocation invocation) throws RpcException; URL getUrl(); 以上の3つの方法により,具体的な方法を実行し,方法の実行結果を得ることができる.実行する必要がある方法の具体的な実装の詳細をgetUrlによって取得し、主に具体的なrefを得る.次に、組立方法のパラメータ情報など、invocationにはパッケージされています.最後にinvokeメソッドを実行することによって特定のメソッドがトリガーされ、結果が返されます.ここから,Invokerは具体的な方法で実行される最後のゲートウェイ者であり,Invokerを取得すると,具体的なインタフェースのコードが得られ,その後エージェントを実行すればよいことが分かる.Invokerは、Duubo呼び出しをローカルで実行するエージェントだけでなく、RPCのときのエージェントとしても機能し、複数のInvokerが集約されたエージェント(主にクラスタを処理するいくつかのポリシー、負荷等化やルーティングなどを含む)に自分をパッケージするエージェントとしての顔にすぎない.
Exporter:サービス暴露の過程でInvokerをExporter(暴露者)に変換し、主に異なるレベルのサービス発表に使用されるInvokerが含まれています.実はDubboにはProtocol、Exchangerなど、重要なオブジェクトがあります.ここで直接説明するのは適切ではないと思いますので、私たちが使ってから説明を始めます.
1.コアの属性情報
いくつかの基本的な属性:group、version、interfaceName、interfaceClass、timeoutなど.dubbo:serviceで構成できる属性は、ServiceConfigで対応する属性を見つけることができます.
//dubbo対応のサービスリリースプロトコルは、Dubboがここで使用している独自のspiメカニズムを明確に見ることができ、柔軟性を保証します.(SPIメカニズムの具体的な実装については、後で機会があれば、簡単に理解するとgetExtensionLoaderによって対応するクラスの拡張クラス実装クラスが得られる)private static final Protocol protocol=ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
//ProxyFactory(エージェントのファクトリクラスを生成し、具体的な実装クラスをInvokerにパッケージする)の拡張クラスprivate static final ProxyFactory proxyFactory=ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
//urlsは主に使用されたurl(urlはdubbo内部通信の情報キャリア、Exporterはサービス露出の主な出口オブジェクト)private final List urls=new ArrayList()を格納する.private final List> exporters = new ArrayList>();
2.サービス暴露プロセス
サービス露出にとって、ServiceConfigでの最初の方法はexport()メソッドです.次に、exportメソッドから見てみましょう.
ServiceConfigの内容分解により,主に次のような内容が行われていることが分かる.検査に必要なパラメータの正当性 は、多層のパラメータ(再構成可能)を最終的に最終的な結果(map)に整理し、パラメータに基づいてサービスが必要とするurlを暴露するように接合する. generic,Stub,injvmなど他のサポートが必要なコンテンツを処理し,dubboの機能多様性を補完するが,コアプロセスには関与しない. は、対応するプロトコルに従ってサービスを暴露し(サービス呼び出し者の発見のために提供されたサービスを登録センターにプッシュ)、デフォルトでDubboプロトコルを使用する.
その中で最も核心的な暴露の流れはこの篇で関連していないで、次の章で具体的な暴露の過程を発表します(==内輪の出た内容は具体的な暴露の過程です
ガイド人
Dubboの起動は主にサービスを公開するプロセスであり、核心的な役割を果たすのはServiceConfig(ServiceConfigは私たちがDubboのプロファイルで構成したdubbo:serviceなどの構成項目に対応するエンティティクラス)である.サービスの開始初期位置も基本的にここにありますが、具体的な実装内容を見てみましょう.基本的な内容を話す前に、まずいくつかの名詞概念を明らかにします:Invoker:Invokerの概念私たちはダイナミックエージェントの時に接触したことがあります.中国語の意味はたぶん実行者で、ここでは実際に具体的な方法の実行者と理解することができます.その核心内容は大体以下の通りである.
Exporter:サービス暴露の過程でInvokerをExporter(暴露者)に変換し、主に異なるレベルのサービス発表に使用されるInvokerが含まれています.実はDubboにはProtocol、Exchangerなど、重要なオブジェクトがあります.ここで直接説明するのは適切ではないと思いますので、私たちが使ってから説明を始めます.
1.コアの属性情報
いくつかの基本的な属性:group、version、interfaceName、interfaceClass、timeoutなど.dubbo:serviceで構成できる属性は、ServiceConfigで対応する属性を見つけることができます.
//dubbo対応のサービスリリースプロトコルは、Dubboがここで使用している独自のspiメカニズムを明確に見ることができ、柔軟性を保証します.(SPIメカニズムの具体的な実装については、後で機会があれば、簡単に理解するとgetExtensionLoaderによって対応するクラスの拡張クラス実装クラスが得られる)private static final Protocol protocol=ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
//ProxyFactory(エージェントのファクトリクラスを生成し、具体的な実装クラスをInvokerにパッケージする)の拡張クラスprivate static final ProxyFactory proxyFactory=ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
//urlsは主に使用されたurl(urlはdubbo内部通信の情報キャリア、Exporterはサービス露出の主な出口オブジェクト)private final List urls=new ArrayList()を格納する.private final List> exporters = new ArrayList>();
2.サービス暴露プロセス
サービス露出にとって、ServiceConfigでの最初の方法はexport()メソッドです.次に、exportメソッドから見てみましょう.
public synchronized void export() {
if (provider != null) {
// provider
if (export == null) {
export = provider.getExport();
}
if (delay == null) {
delay = provider.getDelay();
}
}
// export false
if (export != null && ! export.booleanValue()) {
return;
}
//
if (delay != null && delay > 0) {
Thread thread = new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(delay);
} catch (Throwable e) {
}
doExport();
}
});
thread.setDaemon(true);//
thread.setName("DelayExportServiceThread");
thread.start();
} else {
doExport(); // doExport 。
}
}
protected synchronized void doExport() {
//
//
//
if (ref instanceof GenericService) {
interfaceClass = GenericService.class;
if (StringUtils.isEmpty(generic)) {
generic = Boolean.TRUE.toString();
}
} else {
try {// (interfaceName )
interfaceClass = Class.forName(interfaceName, true, Thread.currentThread()
.getContextClassLoader());
} catch (ClassNotFoundException e) {
throw new IllegalStateException(e.getMessage(), e);
}
//
checkInterfaceAndMethods(interfaceClass, methods);
// ,
checkRef();
// , generic false
generic = Boolean.FALSE.toString();
}
// Local Stub
// Application,Registry,Protocol
//
appendProperties(this);
// Local,Stub Mock
// ,
doExportUrls();
}
private void doExportUrls() {
// URL
List registryURLs = loadRegistries(true);
for (ProtocolConfig protocolConfig : protocols) {
//
doExportUrlsFor1Protocol(protocolConfig, registryURLs);
}
}
private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List registryURLs) {
// Dubbo
// host
// ( )
// map , , timeout, Application,provider,service , , map 。
Map map = new HashMap();
if (anyhost) { // anyhost true
map.put(Constants.ANYHOST_KEY, "true");
}
//
// application,module,provider,protocol service map
// map 。 , :ServiceConfig->PrtocolConfig->ProviderConfig->ModuleConfig->ApplicaionConfig
// method
//
if (ProtocolUtils.isGeneric(generic)) {
map.put("generic", generic);
map.put("methods", Constants.ANY_VALUE);
} else {
String revision = Version.getVersion(interfaceClass, version);
if (revision != null && revision.length() > 0) {
map.put("revision", revision);
}
// interfaceClass , wapper
// http://blog.csdn.net/quhongwei_zhanqiu/article/details/41597261 Wapper
String[] methods = Wrapper.getWrapper(interfaceClass).getMethodNames();
if(methods.length == 0) {
logger.warn("NO method found in service interface " + interfaceClass.getName());
map.put("methods", Constants.ANY_VALUE);
}
else {
//
map.put("methods", StringUtils.join(new HashSet(Arrays.asList(methods)), ","));
}
}
// token
// injvm ( Dubbo )
// URL , map URL
URL url = new URL(name, host, port, (contextPath == null || contextPath.length() == 0 ? "" : contextPath + "/") + path, map);
// ,
String scope = url.getParameter(Constants.SCOPE_KEY);
// none
if (! Constants.SCOPE_NONE.toString().equalsIgnoreCase(scope)) {
// remote ( remote, )
if (!Constants.SCOPE_REMOTE.toString().equalsIgnoreCase(scope)) {
exportLocal(url);
}
// local .( local, )
if (! Constants.SCOPE_LOCAL.toString().equalsIgnoreCase(scope) ){
if (logger.isInfoEnabled()) {
logger.info("Export dubbo service " + interfaceClass.getName() + " to url " + url);
}
if (registryURLs != null && registryURLs.size() > 0
&& url.getParameter("register", true)) {
for (URL registryURL : registryURLs) {
//dynamic ( )
url = url.addParameterIfAbsent("dynamic", registryURL.getParameter("dynamic"));
URL monitorUrl = loadMonitor(registryURL);
if (monitorUrl != null) {
url = url.addParameterAndEncoded(Constants.MONITOR_KEY, monitorUrl.toFullString());
}
if (logger.isInfoEnabled()) {
logger.info("Register dubbo service " + interfaceClass.getName() + " url " + url + " to registry " + registryURL);
}
====================================================
// invoker (ref )
Invoker> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, registryURL.addParameterAndEncoded(Constants.EXPORT_KEY, url.toFullString()));
// invoker exporter
Exporter> exporter = protocol.export(invoker);
exporters.add(exporter); // exporter
}
================================================================
} else {
//
Invoker> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, url);
Exporter> exporter = protocol.export(invoker);
exporters.add(exporter);
}
}
}
// url , 。
this.urls.add(url);
}
ServiceConfigの内容分解により,主に次のような内容が行われていることが分かる.
その中で最も核心的な暴露の流れはこの篇で関連していないで、次の章で具体的な暴露の過程を発表します(==内輪の出た内容は具体的な暴露の過程です