我目前正在维护一个Java应用程序,该应用程序最初设计为只作为单个实例工作(而不是在集群/集群中)。现在,客户端正在计划升级他们的基础设施,他们的计划之一就是将我们的web应用程序放在一个负载均衡器后面。
我已经指出了几个严重的设计问题:
我需要对我提出的解决方案的意见如下。
另外,在设计水平可伸缩的web应用程序从无到有时,我还应该考虑哪些其他的问题呢?
发布于 2013-11-23 01:58:20
用户可以上传文件,我们的应用程序将这些文件存储在本地文件系统中。 I可以通过将所有文件存储在外部/共享存储区(SAN等)来解决项目1。
将常见的静态资源存储在外部系统上,而外部系统对所有人都是可访问的,这无疑是解决用户上传文件的问题的一种方法,然后您必须保存这些文件。这减少了许多问题,并且完全绕过了试图对本地文件系统进行同步的丑陋问题(不要沿着这条路线走下去,它只会导致疯狂)。
有些计划作业在并发执行时可能会导致问题(即生成文件)。使用项目2,我可以在数据库中创建一个锁定机制,以便当计划作业运行时,web应用程序将首先检查表,而只有第一个更新的应用程序将运行该作业。
处理编写“静态”数据的计划作业时,您会遇到其他一些难看的情况。
首先要考虑的是它们产生了什么?如果它们正在生成其他小型文件,为什么不将生成的数据存储在数据库中呢?这也在一定程度上解决了“锁定”问题(因为它将其卸载到数据库中)。然后,应用程序需要从数据库中读取数据,而不是从文件系统读取数据。
当您考虑使用大型oracle数据库执行此操作时,您可能还会考虑使用更轻的nosql数据库。使用文件系统进行锁定还有其他问题,这使得它变得不那么理想。使用多个不同的系统(数据库和文件系统)并不具有完全相同的竞争条件(它们是需要考虑的其他竞争条件),但这也意味着这两个系统需要保持适当的同步。当应用程序不适当地终止时,移除数据库锁的乐趣。
将生成的内容存储在数据库中,您应该会做得很好。它能使一些事情变得容易得多。考虑一些事情,比如带有时间戳的记录,然后选择最近完成的时间戳。
这里还有其他需要考虑的事情,例如在应用程序服务器上有一个服务,该服务将编写来自特定客户端的文件(因此,您的计划作业将其推送到将其写入公共文件系统的应用程序服务器),或者有一些消息传递系统通知应用程序服务器在某个特定位置的新内容,这将触发应用程序将数据拖到本地文件系统。
对于被推送到内容区域的单个更新,有很多不同的方法来处理这个问题。这可能是一个全新问题本身的主题,这取决于问题的具体情况和系统的制约因素。
会话变量在大多数模块中被大量使用。实际上,我仍然不确定第3项是否会引起问题。如果用户登录到我们的应用程序,负载均衡器将他引导到服务器1,那么负载均衡器是否有可能在下一次单击链接时将其指向Server 2?我还不知道负载均衡器是如何在这个级别工作的。
您正在寻找的关键概念是“粘性会话”。它属于“负载均衡器持续承受”的范畴。
在这种情况下,负载均衡器还知道所创建的会话,当一个系统的会话请求通过时,它将始终将它“卡在”生成它的应用服务器上。
这不是没有它自己的一组问题(一个系统崩溃,会话切换到另一个系统(您有故障转移,对吗?)然后回来,但是现在所有的负载都卡在了另一台服务器上)。
请注意,这种支持的确切性质取决于所使用的负载平衡器。有些有自己的cookie,有些使用JSESSIONID等,另一些使用ip (如果您在那里有某种防火墙/代理,那么看起来所有的请求都来自同一个ip)。
您还可能希望查看会话的外部缓存,以便它们在两台机器之间共享,而不是在它们之间进行负载平衡。有些框架有此功能,或者您可以使用其他缓存解决方案来沿着这条路线走下去。同样,如果有更多关于环境和约束的信息,这可能是一个新问题的主题,因为这也变得相当长。
https://softwareengineering.stackexchange.com/questions/219286
复制相似问题