天天看點

Spring Cloud Netflix之Eureka Doc Translation

發博詞

​​Spring Cloud Netflix文檔​​,看這篇文檔時,搜幾個其中的關鍵詞時,發現了幾篇中文翻譯,随便看了幾段,發現跟翻譯機器人翻譯的有一拼,估計自己根本就沒明白其中的意思,就更别說翻譯對了。此文是在意譯的基礎上,将大部分應該代詞直接替換成指代的實際對象,有歧義的地方應該比較少了。根據國内的情況,省略了部分翻譯;如果發現有問題或者翻譯不對的地方,歡迎留言讨論。

Service Discovery: Eureka Clients

微服務架構的關鍵準則之一就是有一個服務發現政策。嘗試去手動配置或者使用某種形式的約定來确定某個遠端服務會導緻應用非常脆弱。Eurka提供了服務發現的服務端和用戶端兩個元件。Eurka服務端可以配置成高可用,某個Eurka服務端可以複制注冊的服務資訊給其他的Eurka服務端。

How to Include Eureka Client

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>      

Registering with Eureka

當一個Eurka用戶端注冊到一個Eurka服務端時,需要提供關于這個用戶端的一些中繼資料,比如:host、port、health indicator url 位址、home page首頁位址等等。Eureka 服務端接收來自注冊到這個服務端的各個Eureka 用戶端的心跳消息。如果心跳檢測逾時,Eureka服務端将删除此用戶端的注冊資訊。

[Example eureka client]

@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);
    }

}      

上邊的代碼使用了@EnableEurekaClient為應用開啟Eureka用戶端的功能,如果你的應用中隻有Eureka一種用戶端,也可以使用@EnableDiscoveryClient來實作同樣的效果。此外,還需要給Eureka用戶端指定Eureka服務端的資訊。例如:

[application.yml]

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

可以分别使用${spring.application.name}, ${spring.application.name} and ${server.port}來從Spring Cloud的運作時環境中擷取應用的名字(service id)、主機位址和端口号。

@EnableEurekaClient注解把應用轉化為一個Eureka Instance(可以自己注冊到Eureka伺服器,可以被别的服務使用)和一個Eureka Client(可以使用别的服務)。

Eureka Instance的表現用eureka.instance.*格式的配置來控制,但是如果你給應用指定了一個spring.application.name屬性的話,大部分情況下,預設值就夠用了;spring.application.name的值會被Eureka用來當作這個服務提供者的Service ID。

想檢視更多的配置,可以去spring-cloud-netflix-eureka-client子產品下面搜尋EurekaInstanceConfigBean和EurekaClientConfigBean類來擷取更多的資訊。

Authenticating with the Eureka Server

如果eureka.client.serviceUrl.defaultZone設定的url,内嵌了身份認證,比如http://user:password@localhost:8761/eureka這樣curl風格的格式,HTTP basic authentication認證機制将會被自動添加到Eureka用戶端。如果你的需求更複雜,可以使用@Bean注解建立一個DiscoveryClientOptionalArgs 類型的bean,同時注入ClientFilter 的執行個體給這個bean,這個配置會在每一次Eureka用戶端到Eureka服務端的調用中起作用。

Status Page and Health Indicator

一個Eureka Instance的狀态頁面和健康訓示頁面的預設位址分别是/info和/health,在一個Spring Boot Actuator的應用中這是預設位址是非常重要的endpoint。

如果你沒有使用預設的context path和servlet path (例如:server.servletPath=/foo)或者management endpoint path(例如:management.contextPath=/admin),你需要像下面這樣改變這兩個配置的值:

[application.yml]

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

上邊的兩個配置,在某些場景下,會被用來決定是否給你的應用發送請求,是以正确的設定這兩個值是非常有幫助的。

Registering a Secure Application

如果你的應用是通過HTTPS協定通路的,那麼你可以設定EurekaInstanceConfig中的兩個标志字段, eureka.instance.[nonSecurePortEnabled,securePortEnabled]=[false,true] 。這将明确的告訴Eureka執行個體通過HTTPS協定發送自身的資訊。經過上邊的配置,Spring Cloud的DiscoveryClient 将總是傳回一個https://開頭的url位址。Eureka Instance的health check url位址也将是https://協定的。

上邊的配置是配置的Eureka内部的工作方式,對于維護人員需要通路的status url和home page url,除非明确的配置,否則還是HTTP協定的。可以像下面這樣覆寫預設的配置:

[application.yml]

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

Eureka’s Health Checks

預設的,Eureka将會使用心跳來确定一個Eureka用戶端是否線上。除非特别指定,Discovery Client 将不會傳播應用目前的健康檢測狀态給Spring Boot Actuator。這也就意味着,當Eureka Client注冊成功之後,這個Eureka Instance的執行個體的狀态将不會再改變,一直是UP狀态。我們可以通過啟用健康檢查來,持續的傳播應用的狀态給Eureka。這樣,就隻有狀态時UP的應用才會接收到請求負載。

[application.yml]

eureka:
  client:
    healthcheck:
      enabled: true      

警告:eureka.client.healthcheck.enabled=true應該隻在application.yml中被設定。如果設定在bootstrap.yml将會引起不可預知的影響比如注冊eureka出現unknown status。

如果你想更多的控制health checks的行為,你可以考慮實作你自己的com.netflix.appinfo.HealthCheckHandler。

Eureka Metadata for Instances and Clients

花一點時間了解一下Eureka中繼資料是如何工作的是非常值得的,因為有時候,你可能要使用這些中繼資料做一些有意義的事情。前面提到了一些常用的中繼資料:hostname、ip、port、status page url、health check等。這些中繼資料在Eureka Client注冊時被推送到Eureka Server,然後其他的用戶端在想使用此執行個體提供的服務時,可以直接連接配接到此Eureka Instance。通過eureka.instance.metadataMap,我們還可以添加一些其他的中繼資料,這些中繼資料同樣可以在其他的遠端Eureka Client中擷取到,但是這些中繼資料一般來說,不會改變Eureka Client的表現,除非Eureka Client了解這些中繼資料的意義。

Using Eureka on Cloudfoundry

略。

Using Eureka on AWS

略。

Changing the Eureka Instance ID

一個普通的Netflix Eureka Instance注冊到Eureka Server上時的id的值為目前主機的hostname(也就是說,一台機器一個service執行個體)。但是Spring Cloud Eureka提供了一個更合乎情理的預設值:

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

例如:

myhost:myappname:8080      

使用Spring Cloud Eureka時,你也可以提供一個唯一辨別字元串給eureka.instance.instanceId。例如:

[application.yml]

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

這樣,你就可以在本地部署多個service執行個體了,最後的随機值将将instanceId的值唯一。

Using the EurekaClient

一旦你的app使用@EnableDiscoveryClient 或者@EnableEurekaClient配置,他将會從Eureka Server發現所有的服務執行個體。一種方式是使用Eureka原聲的API,com.netflix.discovery.EurekaClient,另一種方式是使用Spring Cloud的api DiscoveryClient。

@Autowired
private EurekaClient discoveryClient;

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

注意

Don’t use the EurekaClient in @PostConstruct method or in a @Scheduled method (or anywhere where the ApplicationContext might not be started yet). It is initialized in a SmartLifecycle (with phase=0) so the earliest you can rely on it being available is in another SmartLifecycle with higher phase.

Alternatives to the native Netflix EurekaClient

略。

Why is it so Slow to Register a Service?

略。

Zones

如果你将所有的Eureka用戶端分成多個區域,你可能希望這些用戶端在擷取其他的服務時,首先嘗試同一個區域内的其他服務,在嘗試其他區域的其他服務。Eureka提供了這個功能,你隻需要正确使用就可以實作這個目标。

首先,你需要确認每個zone都有多個Eureka Server,而且他們互相連結。

下一步你需要做的是告訴Eureka Server你的服務在哪一個zone。可以使用metadataMap 屬性來傳遞這個資訊。例如,如果service1部署在zone1和zone2,你需要像下面這樣去配置:

[Service 1 in Zone 1]

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

[Service 1 in Zone 2]

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

Notice

  1. EnableEurekaClient和EnableDiscoveryClient的差別?

​​What’s the difference between EnableEurekaClient and EnableDiscoveryClient?​​

SpringCLoud中的“Discovery Service”有多種實作,比如:eureka, consul, zookeeper。

1,@EnableDiscoveryClient注解是基于spring-cloud-commons依賴,并且在classpath中實作;

2,@EnableEurekaClient注解是基于spring-cloud-netflix依賴,隻能為eureka作用;

如果你的classpath中添加了eureka,則它們的作用是一樣的。

  1. DiscoveryClientOptionalArgs的用法?

​​com.netflix.discovery.DiscoveryClient.DiscoveryClientOptionalArgs​​

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@EnableDiscoveryClient
public @interface EnableEurekaClient {

}      

Service Discovery: Eureka Server

How to Include Eureka Server

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>      

How to Run a Eureka Server

[Example eureka server]

@SpringBootApplication
@EnableEurekaServer
public class Application {

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

}      

High Availability, Zones and Regions

Eureka Server沒有後端存儲,但是所有注冊過的服務執行個體必須發送心跳消息來更新他們自己的注冊資訊(這是沒有後端存儲的原因)。所有的Eureka Client也有一個所有Eureka Client的注冊資訊的緩存,存儲在記憶體中(是以這些用戶端不必在每一次調用其他服務的時候去Eureka Server拉取注冊資訊)。

預設情況下,每一個Eureka Server也是一個Eureka Client,需要至少一個service url來定位另一Eureka Server。如果沒有提供,也能正常工作,但是将會不斷的報出日志告訴你不能注冊。

Standalone Mode

隻要Client和Server活着,Eureka Client和Eureka Server的集合和心跳政策可以使一個Eureka Server能在緩存失效時完全複原。在非叢集模式下,你可能更希望關閉Eureka Client不停拉取注冊的client的資訊的功能,以此來停止擷取注冊資訊持續的失敗的情況下繼續嘗試。

[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 Server執行個體。

Peer Awareness

Eureka可以通過運作多個執行個體,互相注冊來提高彈性和可用性。事實上,這也是Eureka預設的行為,給一個Eureka Server執行個體添加一個有效的serviceUrl 就可以使其這麼工作了。

[application.yml (Two Peer Aware Eureka Servers)]

---
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/      

上邊的樣例配置,通過運作在不同的spring profile,可以運作同一個server在兩台不同的機器上。你可以使用這個配置檔案在一台主機上測試互相發現,想要解析peer1和peer2這兩個hostname的話,需要修改本機的hosts檔案。事實上,如果你的應用運作在一個知道自己的hostname的機器上(預設會使用java.net.InetAddress擷取主機名),eureka.instance.hostname是不用設定的。

Prefer IP Address