[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修改这个周期,改善客户端连接到服务的速度。不过,考虑到短时间的波动以及服务续期等状况,在生产环境最好仍是用默认设定。

相关文章
相关标签/搜索