eureka客户端启动异常: No qualifying assetbean of type [com.netflix.discovery.EurekaClient] found

Spring Cloud源码解析:一个注解加载Eureka client - 推酷
Spring Cloud源码解析:一个注解加载Eureka client
一般我们的都会被告知使用spring cloud app 如果
,只需简单的一个
的annotation,就可以搞定。服务启动时会自动注册到eureka服务,服务消费者只需要使用该名字加方法名就可以调用到服务。代码基本不用加任何东西,很神奇的样子!于是有点好奇一个本文重点关注在spring cloud中Eureka client是如何被注入,来供服务使用的。
1 Eureka client简介
Eureka client 负责与Eureka Server 配合向外提供注册与发现服务接口。首先看下eureka client是怎么定义,Netflix的 eureka client的行为在LookupService中定义,Lookup service for finding active instances,定义了,从outline中能看到起“规定”了如下几个最基本的方法。服务发现必须实现的基本行为:
从继承图上能看到两点:
第一, discoverclient需要实现该接口,用户app需要用该接口来实现服务发现。
第二, discover 的各个peer node实现该接口,来同步注册服务
com.netflix.discovery.DiscoveryClient是netflix使用的客户端,从其class的注释可以看到他主要做这几件事情:
a) Registering the instance with Eureka Server
b) Renewalof the lease with Eureka Server
c) Cancellation of the lease from Eureka Server during shutdown
2 Eureka Client 在Spring cloud中
看到spring cloud自己又搞了个org.springframework.cloud.client.discovery.
接口,其接口定义如下
其实现类是 org.springframework.cloud.netflix.eureka.EurekaDiscoveryClient。看上去spring cloud是自己做了个新client,来和Eureka server通信来实现服务注册和发现吗?里面代码稍微多看一点会看到其实里面还是使用了netflix原生的 com.netflix.discovery.EurekaClient。
@RequiredArgsConstructor
public class EurekaDiscoveryClient implements DiscoveryClient {
public static final String DESCRIPTION = “Spring Cloud Eureka Discovery Client”;
private final EurekaInstanceC
private final EurekaClient eurekaC
@RequiredArgsConstructor
public class EurekaDiscoveryClient implements DiscoveryClient {
public static final String DESCRIPTION = “SpringCloudEurekaDiscoveryClient”;
private final EurekaInstanceC
private final EurekaClienteurekaC
其实这种方式在spring cloud中运用很多。spring cloud里面挺多对象,都是自己定义了一个接口,定义了其在spring cloud上下文中赋予的新的行为要求,但是其实现类其实都是使用netflix原生的对应对象,包括里面的ServiceInstance等,都是有自己的定义 但是实现类EurekaServiceInstance 其实也是对netflix原生的com.netflix.appinfo.InstanceInfo 的封装。因此springcloud中的对象更像是一个wrapper。有点像那种被改造过的
因此要看下spring cloud中怎样加载一个eureka client,其实,先看下如何加载一个EurekaDiscoveryClient
3 EurekaDiscoveryClient在spring cloud的注入过程
如下的是一般写一个服务,在服务的启动类中,用户要做的所有事情就是在自己的app中使用@EnableEurekaClient
@SpringBootApplication
@EnableEurekaClient
public class BookmarkServiceApplication {
public static void main(String[] args) {
SpringApplication.run(BookmarkServiceApplication.class, args);
@SpringBootApplication
@EnableEurekaClient
public class BookmarkServiceApplication {
public static void main(String[] args) {
SpringApplication.run(BookmarkServiceApplication.class, args);
这样一个annotation。我们试着看下这个annotation后面怎么把这个EurekaDiscoveryClient 注入的。可以看到这个自定义的annotation @EnableEurekaClient里面没有内容。只是个属于那种标记类型 的注释,他的作用就是开启Eureka discovery的配置,正是通过这个标记,autoconfiguration就可以加载相关的Eureka类。那我们看下他是怎么做到的。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@EnableDiscoveryClient
public @interface EnableEurekaClient {
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@EnableDiscoveryClient
public @interface EnableEurekaClient {
看到EnableEurekaClient这个自定义anntotaion的定义,用到了另一个自定义的注解:@EnableDiscoveryClient。看看这个自定义注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(EnableDiscoveryClientImportSelector.class)
public @interface EnableDiscoveryClient {
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(EnableDiscoveryClientImportSelector.class)
public @interface EnableDiscoveryClient {
这个注解import了EnableDiscoveryClientImportSelector.class这样一个类,其实就是通过这个类来加载需求要的bean。Import的用法和我们原来用xml的方式来聚合两个类似的配置类。
&import resource=”config/bean1config.xml”/&
&import resource=”config/bean2config.xml”/&
&importresource=”config/bean1config.xml”/&
&importresource=”config/bean2config.xml”/&
看到这里有覆盖了父类SpringFactoryImportSelector的一个方法isEnabled,其实标记体现的也就是这里,在配置的环境中找这个key是否被配置,注意,默认是TRUE,也就是只要import了这个配置,就会enable。
@Order(Ordered.LOWEST_PRECEDENCE – 100)
public class EnableDiscoveryClientImportSelector
extends SpringFactoryImportSelector&EnableDiscoveryClient& {
protected boolean isEnabled() {
return new RelaxedPropertyResolver(getEnvironment()).getProperty(
“spring.cloud.discovery.enabled”, Boolean.class, Boolean.TRUE);
@Order(Ordered.LOWEST_PRECEDENCE – 100)
public class EnableDiscoveryClientImportSelector
extends SpringFactoryImportSelector&EnableDiscoveryClient& {
protected boolean isEnabled() {
return new RelaxedPropertyResolver(getEnvironment()).getProperty(
“spring.cloud.discovery.enabled”, Boolean.class, Boolean.TRUE);
在其父类org.mons.util.SpringFactoryImportSelector的String[] selectImports(AnnotationMetadata metadata)方法中正是根据这个标记类判定是否加载如下定义的类。
TODOODO selectImports 代码快
调用loadFactoryNames其实加载META-INF/spring.factories下的class。
org.springframework.core.io.support.SpringFactoriesLoader.loadFactoryNames(Class&?& factoryClass, ClassLoader classLoader)
TODOTODO loadFactoryNames
spring-cloud-netflix-eureka-client\src\main\resources\META-INF\spring.factories中配置,可以看到EnableAutoConfiguration的包含了EurekaClientConfigServerAutoConfiguration。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.netflix.eureka.config.EurekaClientConfigServerAutoConfiguration,\
org.springframework.cloud.netflix.eureka.config.EurekaDiscoveryClientConfigServiceAutoConfiguration,\
org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration,\
org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.netflix.eureka.config.EurekaClientConfigServerAutoConfiguration,\
org.springframework.cloud.netflix.eureka.config.EurekaDiscoveryClientConfigServiceAutoConfiguration,\
org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration,\
org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration
EurekaClientAutoConfiguration分别会依次注入配置EurekaClientConfigBean、 EurekaInstanceConfigBean和DiscoveryClient
@ConditionalOnMissingBean(value = EurekaClientConfig.class, search = SearchStrategy.CURRENT)
public EurekaClientConfigBean eurekaClientConfigBean() {
EurekaClientConfigBean client = new EurekaClientConfigBean();
if (&bootstrap&.equals(this.env.getProperty(&spring.config.name&))) {
// We don't register during bootstrap by default, but there will be another
// chance later.
client.setRegisterWithEureka(false);
public DiscoveryClient discoveryClient(EurekaInstanceConfig config,
EurekaClient client) {
return new EurekaDiscoveryClient(config, client);
@ConditionalOnMissingBean(value = EurekaClientConfig.class, search = SearchStrategy.CURRENT)
public EurekaClientConfigBeaneurekaClientConfigBean() {
EurekaClientConfigBeanclient = new EurekaClientConfigBean();
if ("bootstrap".equals(this.env.getProperty("spring.config.name"))) {
// We don't register during bootstrap by default, but there will be another
// chance later.
client.setRegisterWithEureka(false);
public DiscoveryClientdiscoveryClient(EurekaInstanceConfigconfig,
EurekaClientclient) {
return new EurekaDiscoveryClient(config, client);
4.& 调用过程
至此就找到了Eureka相关类是在哪里定义的,怎样通过@EnableEurekaClient 这个注解来控制加载的。但是在服务的congtext中这部分又是如何被调用到的呢?如果要分析这部分,就有点想我没试图从原来的spring的application.xml去试图追寻其中定义的bean是如何在context中创建,又如何被被根据配置赋予属性,建立bean之间的关系。
其实在spring cloud中使用的annotation就是原来大家属性的xml配置的另外一种so called alternative。
这个调用关系真的是非常长,非常繁琐的,明显不是本文讨论的重点,这是springIOC的核心实现,详细可以参照spring core相关的东西。但是为了完整期间,还是最粗糙的把这个调用关系贴出来。能看到在自己写的一个服务的main函数开始如果使用spring 上下文来加载那几个eureka的类。只是简单看下这个过程,简化了很多,所以这里的调用过程也是一个简单的链路。
bookmarks.BookmarkServiceApplication.main
bookmarks.BookmarkServiceApplication.main
ConfigurableApplicationContext org.springframework.boot.SpringApplication.run
ConfigurableApplicationContextorg.springframework.boot.SpringApplication.run
org.springframework.boot.SpringApplication.SpringApplication(Object… sources)
org.springframework.boot.SpringApplication.SpringApplication(Object… sources)
org.springframework.boot.SpringApplication.initialize(Object[] sources)
org.springframework.boot.SpringApplication.initialize(Object[] sources)
springframework.boot.SpringApplication.createAndRefreshContext()
springframework.boot.SpringApplication.createAndRefreshContext()
org.springframework.context.support.AbstractApplicationContext.refresh()
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
org.springframework.context.support.AbstractApplicationContext.refresh()
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactorybeanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
TODOTO AbstractApplicationContext.refresh()
可以看到不管是原来的xml的方式还是现在这种annotation的方式,abstract的context还是同样的逻辑。进一步验证了annotation于xml也都只是一种配置的方式,是给开发人员的接口,spring IOC的东西没用变。其实从调用链路上各个类的package从属也能看出端倪。
org.springframework.context一般都是spring 这个包的,org.springframework.context.annotation就是annotation这个包的
org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors()
org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors()
org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors()
org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors()
org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors()
org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors()
org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(BeanDefinitionRegistryregistry)
org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(BeanDefinitionRegistry registry)
org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(BeanDefinitionRegistryregistry)
org.springframework.context.annotation.ConfigurationClassParser.parse()
org.springframework.context.annotation.ConfigurationClassParser.parse()
org.springframework.context.annotation.ConfigurationClassParser.processDeferredImportSelectors()
org.springframework.context.annotation.ConfigurationClassParser.processDeferredImportSelectors()
org.mons.util.SpringFactoryImportSelector.selectImports()
org.mons.util.SpringFactoryImportSelector.selectImports()
org.springframework.context.annotation.ConfigurationClassParser.processImports()
org.springframework.context.annotation.ConfigurationClassParser.processImports()
这个就是我们前面看到的import 类并实例化的地方。看到在processImports中会对这里import的类进行实例化。
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致Eureka service 客户端的注册以及运行示例 - 推酷
Eureka service 客户端的注册以及运行示例
Eureka 服务器架起来了(关于架设步骤参考博客《
》),现在如何把我们要负载均衡的服务器(也就是从 Application Client 接收请求并返回一个响应的 Application Service)注册到 Eureka?本文以一个示例介绍 Eureka Application Service 客户端的 Eureka 生命周期(包括启动时的注册、侍服示例、关闭时的取消注册)情况,相信读完本文之后,读者可以对 Eureka 的 Application Service 角色有了一个进一步了解,而且完全可以把自己的服务加进 Eureka。
& & & & 1. Eureka 服务器启动
& & & & 本文 demo 要求 Eureka Server 已经部署好,并已经启动。关于架设步骤参考博客《
& & & & Eureka 服务器启动以后,可以通过 http://serverIP:8080/eureka/ 或者 http://serverIP:8080/eureka/v2/apps/ 浏览已注册到 Eureka 的 Application Service。比如作者在开发环境 PC 访问服务器端的
http://serverIP:8080/eureka/v2/apps/ ,页面返回结果如下:
&applications&
&versions__delta&1&/versions__delta&
&apps__hashcode&UP_1_&/apps__hashcode&
&application&
&name&EUREKA&/name&
&instance&
&hostName&localhost.localdomain&/hostName&
&app&EUREKA&/app&
&ipAddr&127.0.0.1&/ipAddr&
&status&UP&/status&
&overriddenstatus&UNKNOWN&/overriddenstatus&
&port enabled=&true&&8080&/port&
&securePort enabled=&false&&443&/securePort&
&countryId&1&/countryId&
&dataCenterInfo
class=&com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo&&
&name&MyOwn&/name&
&/dataCenterInfo&
&leaseInfo&
&renewalIntervalInSecs&30&/renewalIntervalInSecs&
&durationInSecs&90&/durationInSecs&
&registrationTimestamp&2&/registrationTimestamp&
&lastRenewalTimestamp&6&/lastRenewalTimestamp&
&evictionTimestamp&0&/evictionTimestamp&
&serviceUpTimestamp&1&/serviceUpTimestamp&
&/leaseInfo&
&metadata class=&java.util.Collections$EmptyMap& /&
&appGroupName&UNKNOWN&/appGroupName&
&homePageUrl&http://localhost.localdomain:8080/&/homePageUrl&
&statusPageUrl&http://localhost.localdomain:8080/Status&/statusPageUrl&
&healthCheckUrl&http://localhost.localdomain:8080/healthcheck&/healthCheckUrl&
&vipAddress&eureka.mydomain.net&/vipAddress&
&isCoordinatingDiscoveryServer&true&/isCoordinatingDiscoveryServer&
&lastUpdatedTimestamp&2&/lastUpdatedTimestamp&
&lastDirtyTimestamp&3&/lastDirtyTimestamp&
&actionType&ADDED&/actionType&
&/instance&
&/application&
&/applications&
& & & & apps__hashcode 是 1,可以看出目前只有一个 Application Service 注册到了 Eureka Server,这个名为 Eureka 的 Application Service 只有一个实例,就是这台 Eureka Server 它自己 - localhost.localdomain。为何 Eureka Server 自己也是一个 Application Service 呢?这也是 Eureka 架构健壮性 feature 之一,Eureka Server 之间也会相互注册,而且还会将注册到自己的 Application Service 注册给其他 Eureka Server,避免了一台 Eureka Server 宕机所造成的区域性服务瘫痪。
& & & & 2. Application Service 配置文件的编写
& & & & 我们的负载均衡服务器就用官方提供
里的 sampleservice 下的 sample-eureka-service.properties 即可,当然还要根据实际情况修正一下,比如把 eureka.name 改为我们自定义的 Application 名以区分开其他服务,把 eureka.port(本服务将会运行并侍服请求的端口)改为我们的 Service 服务器开放的侍服端口 1935,eureka.serviceUrl.default(默认情况下本服务将要注册到的 Eureka 服务器):
http://serverIP:8080/eureka/v2/ :
###Eureka Client configuration for Sample Eureka Service
#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-1
eureka.region=default
#Name of the application to be identified by other services
eureka.name=sampleservice
#Virtual host name by which the clients identifies this service
eureka.vipAddress=sampleservice.mydomain.net
#The port where the service will be running and serving requests
eureka.port=1935
#For eureka clients running in eureka server, it needs to connect to servers in other zones
eureka.preferSameZone=false
#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.properties
eureka.shouldUseDns=false
eureka.us-east-1.availabilityZones=default
eureka.serviceUrl.default=http://serverIP:8080/eureka/v2/
& & & & 3. 日志配置
& & & & 就用官方提供
里的 sampleservice 下的 log4j.properties 即可,当然还要根据实际需要修正一下,比如给 com.defonds.wms.module.server 包的输出级别设置为 DEBUG(log4j.properties 追加 .defonds.wms.module.server=DEBUG),以方便我们研发期跟踪调试。
log4j.rootCategory=INFO,stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %-5p %C:%L [%t] [%M] %m%n
& & & & 4. Application Service 启动时注册 Eureka
& & & & 我们希望每台负载均衡服务器在启动时就注册给 Eureka,以及时承担负载。注册代码如下所示:
private static final DynamicPropertyFactory configInstance = com.netflix.config.DynamicPropertyFactory.getInstance();
private static final Logger logger = LoggerFactory.getLogger(SampleEurekaService.class);
public void registerWithEureka() {
// Register with Eureka
DiscoveryManager.getInstance().initComponent(
new MyDataCenterInstanceConfig(),
new DefaultEurekaClientConfig());
ApplicationInfoManager.getInstance().setInstanceStatus(
InstanceStatus.UP);
& & & & 第一句加载本地配置文件,initComponent 句根据配置初始化这台 Eureka Application Service,并且注册到 Eureka Server,setInstanceStatus 句指示本台 Application Service 已启动,准备好侍服网络请求。
& & & & 5. Application Service 侍服网络请求
& & & & Application Service 的 Eureka Server 初始化以及注册是异步的,需要一段时间,我们想要在确认初始化并注册成功之后,提供一个 Socket 服务,以供网络请求。demo 需要,这个服务是一次性的,只提供一次 Socket 侍服。侍服完一次请求后,本 Socket 服务就关闭,并将自己从 Eureka Server 取消注册。
String vipAddress = configInstance.getStringProperty(
&eureka.vipAddress&, &sampleservice.mydomain.net&).get();
InstanceInfo nextServerInfo =
while (nextServerInfo == null) {
nextServerInfo = DiscoveryManager.getInstance()
.getDiscoveryClient()
.getNextServerFromEureka(vipAddress, false);
} catch (Throwable e) {
System.out
.println(&Waiting for service to register with eureka..&);
Thread.sleep(10000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
System.out.println(&Service started and ready to process requests..&);
ServerSocket serverSocket = new ServerSocket(configInstance
.getIntProperty(&eureka.port&, 8010).get());
final Socket s = serverSocket.accept();
System.out
.println(&Client got connected..Processing request from the client&);
processRequest(s);
} catch (IOException e) {
e.printStackTrace();
& & & & Socket 侍服 processRequest 方法详细如下:
private void processRequest(final Socket s) {
BufferedReader rd = new BufferedReader(new InputStreamReader(
s.getInputStream()));
String line = rd.readLine();
if (line != null) {
System.out.println(&Received the request from the client.&);
PrintStream out = new PrintStream(s.getOutputStream());
System.out.println(&Sending the response to the client...&);
out.println(&Reponse at & + new Date());
} catch (Throwable e) {
System.err.println(&Error processing requests&);
} finally {
if (s != null) {
s.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
& & & & 6. Application Service 关闭时取消注册
& & & & 就像 Spring 管理的对象,初始化、销毁都统一管理起来一样,我们希望本台 Application Service 实例在关闭时也能将自身占用的系统资源释放出来(比如任务列表的线程关闭),而且取消掉 Eureka 服务器的注册。
public void unRegisterWithEureka() {
// Un register from eureka.
DiscoveryManager.getInstance().shutdownComponent();
& & & & 7. 运行 demo
& & & & 现在我们把完整的 Application Service 整理一下。
* 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.
import java.io.BufferedR
import java.io.IOE
import java.io.InputStreamR
import java.io.PrintS
import java.net.ServerS
import java.net.S
import java.util.D
import org.slf4j.L
import org.slf4j.LoggerF
import com.netflix.appinfo.ApplicationInfoM
import com.netflix.appinfo.InstanceI
import com.netflix.appinfo.InstanceInfo.InstanceS
import com.netflix.appinfo.MyDataCenterInstanceC
import com.netflix.config.DynamicPropertyF
import com.netflix.discovery.DefaultEurekaClientC
import com.netflix.discovery.DiscoveryM
* Sample Eureka service that registers with Eureka to receive and process
* requests.
* This example just receives one request and exits once it receives the request
* after processing it.
* @author Karthik Ranganathan
public class SampleEurekaService {
private static final DynamicPropertyFactory configInstance = com.netflix.config.DynamicPropertyFactory
.getInstance();
private static final Logger logger = LoggerFactory
.getLogger(SampleEurekaService.class);
public void registerWithEureka() {
// 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 =
while (nextServerInfo == null) {
nextServerInfo = DiscoveryManager.getInstance()
.getDiscoveryClient()
.getNextServerFromEureka(vipAddress, false);
} catch (Throwable e) {
System.out
.println(&Waiting for service to register with eureka..&);
Thread.sleep(10000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
System.out.println(&Service started and ready to process requests..&);
ServerSocket serverSocket = new ServerSocket(configInstance
.getIntProperty(&eureka.port&, 8010).get());
final Socket s = serverSocket.accept();
System.out
.println(&Client got connected..Processing request from the client&);
processRequest(s);
} catch (IOException e) {
e.printStackTrace();
this.unRegisterWithEureka();
System.out.println(&Shutting down server.Demo over.&);
public void unRegisterWithEureka() {
// Un register from eureka.
DiscoveryManager.getInstance().shutdownComponent();
private void processRequest(final Socket s) {
BufferedReader rd = new BufferedReader(new InputStreamReader(
s.getInputStream()));
String line = rd.readLine();
if (line != null) {
System.out.println(&Received the request from the client.&);
PrintStream out = new PrintStream(s.getOutputStream());
System.out.println(&Sending the response to the client...&);
out.println(&Reponse at & + new Date());
} catch (Throwable e) {
System.err.println(&Error processing requests&);
} finally {
if (s != null) {
s.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
public static void main(String args[]) {
SampleEurekaService sampleEurekaService = new SampleEurekaService();
sampleEurekaService.registerWithEureka();
& & & & 很明显我们的 SampleEurekaService 类需要很多依赖包,这些包都在 eureka-server-1.1.134.war 包里的 WEB-INF/lib 目录下,直接拷贝进我们 demo 的 CLASSPATH,不用一个个去找了,还避免了版本冲突所造成的不必要麻烦。eureka-client-1.1.134.jar 可以去
下载,或者直接 maven 依赖导入:
&dependency&
&groupId&com.netflix.eureka&/groupId&
&artifactId&eureka-client&/artifactId&
&version&1.1.134&/version&
&/dependency&
& & & & 类完成了、环境配置好了,接下来把第二、三步写好的 sample-eureka-service.properties、log4j.properties 也拷贝进 CLASSPATH,接下来就可以运行 demo 了。直接
run SampleEurekaService,发现报以下错误:
17:01:50,141 WARN &com.netflix.config.sources.URLConfigurationSource:120 [main] [&init&] No URLs will be polled as dynamic configuration sources.
17:01:50,144 INFO &com.netflix.config.sources.URLConfigurationSource:121 [main] [&init&] To enable URLs as dynamic configuration sources, define System property archaius.configurationSource.additionalUrls or make config.properties available on classpath.
17:01:50,178 INFO &com.netflix.config.DynamicPropertyFactory:281 [main] [getInstance] DynamicPropertyFactory is initialized with configuration sources: com.netflix.config.ConcurrentCompositeConfiguration@6f25844f
17:01:58,982 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.
17:02:00,140 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.
17:02:03,559 INFO &com.netflix.appinfo.providers.EurekaConfigBasedInstanceInfoProvider:79 [main] [get] Setting initial instance status as: STARTING
Exception in thread &main& java.lang.RuntimeException: Failed to initialize DiscoveryClient!
at com.netflix.discovery.DiscoveryClient.&init&(DiscoveryClient.java:235)
at com.netflix.discovery.DiscoveryClient.&init&(DiscoveryClient.java:169)
at com.netflix.discovery.DiscoveryManager.initComponent(DiscoveryManager.java:84)
at com.netflix.eureka.SampleEurekaService.registerWithEureka(SampleEurekaService.java:60)
at com.netflix.eureka.SampleEurekaService.main(SampleEurekaService.java:139)
Caused by: java.lang.IllegalArgumentException: DiscoveryClient: invalid serviceUrl specified!
at com.netflix.discovery.DiscoveryClient.getEurekaServiceUrlsFromConfig(DiscoveryClient.java:574)
at com.netflix.discovery.DiscoveryClient.getDiscoveryServiceUrls(DiscoveryClient.java:1180)
at com.netflix.discovery.DiscoveryClient.&init&(DiscoveryClient.java:186)
& & & & 原来 Archaius 不认 sample-eureka-service.properties,没有把我们的配置成功加载。Archaius 的官方说,Archaius 在默认情况下(就是不指定 properties 文件的情况下)会在应用的 classpath 中寻找一个名为 config.properties 的文件并读取其内容作为配置属性。
& & & & 好吧,我们把 sample-eureka-service.properties 重命名为 config.properties,然后重新运行 SampleEurekaService,访问服务器端的
http://serverIP:8080/eureka/v2/apps/ ,显示如下页面信息:
&applications&
&versions__delta&1&/versions__delta&
&apps__hashcode&UP_2_&/apps__hashcode&
&application&
&name&SAMPLESERVICE&/name&
&instance&
&hostName&defonds-win7&/hostName&
&app&SAMPLESERVICE&/app&
&ipAddr&172.21.40.134&/ipAddr&
&status&UP&/status&
&overriddenstatus&UNKNOWN&/overriddenstatus&
&port enabled=&true&&1935&/port&
&securePort enabled=&false&&443&/securePort&
&countryId&1&/countryId&
&dataCenterInfo
class=&com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo&&
&name&MyOwn&/name&
&/dataCenterInfo&
&leaseInfo&
&renewalIntervalInSecs&30&/renewalIntervalInSecs&
&durationInSecs&90&/durationInSecs&
&registrationTimestamp&3&/registrationTimestamp&
&lastRenewalTimestamp&6&/lastRenewalTimestamp&
&evictionTimestamp&0&/evictionTimestamp&
&serviceUpTimestamp&5&/serviceUpTimestamp&
&/leaseInfo&
&metadata class=&java.util.Collections$EmptyMap& /&
&appGroupName&UNKNOWN&/appGroupName&
&homePageUrl&http://defonds-win7:1935/&/homePageUrl&
&statusPageUrl&http://defonds-win7:1935/Status&/statusPageUrl&
&healthCheckUrl&http://defonds-win7:1935/healthcheck&/healthCheckUrl&
&vipAddress&sampleservice.mydomain.net&/vipAddress&
&isCoordinatingDiscoveryServer&false&/isCoordinatingDiscoveryServer&
&lastUpdatedTimestamp&3&/lastUpdatedTimestamp&
&lastDirtyTimestamp&4&/lastDirtyTimestamp&
&actionType&ADDED&/actionType&
&/instance&
&/application&
&application&
&name&EUREKA&/name&
&instance&
&hostName&localhost.localdomain&/hostName&
&app&EUREKA&/app&
&ipAddr&127.0.0.1&/ipAddr&
&status&UP&/status&
&overriddenstatus&UNKNOWN&/overriddenstatus&
&port enabled=&true&&8080&/port&
&securePort enabled=&false&&443&/securePort&
&countryId&1&/countryId&
&dataCenterInfo
class=&com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo&&
&name&MyOwn&/name&
&/dataCenterInfo&
&leaseInfo&
&renewalIntervalInSecs&30&/renewalIntervalInSecs&
&durationInSecs&90&/durationInSecs&
&registrationTimestamp&1&/registrationTimestamp&
&lastRenewalTimestamp&2&/lastRenewalTimestamp&
&evictionTimestamp&0&/evictionTimestamp&
&serviceUpTimestamp&8&/serviceUpTimestamp&
&/leaseInfo&
&metadata class=&java.util.Collections$EmptyMap& /&
&appGroupName&UNKNOWN&/appGroupName&
&homePageUrl&http://localhost.localdomain:8080/&/homePageUrl&
&statusPageUrl&http://localhost.localdomain:8080/Status
&/statusPageUrl&
&healthCheckUrl&http://localhost.localdomain:8080/healthcheck
&/healthCheckUrl&
&vipAddress&eureka.mydomain.net&/vipAddress&
&isCoordinatingDiscoveryServer&true&/isCoordinatingDiscoveryServer&
&lastUpdatedTimestamp&1&/lastUpdatedTimestamp&
&lastDirtyTimestamp&5&/lastDirtyTimestamp&
&actionType&ADDED&/actionType&
&/instance&
&/application&
&/applications&
& & & & apps__hashcode 变成 2 了。可以看出多了一个 defonds-win7 名字的 instance,它的 IP 地址正是我运行 demo 的 PC 地址 172.21.40.134 。访问
http://serverIP:8080/eureka/ 也可以看到该 instance:
& & & & 证明我们的 Application Service 已经成功注册到该台 Eureka Server。我们等待 Eureka Server 心跳访问该 Application Service,或者自己手工访问该 Application Service,以达成该服务器关闭条件,将其关闭,Application Service 成功取消注册。完整的 demo log 如下:
10:06:54,124 INFO &com.netflix.config.sources.URLConfigurationSource:125 [main] [&init&] URLs to be used as dynamic configuration source: [file:/D:/javaprojects/test/bin/config.properties]
10:06:54,259 INFO &com.netflix.config.DynamicPropertyFactory:281 [main] [getInstance] DynamicPropertyFactory is initialized with configuration sources: com.netflix.config.ConcurrentCompositeConfiguration@2f774b9b
10:08:32,464 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.
10:08:35,592 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.
10:08:45,835 INFO &com.netflix.appinfo.providers.EurekaConfigBasedInstanceInfoProvider:79 [main] [get] Setting initial instance status as: STARTING
10:08:46,331 WARN &com.netflix.discovery.DiscoveryClient:1339 [main] [getZoneOffset] DISCOVERY: Could not pick a zone based on preferred zone settings. My zone - defaultZone, preferSameZone- false. Defaulting to defaultZone
10:08:49,276 INFO &com.netflix.discovery.DiscoveryClient:646 [main] [fetchRegistry] Disable delta property : false
10:08:49,277 INFO &com.netflix.discovery.DiscoveryClient:647 [main] [fetchRegistry] Single vip registry refresh property : null
10:08:49,277 INFO &com.netflix.discovery.DiscoveryClient:648 [main] [fetchRegistry] Force full registry fetch : false
10:08:49,277 INFO &com.netflix.discovery.DiscoveryClient:649 [main] [fetchRegistry] Application is null : false
10:08:49,277 INFO &com.netflix.discovery.DiscoveryClient:650 [main] [fetchRegistry] Registered Applications size is zero : true
10:08:49,278 INFO &com.netflix.discovery.DiscoveryClient:652 [main] [fetchRegistry] Application version is -1: true
10:08:49,705 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.
10:08:49,706 INFO &com.netflix.discovery.DiscoveryClient:758 [main] [getAndStoreFullRegistry] Getting all instance registry info from the eureka server
10:08:50,501 INFO &com.netflix.discovery.DiscoveryClient:765 [main] [getAndStoreFullRegistry] The response status is 200
10:08:50,504 INFO &com.netflix.discovery.DiscoveryClient:1056 [main] [initScheduledTasks] Starting heartbeat executor: renew interval is: 30
10:09:20,508 INFO &com.netflix.discovery.DiscoveryClient:992 [DiscoveryClient-2] [makeRemoteCall] Finished a call to service url http://serverIP:8080/eureka/v2/ and url path apps/delta with status code 200.
10:09:20,535 INFO &com.netflix.discovery.DiscoveryClient$CacheRefreshThread:1542 [DiscoveryClient-2] [run] Completed cache refresh task for discovery. All Apps hash code is Local region apps hashcode: UP_1_, is fetching remote regions? false&
10:09:20,582 INFO &com.netflix.discovery.DiscoveryClient:992 [DiscoveryClient-3] [makeRemoteCall] Finished a call to service url http://serverIP:8080/eureka/v2/ and url path apps/SAMPLESERVICE/defonds-win7 with status code 404.
10:09:20,599 INFO &com.netflix.discovery.DiscoveryClient$HeartbeatThread:1415 [DiscoveryClient-3] [run] DiscoveryClient_SAMPLESERVICE/defonds-win7 - Re-registering apps/SAMPLESERVICE
10:09:20,600 INFO &com.netflix.discovery.DiscoveryClient:509 [DiscoveryClient-3] [register] DiscoveryClient_SAMPLESERVICE/defonds-win7: registering service...
10:09:20,648 INFO &com.netflix.discovery.DiscoveryClient:992 [DiscoveryClient-3] [makeRemoteCall] Finished a call to service url http://serverIP:8080/eureka/v2/ and url path apps/SAMPLESERVICE with status code 204.
10:09:20,649 INFO &com.netflix.discovery.DiscoveryClient:514 [DiscoveryClient-3] [register] DiscoveryClient_SAMPLESERVICE/defonds-win7 - registration status: 204
Waiting for service to register with eureka..
10:09:30,513 INFO &com.netflix.discovery.DiscoveryClient$InstanceInfoReplicator:1476 [DiscoveryClient-2] [run] DiscoveryClient_SAMPLESERVICE/defonds-win7 - retransmit instance info with status UP
10:09:30,514 INFO &com.netflix.discovery.DiscoveryClient:509 [DiscoveryClient-2] [register] DiscoveryClient_SAMPLESERVICE/defonds-win7: registering service...
10:09:30,561 INFO &com.netflix.discovery.DiscoveryClient:992 [DiscoveryClient-2] [makeRemoteCall] Finished a call to service url http://serverIP:8080/eureka/v2/ and url path apps/SAMPLESERVICE with status code 204.
10:09:30,562 INFO &com.netflix.discovery.DiscoveryClient:514 [DiscoveryClient-2] [register] DiscoveryClient_SAMPLESERVICE/defonds-win7 - registration status: 204
10:09:50,540 INFO &com.netflix.discovery.DiscoveryClient:992 [DiscoveryClient-1] [makeRemoteCall] Finished a call to service url http://serverIP:8080/eureka/v2/ and url path apps/delta with status code 200.
10:09:50,543 INFO &com.netflix.discovery.DiscoveryClient$CacheRefreshThread:1542 [DiscoveryClient-1] [run] Completed cache refresh task for discovery. All Apps hash code is Local region apps hashcode: UP_2_, is fetching remote regions? false&
10:09:50,654 INFO &com.netflix.discovery.DiscoveryClient:992 [DiscoveryClient-1] [makeRemoteCall] Finished a call to service url http://serverIP:8080/eureka/v2/ and url path apps/SAMPLESERVICE/defonds-win7 with status code 404.
10:09:50,654 INFO &com.netflix.discovery.DiscoveryClient$HeartbeatThread:1415 [DiscoveryClient-1] [run] DiscoveryClient_SAMPLESERVICE/defonds-win7 - Re-registering apps/SAMPLESERVICE
10:09:50,654 INFO &com.netflix.discovery.DiscoveryClient:509 [DiscoveryClient-1] [register] DiscoveryClient_SAMPLESERVICE/defonds-win7: registering service...
10:09:50,674 INFO &com.netflix.discovery.DiscoveryClient:992 [DiscoveryClient-1] [makeRemoteCall] Finished a call to service url http://serverIP:8080/eureka/v2/ and url path apps/SAMPLESERVICE with status code 204.
10:09:50,674 INFO &com.netflix.discovery.DiscoveryClient:514 [DiscoveryClient-1] [register] DiscoveryClient_SAMPLESERVICE/defonds-win7 - registration status: 204
Service started and ready to process requests..
10:10:20,548 INFO &com.netflix.discovery.DiscoveryClient:992 [DiscoveryClient-2] [makeRemoteCall] Finished a call to service url http://serverIP:8080/eureka/v2/ and url path apps/delta with status code 200.
10:10:20,551 INFO &com.netflix.discovery.DiscoveryClient$CacheRefreshThread:1542 [DiscoveryClient-2] [run] Completed cache refresh task for discovery. All Apps hash code is Local region apps hashcode: UP_2_, is fetching remote regions? false&
10:10:20,678 INFO &com.netflix.discovery.DiscoveryClient:992 [DiscoveryClient-1] [makeRemoteCall] Finished a call to service url http://serverIP:8080/eureka/v2/ and url path apps/SAMPLESERVICE/defonds-win7 with status code 200.
10:10:50,556 INFO &com.netflix.discovery.DiscoveryClient:992 [DiscoveryClient-1] [makeRemoteCall] Finished a call to service url http://serverIP:8080/eureka/v2/ and url path apps/delta with status code 200.
10:10:50,559 INFO &com.netflix.discovery.DiscoveryClient$CacheRefreshThread:1542 [DiscoveryClient-1] [run] Completed cache refresh task for discovery. All Apps hash code is Local region apps hashcode: UP_2_, is fetching remote regions? false&
10:10:50,681 INFO &com.netflix.discovery.DiscoveryClient:992 [DiscoveryClient-0] [makeRemoteCall] Finished a call to service url http://serverIP:8080/eureka/v2/ and url path apps/SAMPLESERVICE/defonds-win7 with status code 200.
10:11:20,563 INFO &com.netflix.discovery.DiscoveryClient:992 [DiscoveryClient-1] [makeRemoteCall] Finished a call to service url http://serverIP:8080/eureka/v2/ and url path apps/delta with status code 200.
10:11:20,566 INFO &com.netflix.discovery.DiscoveryClient$CacheRefreshThread:1542 [DiscoveryClient-1] [run] Completed cache refresh task for discovery. All Apps hash code is Local region apps hashcode: UP_2_, is fetching remote regions? false&
10:11:20,684 INFO &com.netflix.discovery.DiscoveryClient:992 [DiscoveryClient-1] [makeRemoteCall] Finished a call to service url http://serverIP:8080/eureka/v2/ and url path apps/SAMPLESERVICE/defonds-win7 with status code 200.
10:11:50,570 INFO &com.netflix.discovery.DiscoveryClient:992 [DiscoveryClient-2] [makeRemoteCall] Finished a call to service url http://serverIP:8080/eureka/v2/ and url path apps/delta with status code 200.
10:11:50,573 INFO &com.netflix.discovery.DiscoveryClient$CacheRefreshThread:1542 [DiscoveryClient-2] [run] Completed cache refresh task for discovery. All Apps hash code is Local region apps hashcode: UP_2_, is fetching remote regions? false&
10:11:50,687 INFO &com.netflix.discovery.DiscoveryClient:992 [DiscoveryClient-1] [makeRemoteCall] Finished a call to service url http://serverIP:8080/eureka/v2/ and url path apps/SAMPLESERVICE/defonds-win7 with status code 200.
10:12:20,579 INFO &com.netflix.discovery.DiscoveryClient:992 [DiscoveryClient-0] [makeRemoteCall] Finished a call to service url http://serverIP:8080/eureka/v2/ and url path apps/delta with status code 200.
10:12:20,582 INFO &com.netflix.discovery.DiscoveryClient$CacheRefreshThread:1542 [DiscoveryClient-0] [run] Completed cache refresh task for discovery. All Apps hash code is Local region apps hashcode: UP_2_, is fetching remote regions? false&
10:12:20,691 INFO &com.netflix.discovery.DiscoveryClient:992 [DiscoveryClient-0] [makeRemoteCall] Finished a call to service url http://serverIP:8080/eureka/v2/ and url path apps/SAMPLESERVICE/defonds-win7 with status code 200.
Client got connected..Processing request from the client
Received the request from the client.
Sending the response to the client...
10:12:27,188 INFO &com.netflix.discovery.DiscoveryClient:992 [main] [makeRemoteCall] Finished a call to service url http://serverIP:8080/eureka/v2/ and url path apps/SAMPLESERVICE/defonds-win7 with status code 200.
10:12:27,189 INFO &com.netflix.discovery.DiscoveryClient:603 [main] [unregister] DiscoveryClient_SAMPLESERVICE/defonds-win7 - deregister &status: 200
& & & & 麻雀虽小五脏俱全,例子虽小,却完整地展现了一个 Eureka Application Service 客户端的 Eureka 生命周期。
& & & & 参考资料
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致

我要回帖

更多关于 qualifying 的文章

 

随机推荐