序文
最終講義が既にEurekaClientに起動プロセスを説明し、そこにソースコード解析のユーレカの記事6、あまりにも多くのコードコンポーネントの読書に影響する感じ、次回の前の記事を読んで、メインコードの後者の意志のみ傍受にあり、プラスコメントを説明します。
この講義はもちろん、コア、タイトルはそれを見事な理由に書き込まれます、EurekaClient登録プロセスを探していますか?コードEurekaClient登録について、それはそう簡単には見つかりません。
転載は、ソースを明記してください必要があります。花の数がロマンチック
ソースコード解析
学生は、以前の記事を読んでいれば知っている、確かに、ユーレカクライアントは最終的にプロセスがDiscoveryClientにこのクラスを初期化することで開始します、我々は、このクラスから直接分析を開始し、重要なコードのコードのみを傍受した後、我々は特定のソースに自己参照することができます。
DiscoveryClient.java
@Inject
DiscoveryClient(ApplicationInfoManager applicationInfoManager, EurekaClientConfig config, AbstractDiscoveryClientOptionalArgs args,
Provider<BackupRegistry> backupRegistryProvider) {
// 省略部分代码...
this.applicationInfoManager = applicationInfoManager;
// 创建一个配置实例,这里面会有eureka的各种信息,看InstanceInfo类的注释为:The class that holds information required for registration with Eureka Server
// and to be discovered by other components.
InstanceInfo myInfo = applicationInfoManager.getInfo();
// 省略部分代码...
try {
// 支持底层的eureka client跟eureka server进行网络通信的组件
eurekaTransport = new EurekaTransport();
// 发送http请求,调用restful接口
scheduleServerEndpointTask(eurekaTransport, args);
} catch (Throwable e) {
throw new RuntimeException("Failed to initialize DiscoveryClient!", e);
}
// 初始化调度任务
initScheduledTasks();
}
また、以前の記事で言及しているコードの多くを、省略の上、正直ここにまだ本に強制吐き気の外観、エントランスを見るためにそれで?いいえ、以下のゆっくりと分析を急ぎます。
DiscoveryClient.java
private void initScheduledTasks() {
// 省略大部分代码,这段代码是初始化eureka client的一些调度任务
// InstanceInfo replicator
// 创建服务拷贝副本
instanceInfoReplicator = new InstanceInfoReplicator(
this,
instanceInfo,
clientConfig.getInstanceInfoReplicationIntervalSeconds(),
2); // burstSize
// 执行线程 InitialInstanceInfoReplicationIntervalSeconds默认为40s
instanceInfoReplicator.start(clientConfig.getInitialInstanceInfoReplicationIntervalSeconds());
}
DiscoveryClientは、ソースの上にまだある、私たちはここを参照してくださいするメソッドの名前を知っているEurekaClientが開始初期間違いなくタスクのタイミングに関連しています。
ここでは主に傍受されinstanceInfoReplicator
、初期化の実行instanceInfoReplicator.start
タスク、
その後、我々は、この線に沿って見てとることができますInstatnceInfoReplicator
の背後にある物語とは?
/**
* A task for updating and replicating the local instanceinfo to the remote server. Properties of this task are:
* - configured with a single update thread to guarantee sequential update to the remote server
* - update tasks can be scheduled on-demand via onDemandUpdate()
* - task processing is rate limited by burstSize
* - a new update task is always scheduled automatically after an earlier update task. However if an on-demand task
* is started, the scheduled automatic update task is discarded (and a new one will be scheduled after the new
* on-demand update).
*
* 用于将本地instanceinfo更新和复制到远程服务器的任务。此任务的属性是:
* -配置有单个更新线程以保证对远程服务器的顺序更新
* -可以通过onDemandUpdate()按需调度更新任务
* -任务处理的速率受burstSize的限制
* -新更新总是在较早的更新任务之后自动计划任务。但是,如果启动了按需任务*,则计划的自动更新任务将被丢弃(并且将在新的按需更新之后安排新的任务)
*/
class InstanceInfoReplicator implements Runnable {
}
二つの重要なポイントがあります。
- このクラスを実装
Runnable
インタフェースを、それが非同期実行スレッドを意味し、 - このクラスアクションは次のとおりです。リモートサーバーのタスクへの更新や複製のためのローカルinstanceinfo
これら2つの点を読んだ後、私は助けることはできませんが、思考に陥り、私は、あなたがたは、これが今後に行ってきましたeurekaClient登録プロセス、を探していますか?和解、その後にお読みください。
InstanceInfoReplicator.start()
public void start(int initialDelayMs) {
if (started.compareAndSet(false, true)) {
instanceInfo.setIsDirty(); // for initial register
Future next = scheduler.schedule(this, initialDelayMs, TimeUnit.SECONDS);
scheduledPeriodicRef.set(next);
}
}
これは、このスレッドは、スレッドプールに入れ、その後、指定した時間後にこのスレッドのrunメソッドを実行され、スケジュールされたタスクスケジューラスレッドプールです。
InstanceInfoReplicator.run()
public void run() {
try {
// 刷新一下服务实例信息
discoveryClient.refreshInstanceInfo();
Long dirtyTimestamp = instanceInfo.isDirtyWithTime();
if (dirtyTimestamp != null) {
discoveryClient.register();
instanceInfo.unsetIsDirty(dirtyTimestamp);
}
} catch (Throwable t) {
logger.warn("There was a problem with the instance info replicator", t);
} finally {
Future next = scheduler.schedule(this, replicationIntervalSeconds, TimeUnit.SECONDS);
scheduledPeriodicRef.set(next);
}
}
ここを参照してください突然感のようなものではないのですか?ソウは、register
ここで使用し、ここで希望は、DiscoveryClient.register方法であると感じ、実際には、ここで我々は、メソッドDiscoveryClientを登録するために誰か、再度ペッグ発信者を見つけることができ、これは死ぬには良いアイデアです。
DiscoveryClient.register
boolean register() throws Throwable {
logger.info(PREFIX + appPathIdentifier + ": registering service...");
EurekaHttpResponse<Void> httpResponse;
try {
// 回看eurekaTransport创建及初始化过程
httpResponse = eurekaTransport.registrationClient.register(instanceInfo);
} catch (Exception e) {
logger.warn("{} - registration failed {}", PREFIX + appPathIdentifier, e.getMessage(), e);
throw e;
}
if (logger.isInfoEnabled()) {
logger.info("{} - registration status: {}", PREFIX + appPathIdentifier, httpResponse.getStatusCode());
}
return httpResponse.getStatusCode() == 204;
}
ここで登録する利用eurekaTransport.registrationClientがあり、我々は始まるDiscoveryClientコンストラクタであり、インターセプトeurekaTransportの作成と初期化コードがあり、それをここに貼り付けます。
// 支持底层的eureka client跟eureka server进行网络通信的组件
eurekaTransport = new EurekaTransport();
// 发送http请求,调用restful接口
scheduleServerEndpointTask(eurekaTransport, args);
private void scheduleServerEndpointTask(EurekaTransport eurekaTransport,
AbstractDiscoveryClientOptionalArgs args) {
// 省略大量代码
// 如果需要抓取注册表,读取其他server的注册信息
if (clientConfig.shouldRegisterWithEureka()) {
EurekaHttpClientFactory newRegistrationClientFactory = null;
EurekaHttpClient newRegistrationClient = null;
try {
newRegistrationClientFactory = EurekaHttpClients.registrationClientFactory(
eurekaTransport.bootstrapResolver,
eurekaTransport.transportClientFactory,
transportConfig
);
newRegistrationClient = newRegistrationClientFactory.newClient();
} catch (Exception e) {
logger.warn("Transport initialization failure", e);
}
// 将newRegistrationClient放入到eurekaTransport中
eurekaTransport.registrationClientFactory = newRegistrationClientFactory;
eurekaTransport.registrationClient = newRegistrationClient;
}
}
ここに、あなたはeurekaTransport.registrationClientが実際にある見ることができるEurekaHttpClient
、知って、私は右の場所や何を見つけることができませんでしたではありません、私は特定の実装の実装クラスを見つけることができませんでした。
最後に、オンライン検索、実装クラスの特定の実装では、次のとおりです。AbstractJersey2EurekaHttpClient
AbstractJersey2EurekaHttpClient.register()
public EurekaHttpResponse<Void> register(InstanceInfo info) {
String urlPath = "apps/" + info.getAppName();
Response response = null;
try {
// 发送请求,类似于:http://localhost:8080/v2/apps/ServiceA
// 发送的是post请求,服务实例的对象被打成了一个json发送,包括自己的主机、ip、端口号
// eureka server 就知道了这个ServiceA这个服务,有一个服务实例,比如是在192.168.31.109、host-01、8761端口
Builder resourceBuilder = jerseyClient.target(serviceUrl).path(urlPath).request();
addExtraProperties(resourceBuilder);
addExtraHeaders(resourceBuilder);
response = resourceBuilder
.accept(MediaType.APPLICATION_JSON)
.acceptEncoding("gzip")
.post(Entity.json(info));
return anEurekaHttpResponse(response.getStatus()).headers(headersOf(response)).build();
} finally {
if (logger.isDebugEnabled()) {
logger.debug("Jersey2 HTTP POST {}/{} with instance {}; statusCode={}", serviceUrl, urlPath, info.getId(),
response == null ? "N/A" : response.getStatus());
}
if (response != null) {
response.close();
}
}
}
ここに真実を持っていますが、パスコードを読み取るには理解することは困難であることが判明し、最終的に仕事の波をまとめています。。。
概要
(1)DiscoveryClient EurekaClientコンストラクタ)は、(タイミング関連のタスク、タスクinstanceInfoが開始InstanceInfoReplicatorある別のコピーを開始するスケジュールされたタスクを初期化します
(2)InstanceInfoReplicator行くためのスケジューリング、スレッドプールにスレッドとして、デフォルトはトゥーレに意志isDirtyセット、このスレッド1940の実装を遅らせることであり、それ自体start()メソッド
(3)実行時間のスレッドは、実行run()メソッド、スレッドの場合
(3)第1)(EurekaClient.refreshInstanceInfoを見つけ変更した場合、このメソッドは、実際には、ApplicationInfoManagerリフレッシュ設定サービスインスタンスを呼び出すいくつかの方法がありますが、設定を見ては、変更されていないされ、リフレッシュう;ヘルスチェック、およびチェック少し状態は、ステータスがApplicationInfoManagerの行く、更新サービスインスタンスの状態に設定されています
セットisDirty前に有していた(4)ので、サービス登録の実装が存在するであろう
それはreigsterのEurekaClient()登録する方法に基づいています(5)サービスの登録は、コールはRegistrationClientののtransportClientは、HTTPリクエスト、コールユーレカサーバによってレジスタ()メソッドの実装、サービスインスタンスInstanceInfo情報を根底であります安らかなインタフェースへの外部被ばくはInstanceInfoは、過去に送信するでしょう。ここでは、登録のために特別にRegistrationClientに初期化されEurekaTransport、構築したときに、呼び出されるscheduleServerEndpointTask()メソッド、探しています。
(6)、登録するSessionedEurekaHttpClientコール・レジスタ()メソッドを見つけるAbstractJersey2EurekaHttpClientの基本的な実装の最終使用法を登録します
(7)ジャージベースのフレームワークのユーレカ多くは、ユーレカサーバ上の安らかなインターフェースを提供し、あなたはユーレカクライアントを要求したい場合はユーレカ・サーバに要求を送信し、それはジャージの枠組みに基づいている必要があり、HTTP安らかなインターフェースの呼び出しを送信します
(8)登録要求の実際の実装、AbstractJersey2EurekaHttpClient中ユーレカ・クライアントjersey2プロジェクトであり、要求にhttp:// localhost:8080 / V2 /アプリケーション/サービスA、過去に情報サービスインスタンスを送信
ユーレカクライアントこの作品は、コードのこの部分は、サービス、多くのスロットポイントに登録されています。
(1)登録サービス、InstanceInfoReplicatorの内側に配置すべきではない、意味の不確実性
HttpClientを(2)要求を送信するための責任があり、クラスのシステムはあまりにも複雑であり、単に人々につながる対応するクライアントを見つけ、そして最終的には安らかなインターフェイスが公開と呼び出しに彼のジャージに基づいていないことができ、実際の送信を見つける推測しても、モンゴルへ順に、フレームワークを使用することですローカルサービス登録要求
宣言
:私のブログから始まるこの記事https://www.cnblogs.com/wang-mengと公共番号:ロマンチックみなさ一つramiflorous BEは、ソースを明記してください転載必要があります!
興味のパートナーは、個々の国民の少数心配することができる:一つの枝にはロマンチックな花を数えます