前言

Sprign Cloud connectors 为发现在云平台上运行的基于JVM的应用程序提供的服务和部署信息提供了一个简单的抽象,支持把服务像Spring Beans一样注册和使用。它是一个基于插件的模型,所以相同编译的应用可以部署到本地或者多个云平台,支持通过 Java Service Provider Interfaces(SPI) 自定义服务.

Connectors project 可以开箱即用的使用在Heroku和Cloud Foundry clouds上发现的公共服务,包含了一个 properties-based 连接器可以为开发和测试提供配置。

概念

下面将描述Connectors 的核心概念.

Cloud Connector

一个平台特定的接口,确定平台存在和发现部署在平台上的应用提供的任何服务.

Service Connector

一个表示连接到一个运行服务的对象(如,一个“javax.sql.DataSource”)。

Service Information

基础服务的信息(如主机、端口和凭证)。

Application Information

应用程序和每个运行实例的信息

子模块

这个工程包含了三个主要的子模块.

  • Spring Cloud Connectors Core: 核心库, cloud-agnostic and Spring-agnostic. 如果开发者喜欢手动方式来访问云服务和应用程序的信息,它为开发者提供了一个可编程式的入口,同样为一些常用的服务基础的组件(databases, message queues)提供的基本的服务定义, 为contributing cloud 和 service connectors 提供了一个基于SPI-based 扩展机制.

  • Spring Cloud Spring Service Connector: 一个 Spring 库, 暴露了应用信息,云信息 和 服务发现 做为合适类型的 Spring beans (比如, 一个sql服务会被暴露为带有 可选的 有连接池的 javax.sql.DataSource ).

  • The cloud connectors:

    • Spring Cloud Cloud Foundry Connector: 连接到 Cloud Foundry.

    • Spring Cloud Heroku Connector: 连接到 Heroku.

    • Spring Cloud local-configuration Connector: Properties-based connector 在开发或者测试时可以手动提供配置信息,允许在应用部署的所有阶段支持使用同样配置的Spring Connectors 连接。

入门指南

下面的列子会展示如何添加依赖到你的的构建系统

添加Cloud Connectors

给每个你想发现的云平台添加connector ,也可以添加多个。每个connector自己会确定是否应该活跃在一个特定的环境

使用Maven, 用你想用 artifact 的版本 替换 ${VERSION}

<!-- 在开发环境中使用 Spring cloud Connectors-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-localconfig-connector</artifactId>
    <version>${VERSION}</version>
</dependency>

<!-- 假如你想部署应用到Cloud Foundry -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-cloudfoundry-connector</artifactId>
    <version>${VERSION}</version>
</dependency>

<!--假如你想部署应用到 Heroku -->
<!-- If you intend to deploy the app to Heroku -->
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-heroku-connector</artifactId>
  <version>${VERSION}</version>
</dependency>

使用Gradle 用你想用artifact 的版本 替换 ${VERSION}:

dependencies {

    // To use Spring Cloud Connectors for development
    compile 'org.springframework.cloud:spring-cloud-localconfig-connector:${VERSION}'

    // If you intend to deploy the app to Cloud Foundry
    compile 'org.springframework.cloud:spring-cloud-cloudfoundry-connector:${VERSION}'

    // If you intend to deploy the app to Heroku
    compile 'org.springframework.cloud:spring-cloud-heroku-connector:${VERSION}'

}

Spring 应用

如果你正在写一个spring 应用,添加 Spring Service Connector 到你的 cloud connector 依赖中.

使用 Maven:

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-spring-service-connector</artifactId>
  <version>${VERSION}</version>
</dependency>

使用 Gradle:

dependencies {

    compile 'org.springframework.cloud:spring-cloud-spring-service-connector:${VERSION}'

}

然后按照 Spring configuration 上的文档说明 Spring Service Connector using Java configuration 或者 <cloud> namespace

不是Spring 应用

‘spring-cloud-core’ 依赖包含在每个cloud connector 中,所以你可以简单的添加connector 到你想要的平台,按照instructions on using the Spring Cloud Connectors API.

Spring Cloud Connectors Core

这个核心库提供了编程式的方式访问应用和服务的信息,不依赖Spring,所以可以应用到no-Spring 的应用程序。

**这个库需要java 6 或者更新的版本,是 cloud-agnostic;使用 Java SPI ,它支持插件式的cloud和服务连接器,支持Cloud Foundry和Heroku 开箱即用,此外还有locally-provided配置用来开发和测试。

连接到云

[注意]

如果你在Spring应用程序中使用Spring Cloud Connectors,可以考虑使用automatically injecting Spring beans

  • 添加 cloud connectors 到classpath as described in the main documentation.

  • 创建一个 CloudFactory 实例.创建一个CloudFactory有点消耗资源,我们推荐使用 singleton instance,如果你使用一个依赖注入的框架如Spring, 为CloudFactory创建一个 bean.

    CloudFactory cloudFactory = new CloudFactory();
  • 获得一个当前环境下正在运行的应用程序的Cloud对象.

    Cloud cloud = cloudFactory.getCloud();

    注意 你必须有一个合适的CloudConnector在你的开发环境的classpath中,举列,假如你正在部署应用到 Cloud Foundry,你必须添加 Cloud Foundry Connector 到 classpath,如果找不到合适的CloudConnector,getCloud()方法会抛出一个CloudException

  • 使用 'Cloud' 实例访问应用和服务信息和创建service connectors.

    // ServiceInfo 拥有所有必须的信息用来连接基本的服务
    List<ServiceInfo> serviceInfos = cloud.getServiceInfos();
    // 获取那个合适的`ServiceInfo`定义用来连接一个特定的服务类型
    List<ServiceInfo> databaseInfos = cloud.getServiceInfos(DataSource.class);
    // 可选的,可以让Spring Cloud Connectors 帮你你创建一个service
    String serviceId = "inventory-db";
    DataSource ds = cloud.getServiceConnector(serviceId, DataSource.class,
                                                null /* default config */);

Spring Service Connector

Spring Service Connectors 用来为Spring应用创建连接对象,他支持 Java 或者 Xml 配置,目前支持关系型数据库如Mysql 和 PostgreSQL通过javax.sql.DataSource,SMTP通过org.springframework.mail.MailSender,RabbitMQ 通过 Spring AMQP, MongoDB 和 Redis 通过 Spring Data projects. 也支持连接到一般的services (如 private)

关于service connector的详细信息 可以在Spring Cloud Spring Service Connector查看。

Cloud Foundry Connector

Cloud Foudry Connector 发现在Cloud Foundry 中运行的应用程序提供的服务。它按照Cloud Foudry 的标准格式消费提供服务的的信息,它是provider-agnostic; 一般用作系统监视器,DB2, MongoDB, MySQL, Oracle, PostgreSQL, RabbitMQ, Redis, SMTP, and SQL Server 等服务.

关于cloud connectors的详细信息 可以在Spring Cloud Cloud Foundry Connector查看。

Heroku Connector

Heroku Connector 可以发现在Heroku 中运行的应用程序提供的服务。当前可以发现PostgreSQL(Heroku 提供),MySQL (ClearDB 提供),Redis (Redis To Go, Redis Cloud, RedisGreen, openredis, 和 Heroku提供), MongoDB ( MongoLab, MongoHQ, 和MongoSoup提供), 和 RabbitMQ (CloudAMQP 提供),能为这些服务提供额外的扩展。

关于这个cloud connectors的详细信息 可以在Spring Cloud Heroku Connector查看。

local-configuration Connector

这个可以用来配置本地的Spring Cloud Connectors 服务用来开发和测试. 当前只实现了从 Java properties 读取.

快速入门

由于Service URIs 中包含了密码并且不能直接写在代码中,所以这个connector不会尝试去classpath以外的地方读取service的定义.你可以提供一个系统参数来定义服务.

java -Dspring.cloud.database='mysql://user:pass@host:1234/dbname' -jar my-app.jar

你可以通过一个配置文件,也可以通过设置spring.cloud.propertiesFile这个系统属性来定义服务:

java -Dspring.cloud.propertiesFile=/path/to/spring-cloud.properties -jar my-app.jar

或者提供启动的配置文件 spring-cloud-bootstrap.properties 在classpath 中,这个文件的属性必须命名为 spring.cloud.propertiesFile,它的值会被替换成系统属性.

spring.cloud.propertiesFile: ${user.home}/.config/myApp/spring-cloud.properties

系统属性,或者配置属性文件,应该包含一个应用id,和需要的服务 按照下文中的格式。

spring.cloud.appId:    myApp
; spring.cloud.{id}:   URI
spring.cloud.database: mysql://user:pass@host:1234/dbname

服务的类型是由URI scheme所决定的.如果这个connector (在系统参数或者配置文件中)找到一个名字为spring.cloud.appId的配置这个服务会被激活.

属性来源

这个connector 通常会先去系统属性中读取spring.cloud.propertiesFile.如果系统属性不可读(security manager 拒绝 checkPropertiesAccess), 它为空. 如果spring.cloud.propertiesFile系统参数被找到,这个文件会被加载成参数列表.

提供一个启动参数文件

为了避免手动配置运行时需要的信息或用特定路径下的参数配置文件, connector可以读取一个classpath 外的临时文件,这个文件名必须为spring-cloud-bootstrap.properties 并且位于根classpath .从安全角度上讲,connector 不会尝试读取任何文件之外的 service URIs . 如果connector 找不到这个文件,它会读取spring.cloud.propertiesFile这个属性 substitute the pattern ${system.property} 从系统属性中.最有用的选项通常是${user.home}.

一个系统属性中的配置文件会覆盖classpath中的启动文件.

属性优先

为了提供最灵活的配置,connector 会用spring.cloud.propertiesFile 中定义的属性(包括应用ID和服务定义) 覆盖运行时的系统属性. 如果覆盖了一个service ID,connector 会记录一个 WARN.

激活 Connector

Spring Cloud Connectors Core 期望正确的cloud connector去匹配运行环境. connector通过指定在配置文件或系统属性的 “local cloud”参数来命名 spring.cloud.appId. 这个参数会被 ApplicationInstanceInfo使用.

服务定义

如果这个connector 处于激活状态, 它会遍历所有和spring.cloud.{serviceId} 匹配的可用参数. 每个值可以理解为一个服务的URI, 并且这个服务的类型通过scheme来定义.所有标准的UriBasedServiceInfo 都被支持.

实例 ID

Connector 创建一个UUID 作为实例ID,因为Java没有提供一个跨平台的机制来获得hostnames 和 PIDs.

扩展 Spring Cloud Connectors

除了内置的服务和云支持包含Spring Service Connector, Spring Cloud Connectors 可以扩展用来支持另外的云平台,云服务,或应用框架. 详细信息在下面描述.

可扩展性概述

说起 Including Cloud Connectors 部分,你的应用可以包含cloud connectors来使用多种云平台的. Spring Cloud Connectors Core 激活CloudConnector 平台中正在运行的应用. That cloud connector的 ServiceInfoCreator 类为应用服务创建 ServiceInfo 对象, ServiceConnectorCreator 类使用 ServiceInfo 对象创建服务连接对象可以在你的应用中使用.

spring cloud connectors design.png

你可以通过下面的三种方式来扩展Spring Cloud Connectors:

  1. 云平台支持. 开箱即用, Spring Cloud Connectors 对 Cloud Foundry 和 Heroku 平台提供了支持. 你可以扩展 Spring Cloud Connectors来支持其他的云平台和提供者.

    Spring Cloud Connectors 使用 CloudConnector 接口 来提供云平台支持.为一个特定云平台使用的CloudConnector实现必须能够检测应用是否是运行在那个特定平台,并能获取这个应用的信息和这个应用提供的服务信息.

  2. Cloud service support. 你可以扩展Spring Cloud Connectors 来支持额外的服务, 包含这个服务在你特定的环境或应用中.

    Spring Cloud Connectors 使用两个接口来提供 cloud service 支持:

    • 一个 ServiceInfo models 包含了用来连接服务的信息. 在database服务的的情况, 这个 ServiceInfo 的实现可能包括了database的信息如host,port,database name, username, and password; 在 web service下 , 它包括了 URL and API key.

    • 一个 ServiceInfoCreator 通过基于cloud conntecor收集到的service 信息创建 ServiceInfo 对象. 一个 ServiceInfoCreator 实现于特定的云平台.

  3. Application framework support. Spring Cloud Spring Service Connector 用于创建 Spring Data 类型的 service connectors. 你可以通过扩展使用其他框架来提供服务连接对象.

    Spring Cloud Connectors 使用 ServiceConnectorCreator 接口来提供框架支持. 一个 ServiceConnectorCreatorServiceInfo 对象提供的服务连接信息场景 服务 connectors.

添加云平台支持

允许Spring Cloud Connectors 发现一个新的云平台,并给这个云平台添加一个cloud connector。

一个cloud connector 确定应用是否运行在这个特定的云,识别应用的信息(比如运行实例的名称和实例的ID), and maps bound services (比如 URIs 暴露到环境变量) 作为 ServiceInfo 对象.

去这里 Cloud Foundry Connector and Heroku Connector 看示例。

Spring Cloud Connectors 使用 Java SPI 来发现可用的connectors。

你的connector类必需实现 CloudConnector 接口,包括以下三个方法:

  • boolean isInMatchingCloud(): 检测connector是否在它所提供支持的cloud中

    Spring Cloud Connectors Core 在应用的每一个cloud connector中调用 isInMatchingCloud() 方法, 并激活第一个返回 True 的 connector .

  • ApplicationInstanceInfo getApplicationInstanceInfo(): 返回运行应用实例的相关信息。

    ApplicationInstanceInfo 必需提供实例id (String) 和应用(String). 其他的相关属性可以按需添加到一个 Map 中,并通过 getProperties() 返回。

  • List<ServiceInfo> getServiceInfos(): 为绑定到应用上的每一个服务返回一个 ServiceInfo 对象。

    如果没有服务绑定在应用上的话,getServiceInfos() 可以返回一个空的 List

新cloud connectors 应该在 META-INF/services/org.springframework.cloud.CloudConnector 所提供的配置文件中列出完整类名。

Adding Service Support

为了让Spring Cloud Connectors发现新类型的服务,需要创建一个包含必要的链接信息的http://docs.spring.io/autorepo/docs/spring-cloud/current/api/index.html?org/springframework/cloud/service/ServiceInfo.html[ServiceInfo]类。如果你的服务可以通过URI来指定,请扩展http://docs.spring.io/autorepo/docs/spring-cloud/current/api/org/springframework/cloud/service/UriBasedServiceInfo.html[UriBasedServiceInfo],并在super的构造器中提供URI scheme. 下面这个类提供了HelloWorldService服务的相关信息,并可以通过 helloworld://username:password@host:port/Bonjour来访问。

public class HelloWorldServiceInfo extends UriBasedServiceInfo {
public static final String URI_SCHEME = "helloworld";

// Needed to support structured service definitions such as Cloud Foundry's
public HelloWorldServiceInfo(String id, String host, int port, String username, String password, String greeting) {
super(id, URI_SCHEME, host, port, username, password, greeting);
}

// Needed to support URI-based service definitions such as Heroku's
public HelloWorldServiceInfo(String id, String uri) {
super(id, uri);
}
}

在创建了ServiceInfo类之后,你需要为每一个你想要支持的cloud platform创建一个http://docs.spring.io/autorepo/docs/spring-cloud/current/api/index.html?org/springframework/cloud/ServiceInfoCreator.html[ServiceInfoCreator]。如果你向已经被Spring Cloud Connectors支持的cloud platform添加服务,你最好是扩展对应的creator基类。

Cloud Foundry

Extend CloudFoundryServiceInfoCreator.

Heroku

Extend HerokuServiceInfoCreator.

local-configuration

Extend LocalConfigServiceInfoCreator.

一个简单的ServiceInfoCreator可以只是实例化一个新ServiceInfo的方法。

@Override
public HelloWorldServiceInfo createServiceInfo(String id, String uri) {
return new HelloWorldServiceInfo(id, uri);
}

在相应provider-configuration文件内为cloud中ServiceInfoCreator的基类注册ServiceInfoCreator

Cloud Foundry

为你的creator添加完整的类名到 META-INF/services/org.springframework.cloud.cloudfoundry.CloudFoundryServiceInfoCreator.

Heroku

为你的creator添加完整的类名到META-INF/services/org.springframework.cloud.heroku.HerokuServiceInfoCreator.

local-configuration

为你的creator添加完整的类名到META-INF/services/org.springframework.cloud.localconfig.LocalConfigServiceInfoCreator.

附加 Framework 支持

允许Spring Cloud Connectors 提供一个框架特定服务对象来支持云服务, 并为这个框架添加一个 service connector.

一个service connector 使用一个通过 Cloud connector 发现的服务 ServiceInfo 对象,并转换成适当的服务对象 (比如 一个 DataSource 在服务定义的情况表示一个 SQL database).

服务 Connectors 能紧密的绑定到framework创建的服务对象,举个例,一些 connectors 在 Spring Service Connector Spring Data 定义的创建的工厂,用来使用和构建Spring Data templates.

你的connector类必须实现 ServiceConnectorCreator 接口, 它有三个方法:

  • SC create(): 通过给定的ServiceInfo和配置信息 创建一个服务连接对象。

  • Class<SC> getServiceConnectorType():返回的连接对象的类型将被创建。

  • Class<?> getServiceInfoType():返回 ServiceInfo 的类型将被采用。 完整的connector类名在META-INF/services/org.springframework.cloud.service.ServiceConnectorCreator provider-configuration 文件中。