標籤:
上篇以一個 demo 示範範例介紹了 Eureka 的 Application Service 用戶端角色。今天我們繼續瞭解 Eureka 的 Application Client 用戶端,以一個簡單的互動示範範例,介紹 Application Client 是怎樣使用 Eureka 擷取 Application Service 執行個體並發送請求的。
上篇《Eureka 的 Application Service 用戶端的注冊以及執行示範範例》使用了一個 Socket 服務做為 demo,本文示範範例配合該文,將以一個 Socket 用戶端對該服務進行請求。
1. Eureka 伺服器啟動
本文 demo 要求 Eureka Server 已經部署好,並已經啟動。關於架設步驟參考部落格《Linux 下 Eureka 伺服器的部署》。
2. Application Service 服務啟動
直接將《Eureka 的 Application Service 用戶端的注冊以及執行示範範例》中的小 demo 跑起來(Socket Server 啟動,開始侍服網路請求)。
3. Application Client 設定檔的編寫
我們的 Application Client 就用官方提供 demo 裡的 sampleclient 下的 sample-eureka-client.properties 就可以,當然還要依據實際情況修正一下,比方把 eureka.serviceUrl.default(預設情況下本用戶端將要注冊到的 Eureka 伺服器):http://serverIP:8080/eureka/v2/:
###Eureka Client configuration for Sample Eureka Client#Properties based configuration for eureka client. The properties specified here is mostly what the users#need to change. All of these can be specified as a java system property with -D option (eg)-Deureka.region=us-east-1#For additional tuning options refer <url to go here>#Region where eureka is deployed -For AWS specify one of the AWS regions, for other datacenters specify a arbitrary string#indicating the region.This is normally specified as a -D option (eg) -Deureka.region=us-east-1eureka.region=default#Name of the application to be identified by other serviceseureka.name=sampleEurekaClient#Virtual host name by which the clients identifies this service#eureka.vipAddress=eureka.mydomain.net#The port where the service will be running and servicing requests#eureka.port=80#For eureka clients running in eureka server, it needs to connect to servers in other zoneseureka.preferSameZone=true#Change this if you want to use a DNS based lookup for determining other eureka servers. For example#of specifying the DNS entries, check the eureka-client-test.properties, eureka-client-prod.propertieseureka.shouldUseDns=falseeureka.us-east-1.availabilityZones=defaulteureka.serviceUrl.default=http://serverIP:8080/eureka/v2/
4. 日誌配置
就用官方提供 demo 裡的 sampleclient 下的 log4j.properties 就可以,當然還要依據實際須要修正一下,比方給 com.netflix.eureka 包的輸出層級設定為 DEBUG(log4j.properties 追加 log4j.logger.com.netflix.eureka=DEBUG),以方便我們研發期跟蹤調試。
log4j.rootCategory=INFO,stdoutlog4j.appender.stdout=org.apache.log4j.ConsoleAppenderlog4j.appender.stdout.layout=org.apache.log4j.PatternLayoutlog4j.appender.stdout.layout.ConversionPattern=%d %-5p %C:%L [%t] [%M] %m%nlog4j.logger.com.netflix.eureka=DEBUG
5. 尋找本次請求的 Application Service 執行個體
用戶端在向 Application Service 請求之前得先從 Eureka Server 拿到侍服本次請求的 Application Service 執行個體。尋找本次請求的 Application Service 執行個體的代碼例如以下:
// Register with Eureka DiscoveryManager.getInstance().initComponent( new MyDataCenterInstanceConfig(), new DefaultEurekaClientConfig()); ApplicationInfoManager.getInstance().setInstanceStatus( InstanceStatus.UP); String vipAddress = configInstance.getStringProperty( "eureka.vipAddress", "sampleservice.mydomain.net").get(); InstanceInfo nextServerInfo = DiscoveryManager.getInstance() .getDiscoveryClient() .getNextServerFromEureka(vipAddress, false);
第一句初始化本用戶端,第二句告訴 Eureka 本用戶端處於就緒狀態,接下來兩句是使用 Eureka 找到對本次請求進行侍服的 Application Service 執行個體。
6. Application Client 網路請求
Application Client 拿到 Application Service之後立刻進行網路 Socket 請求,進行資料資訊互動。
Socket s = new Socket(); int serverPort = nextServerInfo.getPort(); try { s.connect(new InetSocketAddress(nextServerInfo.getHostName(), serverPort)); } catch (IOException e) { System.err.println("Could not connect to the server :" + nextServerInfo.getHostName() + " at port " + serverPort); } try { System.out.println("Connected to server. Sending a sample request"); PrintStream out = new PrintStream(s.getOutputStream()); out.println("Sample request " + new Date()); String str = null; System.out.println("Waiting for server response.."); BufferedReader rd = new BufferedReader(new InputStreamReader( s.getInputStream())); str = rd.readLine(); if (str != null) { System.out .println("Received response from server. Communication all fine using Eureka :"); System.out.println("Exiting the client. Demo over.."); } rd.close(); } catch (IOException e) { e.printStackTrace(); }
7. Application Client 關閉時取消注冊
Application Client 在關閉時要將自己在 Eureka 的注冊取消掉。
public void unRegisterWithEureka() { // Un register from eureka. DiscoveryManager.getInstance().shutdownComponent(); }
8. 執行 demo
建立一個項目(不要和 Application Service 的 demo 跑在同一個項目下),如今我們把完整的 Application Client 代碼整理一下。
/* * Copyright 2012 Netflix, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package com.netflix.eureka;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintStream;import java.net.InetSocketAddress;import java.net.Socket;import java.util.Date;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import com.netflix.appinfo.ApplicationInfoManager;import com.netflix.appinfo.InstanceInfo;import com.netflix.appinfo.InstanceInfo.InstanceStatus;import com.netflix.appinfo.MyDataCenterInstanceConfig;import com.netflix.config.DynamicPropertyFactory;import com.netflix.discovery.DefaultEurekaClientConfig;import com.netflix.discovery.DiscoveryManager;/** * Sample Eureka client that discovers the service using Eureka and sends * requests. * * @author Karthik Ranganathan * */public class SampleEurekaClient { private static final DynamicPropertyFactory configInstance = com.netflix.config.DynamicPropertyFactory .getInstance(); private static final Logger logger = LoggerFactory .getLogger(SampleEurekaClient.class); public void sendRequestToServiceUsingEureka() { // Register with Eureka DiscoveryManager.getInstance().initComponent( new MyDataCenterInstanceConfig(), new DefaultEurekaClientConfig()); ApplicationInfoManager.getInstance().setInstanceStatus( InstanceStatus.UP); String vipAddress = configInstance.getStringProperty( "eureka.vipAddress", "sampleservice.mydomain.net").get(); InstanceInfo nextServerInfo = DiscoveryManager.getInstance() .getDiscoveryClient() .getNextServerFromEureka(vipAddress, false); Socket s = new Socket(); int serverPort = nextServerInfo.getPort(); try { s.connect(new InetSocketAddress(nextServerInfo.getHostName(), serverPort)); } catch (IOException e) { System.err.println("Could not connect to the server :" + nextServerInfo.getHostName() + " at port " + serverPort); } try { System.out.println("Connected to server. Sending a sample request"); PrintStream out = new PrintStream(s.getOutputStream()); out.println("Sample request " + new Date()); String str = null; System.out.println("Waiting for server response.."); BufferedReader rd = new BufferedReader(new InputStreamReader( s.getInputStream())); str = rd.readLine(); if (str != null) { System.out .println("Received response from server. Communication all fine using Eureka :"); System.out.println("Exiting the client. Demo over.."); } rd.close(); } catch (IOException e) { e.printStackTrace(); } this.unRegisterWithEureka(); } public void unRegisterWithEureka() { // Un register from eureka. DiscoveryManager.getInstance().shutdownComponent(); } public static void main(String[] args) { SampleEurekaClient sampleEurekaService = new SampleEurekaClient(); sampleEurekaService.sendRequestToServiceUsingEureka(); }}
如上篇部落格所述一樣把各種依賴包加進本文 demo 的 CLASSPATH,然後把第三、四步寫好的 sample-eureka-client.properties、log4j.properties 也拷貝進 CLASSPATH,並將 sample-eureka-client.properties 重新命名為 config.properties(原因參考上篇部落格),接下來就能夠執行本文 demo 了。run SampleEurekaClient,日誌結果例如以下:
2014-07-10 11:02:51,860 INFO com.netflix.config.sources.URLConfigurationSource:125 [main] [<init>] URLs to be used as dynamic configuration source: [file:/D:/javaprojects/test2/bin/config.properties]
2014-07-10 11:02:51,927 INFO com.netflix.config.DynamicPropertyFactory:281 [main] [getInstance] DynamicPropertyFactory is initialized with configuration sources: [email protected]
2014-07-10 11:02:52,060 WARN com.netflix.appinfo.PropertiesInstanceConfig:349 [main] [init] Cannot find the properties specified : eureka-client. This may be okay if there are other environment specific properties or the configuration is installed with a different mechanism.
2014-07-10 11:02:52,065 WARN com.netflix.discovery.DefaultEurekaClientConfig:95 [main] [init] Cannot find the properties specified : eureka-client. This may be okay if there are other environment specific properties or the configuration is installed with a different mechanism.
2014-07-10 11:02:52,103 INFO com.netflix.appinfo.providers.EurekaConfigBasedInstanceInfoProvider:79 [main] [get] Setting initial instance status as: STARTING
2014-07-10 11:02:53,667 INFO com.netflix.discovery.DiscoveryClient:646 [main] [fetchRegistry] Disable delta property : false
2014-07-10 11:02:53,667 INFO com.netflix.discovery.DiscoveryClient:647 [main] [fetchRegistry] Single vip registry refresh property : null
2014-07-10 11:02:53,667 INFO com.netflix.discovery.DiscoveryClient:648 [main] [fetchRegistry] Force full registry fetch : false
2014-07-10 11:02:53,667 INFO com.netflix.discovery.DiscoveryClient:649 [main] [fetchRegistry] Application is null : false
2014-07-10 11:02:53,667 INFO com.netflix.discovery.DiscoveryClient:650 [main] [fetchRegistry] Registered Applications size is zero : true
2014-07-10 11:02:53,668 INFO com.netflix.discovery.DiscoveryClient:652 [main] [fetchRegistry] Application version is -1: true
2014-07-10 11:02:54,061 INFO com.netflix.discovery.DiscoveryClient:992 [main] [makeRemoteCall] Finished a call to service url http://serverIP:8080/eureka/v2/ and url path apps/ with status code 200.
2014-07-10 11:02:54,061 INFO com.netflix.discovery.DiscoveryClient:758 [main] [getAndStoreFullRegistry] Getting all instance registry info from the eureka server
2014-07-10 11:02:54,568 INFO com.netflix.discovery.DiscoveryClient:765 [main] [getAndStoreFullRegistry] The response status is 200
2014-07-10 11:02:54,578 INFO com.netflix.discovery.DiscoveryClient:1056 [main] [initScheduledTasks] Starting heartbeat executor: renew interval is: 30
Connected to server. Sending a sample request
Waiting for server response..
Received response from server. Communication all fine using Eureka :
Exiting the client. Demo over..
證明 demo 擷取 Application Service 執行個體並請求成功。
能夠看出,Application Service 執行個體的資訊都封裝在了 com.netflix.appinfo.InstanceInfo 下,那麼我們還能從中擷取哪些資訊?SampleEurekaClient 類增加下面代碼:
logger.debug("nextServerInfo.getAppGroupName()-" + nextServerInfo.getAppGroupName()); logger.debug("nextServerInfo.getAppName()-" + nextServerInfo.getAppName()); logger.debug("nextServerInfo.getASGName()-" + nextServerInfo.getASGName()); logger.debug("nextServerInfo.getHomePageUrl()-" + nextServerInfo.getHomePageUrl()); logger.debug("nextServerInfo.getHostName()-" + nextServerInfo.getHostName()); logger.debug("nextServerInfo.getId()-" + nextServerInfo.getId()); logger.debug("nextServerInfo.getIPAddr()-" + nextServerInfo.getIPAddr()); logger.debug("nextServerInfo.getLastUpdatedTimestamp()-" + nextServerInfo.getLastUpdatedTimestamp()); logger.debug("nextServerInfo.getPort()-" + nextServerInfo.getPort()); logger.debug("nextServerInfo.getSecureVipAddress()-" + nextServerInfo.getSecureVipAddress()); logger.debug("nextServerInfo.getStatusPageUrl()-" + nextServerInfo.getStatusPageUrl()); logger.debug("nextServerInfo.getVIPAddress()-" + nextServerInfo.getVIPAddress()); logger.debug("nextServerInfo.getLastDirtyTimestamp()-" + nextServerInfo.getLastDirtyTimestamp()); logger.debug("nextServerInfo.getHealthCheckUrls()-" + nextServerInfo.getHealthCheckUrls()); logger.debug("nextServerInfo.getStatus()-" + nextServerInfo.getStatus());
然後又一次執行本文 demo,以上語句列印結果例如以下:
2014-07-10 11:02:54,619 DEBUG com.netflix.eureka.SampleEurekaClient:69 [main] [sendRequestToServiceUsingEureka] nextServerInfo.getAppGroupName()-UNKNOWN
2014-07-10 11:02:54,619 DEBUG com.netflix.eureka.SampleEurekaClient:70 [main] [sendRequestToServiceUsingEureka] nextServerInfo.getAppName()-SAMPLESERVICE
2014-07-10 11:02:54,619 DEBUG com.netflix.eureka.SampleEurekaClient:71 [main] [sendRequestToServiceUsingEureka] nextServerInfo.getASGName()-null
2014-07-10 11:02:54,619 DEBUG com.netflix.eureka.SampleEurekaClient:72 [main] [sendRequestToServiceUsingEureka] nextServerInfo.getHomePageUrl()-http://defonds-win7:1935/
2014-07-10 11:02:54,620 DEBUG com.netflix.eureka.SampleEurekaClient:73 [main] [sendRequestToServiceUsingEureka] nextServerInfo.getHostName()-defonds-win7
2014-07-10 11:02:54,620 DEBUG com.netflix.eureka.SampleEurekaClient:74 [main] [sendRequestToServiceUsingEureka] nextServerInfo.getId()-defonds-win7
2014-07-10 11:02:54,620 DEBUG com.netflix.eureka.SampleEurekaClient:75 [main] [sendRequestToServiceUsingEureka] nextServerInfo.getIPAddr()-172.21.40.134
2014-07-10 11:02:54,620 DEBUG com.netflix.eureka.SampleEurekaClient:76 [main] [sendRequestToServiceUsingEureka] nextServerInfo.getLastUpdatedTimestamp()-1404961202884
2014-07-10 11:02:54,620 DEBUG com.netflix.eureka.SampleEurekaClient:77 [main] [sendRequestToServiceUsingEureka] nextServerInfo.getPort()-1935
2014-07-10 11:02:54,620 DEBUG com.netflix.eureka.SampleEurekaClient:78 [main] [sendRequestToServiceUsingEureka] nextServerInfo.getSecureVipAddress()-null
2014-07-10 11:02:54,620 DEBUG com.netflix.eureka.SampleEurekaClient:79 [main] [sendRequestToServiceUsingEureka] nextServerInfo.getStatusPageUrl()-http://defonds-win7:1935/Status
2014-07-10 11:02:54,620 DEBUG com.netflix.eureka.SampleEurekaClient:80 [main] [sendRequestToServiceUsingEureka] nextServerInfo.getVIPAddress()-sampleservice.mydomain.net
2014-07-10 11:02:54,620 DEBUG com.netflix.eureka.SampleEurekaClient:81 [main] [sendRequestToServiceUsingEureka] nextServerInfo.getLastDirtyTimestamp()-1404961230856
2014-07-10 11:02:54,620 DEBUG com.netflix.eureka.SampleEurekaClient:82 [main] [sendRequestToServiceUsingEureka] nextServerInfo.getHealthCheckUrls()-[http://defonds-win7:1935/healthcheck]
2014-07-10 11:02:54,621 DEBUG com.netflix.eureka.SampleEurekaClient:83 [main] [sendRequestToServiceUsingEureka] nextServerInfo.getStatus()-UP
這些資訊都和 http://serverIP:8080/eureka/v2/apps/ 顯示的 SAMPLESERVICE 執行個體的 各個屬性一一相應。
參考資料
- https://github.com/Netflix/eureka/tree/master/eureka-server/conf
Eureka 的 Application Client client的執行示範範例