Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/303.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何跨多个JVM节点实现计数器的最简单/最快方法_Java_Tomcat_Jvm - Fatal编程技术网

Java 如何跨多个JVM节点实现计数器的最简单/最快方法

Java 如何跨多个JVM节点实现计数器的最简单/最快方法,java,tomcat,jvm,Java,Tomcat,Jvm,考虑一下这个问题: 我有n个Tomcat节点,其中web应用程序提供一些无状态内容。例如,对于1000个首次请求,应用程序必须用“a”响应,对于接下来的10000个请求,应用程序必须用“b”响应,对于其余的请求,应用程序必须用“c”响应 我首先考虑了消息传递:应用程序从一些存储中获取总服务计数->如果它小于n,则服务内容“a”->一旦服务内容,应用程序发送消息->消息被消费->总服务计数在一些存储中递增->。。。然而,在这种情况下,由于消息服务事件和存储上的计数器增量之间的轻微(或在峰值加载时间

考虑一下这个问题:

我有n个Tomcat节点,其中web应用程序提供一些无状态内容。例如,对于1000个首次请求,应用程序必须用“a”响应,对于接下来的10000个请求,应用程序必须用“b”响应,对于其余的请求,应用程序必须用“c”响应

我首先考虑了消息传递:应用程序从一些存储中获取总服务计数->如果它小于n,则服务内容“a”->一旦服务内容,应用程序发送消息->消息被消费->总服务计数在一些存储中递增->。。。然而,在这种情况下,由于消息服务事件和存储上的计数器增量之间的轻微(或在峰值加载时间上的巨大)延迟,超调的可能性很大

然后,我考虑设置memcached会话管理器,将计数器存储在某种共享会话中。但对于我的简单案例来说,这看起来相当沉重


有人能建议一下,多个JVM实例之间是否有直接的通信方式(对于我的情况,什么是适用的)

对于初学者,您可以在tomcat实例之间共享会话。接收请求的tomcat服务器基本上会将其会话的副本发送给所有其他tomcat服务

我忍不住想,您有一些未表达的需求驱动此请求,但只想问如何实现此请求,而不实际问如何满足此需求。在这种情况下,需求得不到满足,但请求往往得到满足

例如,一个简单的多ip地址到DNS主机名配置可以以循环方式分发请求,而不用担心向一台服务器发送1000个请求,然后轮换

您还可以根据数据库协调会话。数据库提供了良好的存储能力,具有读取一致性。通过正确的配置,“下一个数字”可以简单地由处理节点读取

最后,还有其他方法,利用分布式计算。例如,请求可以由内部请求中继处理,该中继启动类似Paxos的协议,以确保所有处理节点都具有新的“下一个”编号

所有这些技术都很简单。然而,你很快就把他们解雇了,因为他们对你来说似乎不太简单。好吧,也许你正在寻找一个更简单的选择,这没有坏处;然而,让两台或两台以上的计算机在同一时间一致、可靠地就某一事项达成一致意见比我们都希望的要复杂一些。在这个领域,您可以自由地开始一项新的工作,但也许您只会发现额外的开销和复杂性有真正的原因。这不是一个微不足道的问题

---更新---

你知道,如果你能以循环的方式处理请求,并且不需要在服务器之间对它们进行排序,并且知道你将只有N个服务器,那么你可以实现N个不同的请求计数器

  • 服务器1增加N,确保
    计数%N==0
  • 服务器2递增N,确保
    计数%N==1
  • 服务器N-1增加N,确保
    计数%N=N-2
  • 服务器N增加N,确保
    计数%N=N-1
当然,在短会话中,跨服务器计数可能会超出全局顺序,但您可能会很快得到一点您想要的:

  • 每个请求的唯一计数
  • 基于每台服务器的请求排序
  • 保证在所有服务器上都是唯一的计数
  • 快速确定哪个服务器处理了请求的方法
你会缺少什么

  • 跨服务器请求的真实顺序

以下是您所订购的所有选项,从最省力到最省力,都是设置这些选项所需的:

  • 用于跨各种Tomcat存储会话
  • 使用轻量级数据库,如
    sqlite
    ,并将计数器存储在表/集合中
  • 使用共享文件系统并将计数器存储在文本文件中
  • 使用轻量级缓存提供程序,如Redis、Memcahed、Ehcache或Hazelcast
  • 使用JMS之类的消息传递,并不断传递计数器

  • 如果它必须是正确的,并且您不希望延迟,那么我认为RedisHazlecast是您的最佳选择。虽然从理论上讲,您可以对memcache执行相同的操作,但Redis是为这个确切的用例(统计计数器)而设计的


    您还可以使用内存中的db(如H2),或者只将Postgres表设置为
    unlocked
    ,或者任何适用于RDBMS的设置,以保持不太安全的内存中伪表。RDBMS令人恼火的一点是,并非所有RDBMS都支持一致性。

    一致性有多重要?如果您想在前10000个请求之后更改行为,那么如果行为在前10010个请求之后实际更改,会发生什么情况?您愿意容忍什么级别的slop?会话不是与“无状态”不兼容吗?递增计数器的想法不是与“无状态”的想法不兼容吗?无状态操作可以为相同的输入生成相同的输出,而不管以前的调用历史如何。不可能有无状态计数器,除非您设法将状态处理逻辑推离web处理逻辑很远,在这种情况下,您将如何满足您的需求?远程项目在会话启动很久之后才能开始“计算”会话。@ChristopherSchultz我添加了一个更新。这项技术远非新技术,但它取决于服务器之间不需要真正的排序。它确实提供了一些你想要的,非常简单的架构;然而,它并不能提供你想要的一切。如果解决方案的简单性变得比