扩展 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 社区所有即将举行的活动。

查看所有