部署 Web 服务的最佳做法是什么?

What is a good practice to deploy webservices?

单独部署 Web 服务是一种好的做法,还是它们应该成为 Web 应用程序的一部分?例如,我正在开发一个 spring 基于 rest 的 Web 服务。比方说,这项服务的功能是获取用户数据。

查询此 Web 服务的每个 Web 应用程序都有不同模式的用户数据。所以,现在 web 服务需要知道是谁在调用它——是 Appilcation A 还是 Application B?如果它是 AppA,那么它应该从模式 A 获取数据,如果它是 AppB,那么它应该从另一个模式获取数据。请注意,AppA 和 AppB 只是打包到两个不同战争中的相同代码,它们应该查询的模式是从属性文件中提供的。

在这种情况下,将 web 服务与 webapp 代码打包并部署在不同的上下文中是否有意义,因此它在不同的上下文中成为重复服务 运行。或者,它是否应该单独部署,并且 AppA 和 AppB 应该以某种方式向该 Web 服务标识自己?

我的输入:

1) 为同一代码构建 2 个不同的战争有什么具体原因吗?仅仅是因为您每个人都有两个不同的数据源吗? 为什么不能在每个请求中使用某种参数化机制部署单个应用程序来识别从哪个模式获取数据?

2) 为什么首先需要 Web 服务?为什么应用程序不直接挂接到它需要的数据库。

3)底层数据库是事务性DB还是一些历史数据?如何将两个模式合并为 one-time 努力 使用某种虚拟化视图,该视图根据输入参数从 2 个模式中挑选数据。

***** 在 Jay 的输入后编辑:

我的建议是将 Web 服务与 2 个 Web 应用程序分开部署,因为它提供单一位置来管理长 运行 中的代码。我有以下额外建议:

  1. 在 SOAP XML 架构中定义您自己的 headers,它可以为您提供 appContext(应用程序调用)和 userContext(用户)。保持长远眼光,在这方面好好考虑一下。

  2. 保持 SOAP request-response 无状态,这将为您提供可扩展性。不要在服务器端维护 SOAP 请求的任何状态。

  3. 我过去使用过数据虚拟化解决方案(CISCO Composite)..它提供的好处:如果有两个(或更多)数据源包含相似类型的数据(实体),它可以虚拟地加入、清理和合并它,并将其公开为基于 REST/SOAP 的 Web 服务。也尝试评估此选项。 如果将来您有其他消费者使用普通 SQL/JDBC 调用访问您的信息,他们将能够做到这一点,它还能提供什么帮助...此外,数据虚拟化解决方案支持许多其他消费者接口,如 Hadoop、OData 等...再次取决于项目的预算和其他限制...我不确定是否有可用的有效开源数据虚拟化解决方案?

我不知道您的业务需求是维护用户数据的不同模式并使用 web 服务。

但是我建议您在应用程序中配置多个数据源并根据您的要求切换到数据源,而不是使用相同的代码维护多个战争。

This link may help you to configure multiple DS

如果您遵循上述逻辑,您最终可能会得到单一的可部署上下文。

仍然想坚持将多个战争作为 web 服务,我建议您看一下 SpringBoot 简单、容器较少的可部署性和可扩展性。

见仁见智,两种选择都可以。您应该考虑服务的使用、缩放问题等。

您可以将 Microservices 视为一个想法,但从您的角度来看它必须有意义。

关于这两个不同的应用程序:如果差异仅在于配置,请尝试将其外部化 (23. Externalized Configuration)。这样您就可以将一个工件部署两次。

在这种情况下,只使用一个 Web 服务是一种很好的做法,这样可以提高系统的可维护性,因为您不会有两次相同的代码。如果您将来有其他新的类似应用程序,则不必实施新服务。

方法一:-(首选)

您应该有一个 Web 应用程序,其中包含应用程序 UI 和 Repo/data 交互的完整代码。

根据请求类型动态切换数据源。你可以看看 Spring Dynamic datasource routing here

方法二:-

如果您的 UI 具有由不同团队管理的完全不同类型的交互,则在同一位置维护单独的 UI 组件和后端 Web 服务是有意义的。

再次根据请求类型,您可以动态路由数据源。

希望对您有所帮助:)

就个人而言,根据我的经验,将它们分开要好得多,这通常取决于您的主要项目的大小和重要性。

但是,即使一开始你的项目不是那么大,而且只有一个人在做,但随着它的不断发展,如果你的主要项目所做的所有事情都有微服务,它将更容易维护,而不是让许多人在同一代码上处理一个独特项目的多个版本,处理许多小项目不会那么混乱,也更容易发现错误。

此外,如果出现故障,您可以关闭 1 个微服务,而您的主服务仍在不间断地运行,它只会拒绝 1 个服务,而不是在您修复它时关闭所有服务。

高可用性在生产中非常重要,将它们分开有助于此。

这真的取决于你想要实现什么。

如果要封装database/schema/table,那么真的应该是每个应用一个服务。这样做的主要优点是如果当前数据库出现问题,您可以稍后交换数据库,它还简化了缓存和失效等。

如果database/schema/table反正不封装,那么单体服务就容易多了,也好很多。每个 web 应用程序只需要识别自己,每个应用程序都会得到他们需要的东西。这可以通过将 query/schema 信息放入 属性 文件,或创建与客户端同名的数据库视图等来实现

如果我们采用这种方法,就会弹出一个问题。为什么要费心拥有这一层呢?难道每个 Web 应用程序都不能直接查询数据库吗?如果答案是肯定的,那么就把整个层完全删除。

考虑到您的情况,我建议您使用一个网络应用程序(一个 "project"),但要注意一些,然后考虑以下两种解决方案之一:

1) 鉴于您正在使用 spring,我假设(希望)您也在使用 maven.. 制定不同的编译目标,并根据生成 war 所调用的目标,使相关的属性文件不同。 这样你就有了一个网络应用程序,并且基于编译(或者更确切地说基于与该特定编译相关的属性文件)你将获得一个与特定环境和模式相关的 war ...你部署一个单独的 war 对于每个 web 服务都有一个干净的分离,虽然根代码是完全相同的,它只是一个应用程序...... [更清洁的解决方案] 2) 使它不仅得到 json 请求而且得到发件人的 https 证书(因此你根据公开的 https 证书识别特定的 "webapp"),并基于证书和请求的来源,您确保来源为 "qualified" 以从模式 X 而不是模式 Y 接收数据。您只部署一个 war,它将根据他自己的判断将逻辑应用于将您的 "user data fetch query" 重新路由到一个数据库或另一个数据库 [我不鼓励这种做法]

当然还有其他方法,不过我觉得这两个是最可行的..

我更喜欢下面的方法,它用于 50K 并发用户。

  1. 通过执行所需的业务用例,确保每个网络服务独立封装UI和Schema。每个 Web 服务都将具有所有三个层 - 该业务服务的模型、视图和控制器。这意味着您的 App-A 是一个 Web 服务,而 App-B 是另一个 Web 服务。
  2. 所有网络服务都将注册和注销主网络服务。主 Web 服务负责将用户请求重定向到适当的 Web 服务,如 App-A 或 App-B。
  3. 您应该有 Master Web 服务集群和个人 Web 服务集群 - App-A & App -B

  4. 在这种方法中,您的模式可以驻留在不同的数据库而不是单个数据库

这种方法的优点:

  1. 每个 Web 服务都可以水平扩展。如果您想增加规模,只需添加额外的 VM 节点。

  2. 如果您在不同位置的不同数据库上有不同的架构,则可以避免 OLTP 查询(联机事务处理查询)中的网络性能瓶颈。

缺点:

  1. 我只看到一个缺点,因为 Master Web Service 就像一个 Facade,它应该了解各个 Web 服务的内部结构。但是,如果您考虑权衡取舍,这并不是它提供的优势的缺点。

我会部署到一个实例。无论。当然,也有可能需要单独部署的情况。根据最佳 "coding" 实践,应该使用一个实例来允许 "right once, use many".

然后...

  • 为每个 AppA、AppB 等定义不同的 XSD。相应地编组。
  • 或者,使用 Groovy 将适当的对象编组为 json 或 xml。

您正在尝试将数据提供程序或 DAO 作为服务来实现。 做到 -

  1. 简单
  2. 可扩展
  3. 易于维护,
  4. 适应性强

您可以简单地拥有一个 web 服务,部署在 Web 应用程序之外并关闭配置。配置本身可以存储为 属性 文件,或来自数据库。客户端的标识符应该在 web 服务请求中传递。

这实际上是一种非常标准的方法,用于在 DB 之外的数据层实现优化,例如缓存(再次由配置驱动)、过期、池化等。

另一种选择,作为共享 jar 包含在 webapp 中,是的,具有代码重用的优点(您也可以通过外部部署的服务获得),但以下缺点超过了该选项。

  • 耦合
  • 采用优化很困难
  • 发布管理(这也取决于您的代码的组织方式)
  • 版本控制。

希望对您有所帮助。