扩展 Spring Cloud

工程 | Ramnivas Laddad | 2014年8月5日 | ...

Spring Cloud 最有趣的功能之一是它的可扩展性。您可以扩展它来支持其他云,增强已经支持的云,支持新服务,新的服务连接器——所有这些都无需修改 Spring Cloud 代码本身。在这篇博客中,我们将探讨这一功能。如果您还没有阅读本系列的第一篇第二篇博客以获取足够的背景知识,请务必先阅读。

可扩展性的三个维度

Spring Cloud 提供了沿三个正交方向的可扩展性。您可以在其中一个方向上进行扩展,而正交性确保您可以继续从其他方向获益。

  1. 云平台:虽然 Spring Cloud 支持 Cloud Foundry、Heroku 和一个本地配置云(用于在类似云的环境中进行本地测试),但您的选择不限于这些。您可以添加自己的云平台,并利用 Spring Cloud 的其余功能,例如 Spring Java Config。

  2. 云服务:云平台提供各种服务,从关系数据库到消息传递。每个云平台提供的服务差异很大,即使是同一平台的多个安装也是如此。对于 PaaS 产品(如 Cloud Foundry)来说尤其如此,Cloud Foundry 的私有实例往往具有每个安装特定的服务。Spring Cloud 提供了一种简单的方法来扩展其核心产品之外的服务。就像云平台的可扩展性一样,您无需更改 Spring Cloud 代码即可扩展到新服务,并且您可以继续利用其他部分。

  3. 框架:Spring Cloud 当前通过 spring-service-connector 模块支持 Spring 框架。然而,除了该模块之外,Spring Cloud 中的任何部分都不依赖于 Spring。因此,您应该能够使用任何基于 JVM 框架的其他部分,或者通过添加新模块来为某个框架进行扩展。

上一篇博客中,我们探讨了如何使用 CloudFactoryCloud 以编程方式使用 Spring Cloud。涉及可扩展性时,您不会使用这两者中的任何一个;相反,您将实现核心模块中的其他类型。让我们来看看它们。

云平台可扩展性

要将 Spring Cloud 扩展到新的云平台,您需要熟悉的主要类型是 CloudConnector,它是一个简单的三方法接口

public interface CloudConnector {
	boolean isInMatchingCloud();
	ApplicationInstanceInfo getApplicationInstanceInfo();
	List<ServiceInfo> getServiceInfos();
}

isInMatchingCloud() 方法应检查其环境以确定它是否在正确的环境中运行。例如,Cloud Foundry 连接器检查 VCAP_APPLICATION 环境变量是否存在,而 Heroku 连接器则查找 DYNO 环境变量是否存在。getApplicationInstanceInfo() 方法返回有关当前应用程序实例的信息(应用程序名称、主机、端口和应用程序属性)。最有趣的方法 getServiceInfos() 返回一个列表,其中每个元素包含足够的信息,以便应用程序知道如何连接到每个服务。每个 ServiceInfo 对象中包含的确切信息取决于各个实现(ServiceInfo 本身仅定义一个方法:getId())。

创建 CloudConnector 的实现后,您需要让 Spring Cloud 了解它。对于所有扩展点,Spring Cloud 使用基于 ServiceLoader 的统一机制。应用于 Spring Cloud 的平台可扩展性时,它归结为包含一个名为 /META-INF/services/org.springframework.cloud.CloudConnector 的文件,其中包含一个带有实现类完全限定名称的条目。通常,您会将此文件与您的实现和支持类捆绑在一起。然后,应用程序只需在类路径中包含此 jar 即可。

服务可扩展性

ServiceInfoCreator 接口提供了一个扩展点来处理新服务。

public interface ServiceInfoCreator<SI extends ServiceInfo, SD> {
    public boolean accept(SD serviceData);
    public SI createServiceInfo(SD serviceData);
}

泛型参数 SI 定义了它将创建的 ServiceInfo 类型,而 SD 参数定义了它可以处理的原始服务数据类型。原始服务数据类型取决于云平台。例如,在 Cloud Foundry 中,它将是基于 VCAP_SERVICES 环境变量的 Map,而在 Heroku 中,它将是包含特定服务环境变量及其值的对。由于原始数据类型取决于平台,因此 ServiceInfoCreator 的实现也取决于平台。accept() 方法检查服务数据并确定它是否可以处理。例如,它可以查看 URL 方案并确定它是否可以消费该服务数据。如果可以,createServiceInfo() 必须返回一个 ServiceInfo 对象。如果这是一个全新的服务,您可能还需要为其实现 ServiceInfo,否则您可以使用现有的服务信息对象之一。

实现 ServiceInfoCreator 后,您必须让 Spring Cloud 了解它。这遵循了与之前讨论的云平台可扩展性相同的思路。在这种情况下,您使用的文件名称取决于 CloudConnector。对于 Cloud Foundry,它是 /META-INF/services/org.springframework.cloud.cloudfoundry.CloudFoundryServiceInfoCreator(理论上,CloudConnector 实现可以决定使用另一种扩展机制,但 Spring Cloud 不推荐这样做)。

正如上一篇博客中讨论的,云应用程序开发人员可能会决定直接使用 ServiceInfo 对象。因此,如果您只实现了一个 ServiceInfoCreator,您已经提供了一些好处。但是,对于许多专注于开发应用程序的开发人员来说,使用原始 ServiceInfo 对象可能不受欢迎,因此您还需要实现下一个扩展点。

框架可扩展性

最后一个扩展点是 ServiceConnectorCreator。它的工作是将 ServiceInfo 转换为适合应用程序使用的框架的服务连接器。例如,它可以将 MysqlServiceInfo 转换为 DataSource 对象。Spring Cloud 开箱即用支持 DataSource 以及一些 Spring DataSpring AMQP 类型的连接器。如果您希望将 Spring Cloud 扩展到其他框架,或者希望支持 Spring Cloud 尚未直接支持的其他 Spring Data 类型(如 Neo4J、Elasticsearch、Cassandra)或 Spring 兼容类型(如 S3),这就是您需要的扩展点。

public interface ServiceConnectorCreator<SC, SI extends ServiceInfo> {
    SC create(SI serviceInfo, ServiceConnectorConfig serviceConnectorConfig);
    ...
}

还有几个方法;但是,您通常会扩展 AbstractServiceConnectorCreator 来处理这些方法的实现。

ServiceConnectorCreatorSC 泛型参数绑定到它将创建的连接器类型,例如 DataSource,而 SI 参数表示它可以处理的 ServiceInfo 类型。

create() 方法提供一个 ServiceInfo 对象和一个配置对象,该配置对象携带特定服务的信息,例如连接池参数。它需要使用这些参数来创建适当的连接器。

实现准备就绪后,只需将其放入一个名为 /META-INF/services/org.springframework.cloud.service.ServiceConnectorCreator 的文件中即可。Spring Cloud 将使用前面描述的 Service Loader 机制。

总结

正如您所见,Spring Cloud 在云平台、服务和框架维度上提供了实质性的可扩展性。下次遇到这些新类型时,您应该能够扩展 Spring Cloud 以便与之协作。如果您将扩展开源,请告知我们,以便我们可以展示它以使其他人受益。如果它是足够常见的扩展,请考虑提交拉取请求。

获取 Spring 邮件列表

订阅 Spring 邮件列表,保持联系

订阅

领先一步

VMware 提供培训和认证,助您加速进步。

了解更多

获得支持

Tanzu Spring 提供对 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件,一个简单的订阅即可拥有。

了解更多

即将到来的活动

查看 Spring 社区所有即将到来的活动。

查看全部