在 Java Web 应用程序中同步的位置
Where to syncronize inside a Java WebApp
我的雇主目前给了我一个让我绞尽脑汁同步的项目。
我先说说我现在的情况:
- 我被要求创建一个 pdf-report/quotation-tool 来获取数据(来自 csv 文件;因为数据所在的实际数据库正在被旧的 IBM 软件使用,它们出于(未知)原因不' 不希望直接访问该数据库(因此,与其将数据复制到其他数据库,他们显然发现在服务器上创建一个包含大量 CSV 文件的文件夹非常好。)),这个软件是将数据加载到应用程序中,查询数据,在需要的地方进行转换,进行计算,然后 return 将 pdf 文件提供给最终用户。
这里的问题是获取、查询和计算需要相当多的时间,另一个问题是:他们希望它成为一个 WebApp,因为业务团队不想安装任何新软件,他们现在主要是在网上做所有事情(自大流行开始以来),它是一个 WebApp 意味着每个计算都必须由 WebApp 完成并以同样的方式获取数据。
我的问题:是否将单独用户对 servlet 的每次调用都视为单独的 servlet,我应该只同步业务逻辑(获取和使用数据)上的方法吗?或者我应该写一些代码,将自己放在 servlet 的中间,接收一个用户 ID(作为参考),然后 运行 以同步方式处理业务逻辑,然后接收数据和 return正在处理 pdf 文件?
(我希望你明白它的要点...)
如果有帮助,一切都将 运行 在 Apache Tomcat 8 上。构建是 Java 11lts.
抱歉,还没有代码。但是我画了一些图。
对于 java 网络应用程序,通常的模式是组件没有对话状态(意味着特定于特定用户请求的信息)。如果您需要在服务器上为用户保持状态,您可以使用 http 会话。使用 SPA 或 Ajax 应用程序,通常更容易在浏览器中保留大量此类状态。您在服务器上保留的状态越少,随着应用程序的扩展,事情就越容易,您不必将会话固定到服务器(搞乱负载平衡)或跨集群复制大量会话状态。
对于阻塞 i/o 的简单(非反应性)Web 应用程序,每个请求-响应周期都从 tomcat 的池中获取自己的专用线程。该线程将 http 请求传递给 servlet,在与数据库对话时处理业务逻辑和块,然后携带 http 响应。
(响应式 Web 应用程序的构建将变得更加复杂,您将需要一个非阻塞数据库驱动程序,并且您对数据库的选择会更少,所以我会避开这些,至少对于您的第一个 Web 应用程序.)
tomcat 使用的线程池必须保护自己免受并发访问,但这不会影响您的代码。同样,有 3rd 方中间层缓存库必须处理并发性,但您可以避免直接处理它。您的所有逻辑都限制在一个线程中,因此它不会干扰其他线程完成的处理,除非存在共享的可变数据结构。这些数据结构将是应用程序的一部分,其中同步可能是几种可能的解决方案之一。
同步或其他锁定方案对于应用程序的一个实例是本地的。如果你想支持这个应用程序的多个实例,那么你需要知道每个实例都将与其他实例分开锁定。所以对于某些事情,最好在数据库中进行锁定,因为它在 webapp 实例之间共享。
如果您可以使用数据库来存储您的数据,以便您可以依赖数据库进行缓存和索引,那么您的应用程序似乎应该能够避免进行大量锁定。
如果您想要示例,可以使用 https://spring.io/guides 中的 spring 构建网络应用程序的许多小示例。这些是 spring 自托管的引导应用程序,因此您可以快速将它们组合在一起并立即 运行 它们。
使用数据库可能不是最好的方法,因为数据库需要由 DBA 照管。我的建议是将两个项目计划放在一起,一个使用数据库,一个使用平面文件。平面文件必须允许解决诸如处理缓存、索引数据、从遗留数据库复制数据以及没有从 sql 查询生成 pdf 的标准工具等问题。使用数据库的替代计划应该有更少的基础设施整理和更短的时间,直到您可以开始制作报告。
我的雇主目前给了我一个让我绞尽脑汁同步的项目。
我先说说我现在的情况:
- 我被要求创建一个 pdf-report/quotation-tool 来获取数据(来自 csv 文件;因为数据所在的实际数据库正在被旧的 IBM 软件使用,它们出于(未知)原因不' 不希望直接访问该数据库(因此,与其将数据复制到其他数据库,他们显然发现在服务器上创建一个包含大量 CSV 文件的文件夹非常好。)),这个软件是将数据加载到应用程序中,查询数据,在需要的地方进行转换,进行计算,然后 return 将 pdf 文件提供给最终用户。
这里的问题是获取、查询和计算需要相当多的时间,另一个问题是:他们希望它成为一个 WebApp,因为业务团队不想安装任何新软件,他们现在主要是在网上做所有事情(自大流行开始以来),它是一个 WebApp 意味着每个计算都必须由 WebApp 完成并以同样的方式获取数据。
我的问题:是否将单独用户对 servlet 的每次调用都视为单独的 servlet,我应该只同步业务逻辑(获取和使用数据)上的方法吗?或者我应该写一些代码,将自己放在 servlet 的中间,接收一个用户 ID(作为参考),然后 运行 以同步方式处理业务逻辑,然后接收数据和 return正在处理 pdf 文件?
(我希望你明白它的要点...) 如果有帮助,一切都将 运行 在 Apache Tomcat 8 上。构建是 Java 11lts.
抱歉,还没有代码。但是我画了一些图。
对于 java 网络应用程序,通常的模式是组件没有对话状态(意味着特定于特定用户请求的信息)。如果您需要在服务器上为用户保持状态,您可以使用 http 会话。使用 SPA 或 Ajax 应用程序,通常更容易在浏览器中保留大量此类状态。您在服务器上保留的状态越少,随着应用程序的扩展,事情就越容易,您不必将会话固定到服务器(搞乱负载平衡)或跨集群复制大量会话状态。
对于阻塞 i/o 的简单(非反应性)Web 应用程序,每个请求-响应周期都从 tomcat 的池中获取自己的专用线程。该线程将 http 请求传递给 servlet,在与数据库对话时处理业务逻辑和块,然后携带 http 响应。
(响应式 Web 应用程序的构建将变得更加复杂,您将需要一个非阻塞数据库驱动程序,并且您对数据库的选择会更少,所以我会避开这些,至少对于您的第一个 Web 应用程序.)
tomcat 使用的线程池必须保护自己免受并发访问,但这不会影响您的代码。同样,有 3rd 方中间层缓存库必须处理并发性,但您可以避免直接处理它。您的所有逻辑都限制在一个线程中,因此它不会干扰其他线程完成的处理,除非存在共享的可变数据结构。这些数据结构将是应用程序的一部分,其中同步可能是几种可能的解决方案之一。
同步或其他锁定方案对于应用程序的一个实例是本地的。如果你想支持这个应用程序的多个实例,那么你需要知道每个实例都将与其他实例分开锁定。所以对于某些事情,最好在数据库中进行锁定,因为它在 webapp 实例之间共享。
如果您可以使用数据库来存储您的数据,以便您可以依赖数据库进行缓存和索引,那么您的应用程序似乎应该能够避免进行大量锁定。
如果您想要示例,可以使用 https://spring.io/guides 中的 spring 构建网络应用程序的许多小示例。这些是 spring 自托管的引导应用程序,因此您可以快速将它们组合在一起并立即 运行 它们。
使用数据库可能不是最好的方法,因为数据库需要由 DBA 照管。我的建议是将两个项目计划放在一起,一个使用数据库,一个使用平面文件。平面文件必须允许解决诸如处理缓存、索引数据、从遗留数据库复制数据以及没有从 sql 查询生成 pdf 的标准工具等问题。使用数据库的替代计划应该有更少的基础设施整理和更短的时间,直到您可以开始制作报告。