扩展 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. 云服务:云平台提供各种服务,从关系数据库到消息传递。每个云平台提供的服务差异很大,即使是同一平台的多个安装也是如此。对于 Cloud Foundry 等 PaaS 产品尤其如此,其中 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 Found 中,它将基于VCAP_SERVICES环境变量的Map,而在 Heroku 中,它将是一对包含特定于服务的环境变量及其值的配对。由于原始数据类型取决于平台,因此ServiceInfoCreator的实现也取决于平台。accept()方法检查服务数据并确定它是否可以处理它。例如,它可以查看 URL 方案并确定它是否可以使用该服务数据。如果可以,createServiceInfo()必须返回一个ServiceInfo对象。如果这是一个全新的服务,您可能还需要为此实现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 社区中所有即将举行的活动。

查看全部