Spring Cloud Eureka

Spring Cloud Netflix

Dalston.RELEASE

該項目通過自動配置為Spring Boot應用程序提供Netflix OSS集成,并綁定到Spring環(huán)境和其他Spring編程模型成語浇垦。通過幾個簡單的注釋苗膝,您可以快速啟用和配置應用程序中的常見模式绽左,并通過經過測試的Netflix組件構建大型分布式系統(tǒng)。提供的模式包括服務發(fā)現(Eureka),斷路器(Hystrix),智能路由(Zuul)和客戶端負載平衡(Ribbon)盆犁。

服務發(fā)現:Eureka客戶端

服務發(fā)現是基于微服務架構的關鍵原則之一。嘗試配置每個客戶端或某種形式的約定可能非常困難篡九,可以非常脆弱谐岁。Netflix服務發(fā)現服務器和客戶端是Eureka¢痪剩可以將服務器配置和部署為高可用性伊佃,每個服務器將注冊服務的狀態(tài)復制到其他服務器。

如何包含Eureka客戶端

要在您的項目中包含Eureka客戶端讽坏,請使用組org.springframework.cloud和工件ID spring-cloud-starter-eureka的啟動器。有關 使用當前的Spring Cloud發(fā)布列表設置構建系統(tǒng)的詳細信息例证,請參閱Spring Cloud項目頁面路呜。

注冊Eureka

當客戶端注冊Eureka時,它提供關于自身的元數據,例如主機和端口胀葱,健康指示符URL漠秋,主頁等。Eureka從屬于服務的每個實例接收心跳消息抵屿。如果心跳失敗超過可配置的時間表庆锦,則通常將該實例從注冊表中刪除。

示例eureka客戶端:

@Configuration
@ComponentScan
@EnableAutoConfiguration
@EnableEurekaClient
@RestController
public class Application {

    @RequestMapping("/")
    public String home() {
        return "Hello world";
    }

    public static void main(String[] args) {
        new SpringApplicationBuilder(Application.class).web(true).run(args);
    }

}

即完全正常的Spring Boot應用程序)轧葛。在這個例子中搂抒,我們明確地使用@EnableEurekaClient,但只有Eureka可用尿扯,你也可以使用@EnableDiscoveryClient求晶。需要配置才能找到Eureka服務器。例:

application.yml

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

其中“defaultZone”是一個魔術字符串后備值衷笋,為任何不表示首選項的客戶端提供服務URL(即它是有用的默認值)芳杏。

Environment獲取的默認應用程序名稱(服務ID),虛擬主機和非安全端口分別為${spring.application.name}辟宗,${spring.application.name}${server.port}爵赵。

@EnableEurekaClient將應用程序同時進入一個Eureka“實例”(即注冊自己)和一個“客戶端”(即它可以查詢注冊表以查找其他服務)。實例行為由eureka.instance.*配置鍵驅動泊脐,但是如果您確保您的應用程序具有spring.application.name(這是Eureka服務ID或VIP的默認值)空幻,那么默認值將是正常的。

有關可配置選項的更多詳細信息晨抡,請參閱EurekaInstanceConfigBeanEurekaClientConfigBean氛悬。

使用Eureka服務器進行身份驗證

如果其中一個eureka.client.serviceUrl.defaultZone網址中包含一個憑據(如http://user:password@localhost:8761/eureka)),HTTP基本身份驗證將自動添加到您的eureka客戶端耘柱。對于更復雜的需求如捅,您可以創(chuàng)建DiscoveryClientOptionalArgs類型的@Bean,并將ClientFilter實例注入到其中调煎,所有這些都將應用于從客戶端到服務器的調用镜遣。

注意: 由于Eureka中的限制,不可能支持每個服務器的基本身份驗證憑據士袄,所以只能使用第一個找到的集合悲关。

狀態(tài)頁和健康指標

Eureka實例的狀態(tài)頁面和運行狀況指示器分別默認為“/ info”和“/ health”,它們是Spring Boot執(zhí)行器應用程序中有用端點的默認位置娄柳。如果您使用非默認上下文路徑或servlet路徑(例如server.servletPath=/foo)或管理端點路徑(例如management.contextPath=/admin)寓辱,則需要更改這些,即使是執(zhí)行器應用程序赤拒。例:

application.yml

eureka:
  instance:
    statusPageUrlPath: ${management.context-path}/info
    healthCheckUrlPath: ${management.context-path}/health

這些鏈接顯示在客戶端使用的元數據中秫筏,并在某些情況下用于決定是否將請求發(fā)送到應用程序诱鞠,因此如果它們是準確的,這是有幫助的这敬。

注冊安全應用程序

如果您的應用程序想通過HTTPS聯系航夺,則可以分別在EurekaInstanceConfig eureka.instance.[nonSecurePortEnabled,securePortEnabled]=[false,true] 中設置兩個標志崔涂。這將使Eureka發(fā)布實例信息顯示安全通信的明確偏好阳掐。Spring Cloud DiscoveryClient將始終為以這種方式配置的服務返回一個https://…; URI,并且Eureka(本機)實例信息將具有安全的健康檢查URL冷蚂。

由于Eureka內部的工作方式缭保,它仍然會發(fā)布狀態(tài)和主頁的非安全網址,除非您也明確地覆蓋帝雇。您可以使用占位符來配置eureka實例URL涮俄,例如

application.yml

eureka:
  instance:
    statusPageUrl: https://${eureka.hostname}/info
    healthCheckUrl: https://${eureka.hostname}/health
    homePageUrl: https://${eureka.hostname}/

請注意,${eureka.hostname}是僅在稍后版本的Eureka中可用的本地占位符尸闸,您也可以使用Spring占位符實現同樣的功能彻亲,例如使用${eureka.instance.hostName}

注意:

如果您的應用程序在代理服務器后面運行吮廉,并且SSL終止服務在代理中(例如苞尝,如果您運行在Cloud Foundry或其他平臺作為服務),則需要確保代理“轉發(fā)”頭部被截取并處理應用程序宦芦。Spring Boot應用程序中的嵌入式Tomcat容器會自動執(zhí)行“X-Forwarded - \ *”標頭的顯式配置宙址。你這個錯誤的一個跡象就是你的應用程序本身所呈現的鏈接是錯誤的(錯誤的主機,端口或協(xié)議)调卑。

Eureka的健康檢查

默認情況下抡砂,Eureka使用客戶端心跳來確定客戶端是否啟動。除非另有規(guī)定恬涧,否則發(fā)現客戶端將不會根據Spring Boot執(zhí)行器傳播應用程序的當前運行狀況檢查狀態(tài)注益。這意味著成功注冊后Eureka將永遠宣布申請?zhí)幱凇癠P”狀態(tài)。通過啟用Eureka運行狀況檢查可以改變此行為溯捆,從而將應用程序狀態(tài)傳播到Eureka丑搔。因此,每個其他應用程序將不會在“UP”之外的狀態(tài)下將流量發(fā)送到應用程序提揍。

application.yml

eureka:
  client:
    healthcheck:
      enabled: true

警告: eureka.client.healthcheck.enabled=true只能在application.yml中設置啤月。設置bootstrap.yml中的值將導致不期望的副作用,例如在具有UNKNOWN狀態(tài)的eureka中注冊劳跃。

如果您需要更多的控制健康檢查谎仲,您可以考慮實施自己的com.netflix.appinfo.HealthCheckHandler

Eureka實例和客戶端的元數據

值得花點時間了解Eureka元數據的工作原理刨仑,以便您可以在平臺上使用它郑诺。有主機名绞呈,IP地址,端口號间景,狀態(tài)頁和運行狀況檢查等標準元數據。這些發(fā)布在服務注冊表中艺智,由客戶使用倘要,以直接的方式聯系服務。額外的元數據可以添加到eureka.instance.metadataMap中的實例注冊中十拣,并且這將在遠程客戶端中可訪問封拧,但一般不會更改客戶端的行為,除非意識到元數據的含義夭问。下面描述了幾個特殊情況泽西,其中Spring Cloud已經為元數據映射指定了含義。

在Cloudfoundry上使用Eureka

Cloudfoundry有一個全局路由器缰趋,所以同一個應用程序的所有實例都具有相同的主機名(在具有相似架構的其他PaaS解決方案中也是如此)捧杉。這不一定是使用Eureka的障礙,但如果您使用路由器(建議秘血,甚至是強制性的味抖,具體取決于您的平臺的設置方式),則需要明確設置主機名和端口號(安全或非安全)灰粮,以便他們使用路由器仔涩。您可能還需要使用實例元數據,以便您可以區(qū)分客戶端上的實例(例如粘舟,在自定義負載平衡器中)熔脂。默認情況下,eureka.instance.instanceIdvcap.application.instance_id柑肴。例如:

application.yml

eureka:
  instance:
    hostname: ${vcap.application.uris[0]}
    nonSecurePort: 80

根據Cloudfoundry實例中安全規(guī)則的設置方式霞揉,您可以注冊并使用主機VM的IP地址進行直接的服務到服務調用。此功能尚未在Pivotal Web Services(PWS)上提供嘉抒。

在AWS上使用Eureka

如果應用程序計劃將部署到AWS云零聚,那么Eureka實例必須被配置為AWS意識到,這可以通過定制來完成EurekaInstanceConfigBean方式如下:

@Bean
@Profile("!default")
public EurekaInstanceConfigBean eurekaInstanceConfig(InetUtils inetUtils) {
  EurekaInstanceConfigBean b = new EurekaInstanceConfigBean(inetUtils);
  AmazonInfo info = AmazonInfo.Builder.newBuilder().autoBuild("eureka");
  b.setDataCenterInfo(info);
  return b;
}

更改Eureka實例ID

一個標準的 Netflix_實例注冊的ID等于其主機名(即每個主機只有一個服務)些侍。Spring Cloud Eureka提供了一個明智的默認隶症,如下所示:

${spring.cloud.client.hostname}:${spring.application.name}:${spring.application.instance_id:${server.port}}}

例如myhost:myappname:8080岗宣。

使用Spring Cloud蚂会,您可以通過在eureka.instance.instanceId中提供唯一的標識符來覆蓋此。例如:

application.yml

eureka:
  instance:
    instanceId: ${spring.application.name}:${vcap.application.instance_id:${spring.application.instance_id:${random.value}}}

使用這個元數據和在localhost上部署的多個服務實例耗式,隨機值將在那里進行胁住,以使實例是唯一的趁猴。在Cloudfoundry中,vcap.application.instance_id將在Spring Boot應用程序中自動填充彪见,因此不需要隨機值儡司。

使用EurekaClient

一旦您擁有@EnableDiscoveryClient(或@EnableEurekaClient)的應用程序,您就可以使用它來從Eureka服務器發(fā)現服務實例余指。一種方法是使用本機com.netflix.discovery.EurekaClient(而不是Spring云DiscoveryClient)捕犬,例如

@Autowired
private EurekaClient discoveryClient;

public String serviceUrl() {
    InstanceInfo instance = discoveryClient.getNextServerFromEureka("STORES", false);
    return instance.getHomePageUrl();
}

提示

不要使用@PostConstruct方法或@Scheduled方法(或ApplicationContext可能尚未啟動的任何地方)EurekaClient。它被初始化為SmartLifecycle(帶有phase=0)酵镜,所以最早可以依靠它可用的是另一個具有更高階段的SmartLifecycle碉碉。

本機Netflix EurekaClient的替代方案

您不必使用原始的Netflix EurekaClient,通常在某種包裝器后面使用它更為方便淮韭。Spring Cloud支持Feign(REST客戶端構建器)垢粮,還支持Spring RestTemplate使用邏輯Eureka服務標識符(VIP)而不是物理URL。要使用固定的物理服務器列表配置Ribbon靠粪,您可以將<client>.ribbon.listOfServers設置為逗號分隔的物理地址(或主機名)列表蜡吧,其中<client>是客戶端的ID。

您還可以使用org.springframework.cloud.client.discovery.DiscoveryClient占键,它為Netflix不具體的發(fā)現客戶端提供簡單的API斩跌,例如

@Autowired
private DiscoveryClient discoveryClient;

public String serviceUrl() {
    List<ServiceInstance> list = discoveryClient.getInstances("STORES");
    if (list != null && list.size() > 0 ) {
        return list.get(0).getUri();
    }
    return null;
}

為什么注冊服務這么慢?

作為一個實例也包括定期心跳到注冊表(通過客戶端的serviceUrl)捞慌,默認持續(xù)時間為30秒耀鸦。在實例,服務器和客戶端在其本地緩存中都具有相同的元數據(因此可能需要3個心跳)之前啸澡,客戶端才能發(fā)現服務袖订。您可以使用eureka.instance.leaseRenewalIntervalInSeconds更改期限,這將加快客戶端連接到其他服務的過程嗅虏。在生產中洛姑,最好堅持使用默認值,因為服務器內部有一些計算可以對租賃更新期進行假設皮服。

區(qū)

如果您已將Eureka客戶端部署到多個區(qū)域楞艾,您可能希望這些客戶端在使用另一個區(qū)域中的服務之前,利用同一區(qū)域內的服務龄广。為此硫眯,您需要正確配置您的Eureka客戶端。

首先择同,您需要確保將Eureka服務器部署到每個區(qū)域两入,并且它們是彼此的對等體。有關詳細信息敲才,請參閱區(qū)域和區(qū)域部分 裹纳。

接下來择葡,您需要告知Eureka您的服務所在的區(qū)域。您可以使用metadataMap屬性來執(zhí)行此操作剃氧。例如敏储,如果service 1部署到zone 1zone 2,則需要在service 1中設置以下Eureka屬性

1區(qū)服務1

eureka.instance.metadataMap.zone = zone1
eureka.client.preferSameZoneEureka = true

第2區(qū)的服務1

eureka.instance.metadataMap.zone = zone2
eureka.client.preferSameZoneEureka = true

服務發(fā)現:Eureka服務器

如何包含Eureka服務器

要在項目中包含Eureka服務器朋鞍,請使用組org.springframework.cloud和工件id spring-cloud-starter-eureka-server的啟動器虹曙。有關 使用當前的Spring Cloud發(fā)布列表設置構建系統(tǒng)的詳細信息,請參閱Spring Cloud項目頁面番舆。

如何運行Eureka服務器

示例eureka服務器;

@SpringBootApplication
@EnableEurekaServer
public class Application {

    public static void main(String[] args) {
        new SpringApplicationBuilder(Application.class).web(true).run(args);
    }

}

服務器具有一個帶有UI的主頁,并且根據/eureka/*下的正常Eureka功能的HTTP API端點矾踱。

Eureka背景閱讀:看助焊劑電容谷歌小組討論恨狈。

提示:

由于Gradle的依賴關系解決規(guī)則和父母的bom功能缺乏,只要依靠spring-cloud-starter-eureka-server就可能導致應用程序啟動失敗呛讲。要解決這個問題禾怠,必須添加Spring Boot Gradle插件,并且必須導入Spring云啟動器父母bom:

build.gradle

buildscript {
  dependencies {
    classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.5.RELEASE")
  }
}

apply plugin: "spring-boot"

dependencyManagement {
  imports {
    mavenBom "org.springframework.cloud:spring-cloud-dependencies:Brixton.RELEASE"
  }
}

高可用性贝搁,區(qū)域和地區(qū)

Eureka服務器沒有后端存儲吗氏,但是注冊表中的服務實例都必須發(fā)送心跳以保持其注冊更新(因此可以在內存中完成)±啄妫客戶端還具有eureka注冊的內存緩存(因此弦讽,他們不必為注冊表提供每個服務請求)。

默認情況下膀哲,每個Eureka服務器也是一個Eureka客戶端往产,并且需要(至少一個)服務URL來定位對等體。如果您不提供該服務將運行和工作某宪,但它將淋浴您的日志與大量的噪音無法注冊對等體仿村。

關于區(qū)域和區(qū)域的客戶端Ribbon支持的詳細信息,請參見下文兴喂。

獨立模式

只要存在某種監(jiān)視器或彈性運行時間(例如Cloud Foundry)蔼囊,兩個高速緩存(客戶機和服務器)和心跳的組合使獨立的Eureka服務器對故障具有相當的彈性。在獨立模式下衣迷,您可能更喜歡關閉客戶端行為畏鼓,因此不會繼續(xù)嘗試并且無法訪問其對等體。例:

application.yml(Standalone Eureka Server)

server:
  port: 8761

eureka:
  instance:
    hostname: localhost
  client:
    registerWithEureka: false
    fetchRegistry: false
    serviceUrl:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

請注意壶谒,serviceUrl指向與本地實例相同的主機滴肿。

同行意識

通過運行多個實例并請求他們相互注冊勺届,可以使Eureka更具彈性和可用性想许。事實上腾誉,這是默認的行為蚌斩,所以你需要做的只是為對方添加一個有效的serviceUrl,例如

application.yml(Two Peer Aware Eureka服務器)

---
spring:
  profiles: peer1
eureka:
  instance:
    hostname: peer1
  client:
    serviceUrl:
      defaultZone: http://peer2/eureka/

---
spring:
  profiles: peer2
eureka:
  instance:
    hostname: peer2
  client:
    serviceUrl:
      defaultZone: http://peer1/eureka/

在這個例子中堆缘,我們有一個YAML文件滔灶,可以通過在不同的Spring配置文件中運行,在2臺主機(peer1和peer2)上運行相同的服務器吼肥。您可以使用此配置來測試單個主機上的對等體感知(通過操作/etc/hosts來解析主機名录平,在生產中沒有太多價值)。事實上缀皱,如果您在一臺知道自己的主機名的機器上運行(默認情況下使用java.net.InetAddress查找)斗这,則不需要eureka.instance.hostname

您可以向系統(tǒng)添加多個對等體啤斗,只要它們至少一個邊緣彼此連接表箭,則它們將在它們之間同步注冊。如果對等體在物理上分離(在數據中心內或多個數據中心之間)钮莲,則系統(tǒng)原則上可以分裂腦型故障免钻。

喜歡IP地址

在某些情況下,Eureka優(yōu)先發(fā)布服務的IP地址而不是主機名崔拥。將eureka.instance.preferIpAddress設置為true极舔,并且當應用程序向eureka注冊時,它將使用其IP地址而不是其主機名链瓦。

保護Eureka服務器

只需將Spring Security添加到服務器的類路徑中即可保護您的Eureka服務器spring-boot-starter-security拆魏。默認情況下,當Spring Security位于類路徑上時慈俯,它將要求在應用程序的每個請求中發(fā)送有效的CSRF令牌稽揭。Eureka客戶端通常不會擁有有效的跨站點請求偽造(CSRF)令牌,您需要為/eureka/**端點禁用此要求肥卡。例如:

@EnableWebSecurity
class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().ignoringAntMatchers("/eureka/**");
        super.configure(http);
    }
}

有關CSRF的更多信息溪掀,請參閱Spring Security文檔

可以在Spring Cloud Samples 回購中找到演示Eureka Server 步鉴。

JDK 11支持

在JDK 11中刪除了Eureka服務器所依賴的JAXB模塊揪胃。如果您打算在運行Eureka服務器時使用JDK 11,則必須在POM或Gradle文件中包含這些依賴項氛琢。

<dependency>
    <groupId>org.glassfish.jaxb</groupId>
    <artifactId>jaxb-runtime</artifactId>
</dependency>

筆記來自Spring Cloud官方文檔

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末喊递,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子阳似,更是在濱河造成了極大的恐慌骚勘,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,743評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異俏讹,居然都是意外死亡当宴,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 90,296評論 3 385
  • 文/潘曉璐 我一進店門泽疆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來户矢,“玉大人,你說我怎么就攤上這事殉疼√堇耍” “怎么了?”我有些...
    開封第一講書人閱讀 157,285評論 0 348
  • 文/不壞的土叔 我叫張陵瓢娜,是天一觀的道長挂洛。 經常有香客問我,道長眠砾,這世上最難降的妖魔是什么虏劲? 我笑而不...
    開封第一講書人閱讀 56,485評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮荠藤,結果婚禮上,老公的妹妹穿的比我還像新娘获高。我一直安慰自己哈肖,他們只是感情好,可當我...
    茶點故事閱讀 65,581評論 6 386
  • 文/花漫 我一把揭開白布念秧。 她就那樣靜靜地躺著淤井,像睡著了一般。 火紅的嫁衣襯著肌膚如雪摊趾。 梳的紋絲不亂的頭發(fā)上币狠,一...
    開封第一講書人閱讀 49,821評論 1 290
  • 那天,我揣著相機與錄音砾层,去河邊找鬼漩绵。 笑死,一個胖子當著我的面吹牛肛炮,可吹牛的內容都是我干的止吐。 我是一名探鬼主播,決...
    沈念sama閱讀 38,960評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼侨糟,長吁一口氣:“原來是場噩夢啊……” “哼碍扔!你這毒婦竟也來了?” 一聲冷哼從身側響起秕重,我...
    開封第一講書人閱讀 37,719評論 0 266
  • 序言:老撾萬榮一對情侶失蹤不同,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體二拐,經...
    沈念sama閱讀 44,186評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡服鹅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,516評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了卓鹿。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片菱魔。...
    茶點故事閱讀 38,650評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖吟孙,靈堂內的尸體忽然破棺而出澜倦,到底是詐尸還是另有隱情,我是刑警寧澤杰妓,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布藻治,位于F島的核電站,受9級特大地震影響巷挥,放射性物質發(fā)生泄漏桩卵。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,936評論 3 313
  • 文/蒙蒙 一倍宾、第九天 我趴在偏房一處隱蔽的房頂上張望雏节。 院中可真熱鬧,春花似錦高职、人聲如沸钩乍。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽寥粹。三九已至,卻和暖如春埃元,著一層夾襖步出監(jiān)牢的瞬間涝涤,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評論 1 266
  • 我被黑心中介騙來泰國打工岛杀, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留阔拳,地道東北人。 一個月前我還...
    沈念sama閱讀 46,370評論 2 360
  • 正文 我出身青樓类嗤,卻偏偏與公主長得像衫生,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子土浸,可洞房花燭夜當晚...
    茶點故事閱讀 43,527評論 2 349