[Spring Cloud] 4.1 Spring Cloud Netflix : Netflix 實現

Spring Cloud Netflix : Netflix 實現

Netflix是一家在線影片租賃提供商。java

Netflix 開源軟件git

NetflixOSS github

Spring Cloud Netflix 經過自動配置以及綁定Spring環境中的其餘模塊的方式將Netflix OSS與Spring Boot 應用進行整合。web

經過簡單的註解就能夠快速在應用中開啓一個標準配置的大型分佈式及高可用的Netflix組件。spring

標準配置 包括:服務發現(Eureka);斷路器(Hystrix);智能路由(Zuul);客戶端負載均衡(Ribbonbootstrap

4.1 Service Discovery: Eureka Clients 服務發現:Eureka客戶端

服務發現是微服務架構中重要的一個概念。通常來講,在每一個客戶端進行配置或者某種形式的約定來進行服務調用是很麻煩的,並且須要頻繁修改。 Eureka 是Netflix服務發現服務以及客戶端的實現。服務可以以一種高可用的方式進行配置和部署,對於每一個註冊的服務彼此間都會進行狀態複製。緩存

4.1.1 Registering with Eureka 經過Eureka進行服務註冊

當一個註冊器客戶端經過Eureka進行註冊時,它會帶上一些描述本身狀況的元數據,如:地址、端口、健康指示器地址、主頁等等。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請求。(默認請求處理地址)

默認應用名(服務ID)、虛擬地址和端口,會從Environment中獲取:${spring.application.name}${spring.application.name}${server.port}

@EnableEurekaClient會讓應用既作爲一個Eurake實例,同時也做爲一個Eurake的客戶端(可以經過這個客戶端,查詢到註冊的本地其餘服務)。Eurake實例能夠經過eureka.instance.*相關配置項進行配置。默認狀況下使用spring.application.name做爲註冊服務的service ID 和 虛擬IP

具體配置相能夠參見 EurekaInstanceConfigBeanEurekaClientConfigBean

4.1.2 Authenticating with the Eureka Server :Eureka服務的身份認證

若是eureka.client.serviceUrl.defaultZone的URL中嵌入了帳號信息則Eurake客戶端會自動使用HTTP basic 認證。(如:http://user:password@localhost:8761/eureka

若是須要更爲複雜的認證方式,能夠本身實現一個DiscoveryClientOptionalArgs而後注入一個ClientFilter實例,這樣客戶端與服務端的調用都會通過這個Filter。

注意: 因爲Eurake的限制,不可能爲每個服務配置單獨的認證,所以第一個被發現的認證方式會被使用。

4.1.3 Status Page and Health Indicator 狀態頁和健康指示器

一個Eurake實例的狀態頁和健康指示器默認爲:/info/health,這兩個是由Spring Boot Actuator應用提供的訪問端點。能夠經過如下方式進行修改:

application.yml

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

這些地址將會被用於客戶端元數據的獲取,以及必要的檢測時使用。所以,這些端點是頗有用的。

4.1.4 Registering a Secure Application 註冊一個安全的應用

若是你想讓應用之間經過HTTPS通信,那能夠在EurekaInstanceConfig中配置兩個開關: eureka.instance.[nonSecurePortEnabled,securePortEnabled]=[false,true]。 這樣Eureka就會經過安全方式發佈實例信息。 這樣的話,Spring Cloud 的DiscoveryClient將會爲已註冊的服務返回一個https://…URI, 同時Eureka實例信息將會提供一個安全的健康檢查URL。

因爲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可能被代理清理掉。並且,代理可能致使你得到的來源端口、地址不正確

4.1.5 Eureka’s Health Checks : Eureka的健康檢查

默認狀況下,Eureka經過客戶端心跳包來檢測客戶端狀態。沒有額外配置的狀況下Discovery客戶端不會爲每個Spring Boot 應用發起額外的健康檢查。這樣,也就意味着,一旦服務註冊成功後,Eureka總會認爲應用是在線狀態。 固然,也能夠開啓Eureka的健康檢查,這樣應用狀態就能夠轉播給Eureka了。

application.yml

eureka:
  client:
    healthcheck:
      enabled: true

警告:eureka.client.healthcheck.enabled=true只能在application.yml中設置,若是在bootstrap.yml中設置,會致使Eureka在註冊時獲得一個UNKNOWN的狀態

若是須要更多的健康檢查控制,能夠本身實現一個com.netflix.appinfo.HealthCheckHandler.

4.1.6 Eureka Metadata for Instances and Clients : Eureka實例和客戶端的元數據

花些時間去了解Eureka的元數據是值得的,你能夠在這個過程當中對本身平臺有更清楚的認識。標準的元數據例如:主機名,IP地址,端口號,狀態頁,健康檢查。這些會在服務註冊以及客戶端直連服務端時被髮布出來。對於實例註冊時,能夠經過eureka.instance.metadataMap配置額外的元數據信息,這樣不會對客戶端有啥影響,除非客戶端能本身處理某些特殊元數據。後面還會繼續說明元數據在Spring Cloud 中的意義。

4.1.6.1 Using Eureka on Cloudfoundry : 在Cloudfoundry中使用Eureka

Cloudfoundry提供了針對全部實例中相同主機名相同應用的全局路由功能。相似一個小型PaaS平臺。這個不是Eureka必要的功能,但仍是建議開啓此功能。開啓時,須要明確指定主機名和端口號。能夠經過設置實例的元數據來讓客戶端區分不一樣的實例,默認經過eureka.instance.instanceIdvcap.application.instance_id來區分。例如:

application.yml

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

經過這種方式來設置Cloudfoundry實例的安全規則,你能夠註冊並使用虛擬主機的IP地址進行服務之間的調用。這個特性還不能在PWS(Pivotal Web Services)環境下使用。

4.1.6.2 Using Eureka on AWS : 在AWS中使用Eureka

若是須要在AWS中部署Eureka,能夠定製一個EurekaInstanceConfigBean

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

4.1.6.3 Changing the Eureka Instance ID : 修改Eureka實例ID

普通的Netflix Eureka實例註冊時使用主機名做爲實例ID。Spring Cloud Eureka提供了一個更爲合理的ID策略:${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}}}

若是多個服務實例部署在同一個主機上,那這個元數據會加上一個隨機數,保證明例惟一性。 在一個Spring Boot 應用中,Cloudfoundry的vcap.application.instance_id會被自動賦值,不須要隨機數。

4.1.7 Using the EurekaClient

一旦在應用中使用了@EnableDiscoveryClient 或者@EnableEurekaClient,那你就能夠從Eureka Server中使用服務發現功能。 還有一種方法就是直接使用原生的com.netflix.discovery.EurekaClient(對應Spring Cloud的DiscoveryClient)。例如:

@Autowired
private EurekaClient discoveryClient;

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

提示:不要在@PostConstruct方法以及@Scheduled中(或者任何ApplicationContext還沒初始完成的地方)使用EurekaClient。其須要等待SmartLifecyclephase=0)初始化完成才能夠

4.1.8 Alternatives to the native Netflix EurekaClient : 如何決定是否使用原生Netflix Eureka客戶端

一般來講,不須要直接使用原始的Netflix 的EurekaClient ,由於,提供了不少更方便使用的包裝器。 Spring Cloud支持Feign(一個REST客戶端)以及Spring本身的RestTemplate來使用Eureka服務的邏輯標識符,而不是經過物理URL。 能夠爲物理服務簡單的配置一個固定列表集合:<client>.ribbon.listOfServers用逗號分割物理地址或者主機名,<client>指的是客戶端ID。

你也可使用org.springframework.cloud.client.discovery.DiscoveryClient,這個客戶端提供了一套簡單的API來操做客戶端,不須要專門去使用Netflix。例如:

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

4.1.9 Why is it so Slow to Register a Service? 註冊一個服務爲啥慢如狗

做爲一個實例涉及到一個心跳機制去註冊(經過serviceUrl),默認持續30秒。直到實例自身,服務端,客戶端各自元數據本地緩存同步完成後,服務纔可用(至少須要3次心跳週期)。 能夠經過eureka.instance.leaseRenewalIntervalInSeconds修改這個週期,改善客戶端連接到服務的速度。不過,考慮到短時間的波動以及服務續期等狀況,在生產環境最好仍是用默認設定。

相關文章
相關標籤/搜索