我正在做一个项目,在这个项目中我们有一个认证机制。我们在身份验证机制中遵循以下步骤。
wait()方法的帮助下使当前线程等待。notify()方法调用到先前等待的线程,并在响应和用户被输入到我们的系统时发送成功。notify()方法调用到先前等待的线程,并将失败作为响应发送,并向用户显示无效的凭据消息。一切都很好,但最近我们转向了集群环境。我们发现,一些线程即使在用户回复后也没有得到通知,等待时间也是无限的。
对于服务器,我们使用Tomcat5.5,我们遵循http://tomcat.apache.org/tomcat-5.5-doc/cluster-howto.html来创建Tomcat集群环境。
答案::可能的问题和解决方案
可能的问题是集群环境中的多个JVM。现在,我们还将集群Tomcat与生成的字符串一起发送给用户Android应用程序。
当用户单击“回复”按钮时,我们将发送生成的字符串和集群Tomcat,因此在本例中,这两个请求都指向相同的JVM,并且工作正常。
但我不知道上述问题是否有单一的解决办法。
这个解决方案有一个问题。如果集群Tomcat崩溃会发生什么?负载均衡器将向第二个集群Tomcat发送请求,同样的问题也会出现。
发布于 2012-12-27 09:16:54
造成问题的根本原因是,Java被设计成以一种不同的方式工作--试图阻止/等待服务线程是一个重要的不-不。我将首先给出原因,以及如何在此之后解决问题。
Java ( web和EJB层)被设计成能够扩展到非常大的大小(集群中有数百台计算机)。然而,为了做到这一点,设计者必须做出以下假设,这是对如何编写代码的具体限制:
1. Short lived (eg don't block or wait for periods greater than a second or so)
2. Independent of each other (eg no communication between threads)
3. For EJBs, managed by the container
1. A data store accessed through, eg, JDBC. You can use a traditional SQL database or a NoSQL backend
2. Stateful session beans, if you use EJBs. Think of these as Java Bean that persists its fields to a database. Stateful session beans are managed by the container
3. [Web session](http://tomcat.apache.org/tomcat-5.5-doc/servletapi/javax/servlet/http/HttpSession.html) This is a key-value store (kinda like a NoSQL database but without the scale or search capabilities) that persists data for a specific user over their session. It's managed by the Java EE container and has the following properties: 1. It will automatically relocate if the node crashes in a cluster
2. Users can have more than one current web session (i.e. on two different browsers)
3. Web sessions end when the user ends their session by logging out, or when the session is inactive for longer than the configurable timeout.
4. All values that are stored **must** be serializable for them to be persisted or transfered between nodes in a cluster.
如果遵循这些规则,Java容器可以成功地管理集群,包括关闭节点、启动新节点和迁移用户会话,而无需任何特定的开发人员代码。开发人员编写图形界面和业务逻辑--所有的“管道”都由可配置的容器特性管理。
此外,在运行时,Java容器可以被一些相当复杂的软件监视和管理,这些软件可以跟踪实时系统上的应用程序性能和行为问题。
< snark >嗯,这就是理论。实践表明,忽略了一些非常重要的限制,这导致了AOSP和代码注入技术,但这是另一个故事< /snark >
[在这个问题上,围绕‘网络有许多讨论。其中一个关注于EJB的是:为什么不鼓励在Java容器中生成线程? --对像Tomcat这样的web容器来说完全一样--]
抱歉,这篇文章--但这对你的问题很重要。由于线程的限制,您不应该阻止web请求等待另一个请求,稍后的请求。
当前设计的另一个问题是,如果用户与网络断开连接、断电或干脆放弃,该怎么办?大概你会超时,但过了多久?对一些客户来说,可能太早了,这会导致满意度问题。如果超时时间太长,您可能会阻塞Tomcat中的所有工作线程,服务器就会冻结。这将为您的组织打开拒绝服务攻击的大门。
编辑:在发布了更详细的算法描述之后,改进了建议。
尽管上面讨论了阻塞web工作线程的不良做法以及可能的拒绝服务,但很明显,用户有一个很小的时间窗口来对Android电话上的通知作出反应,并且可以保持较小的时间以增强安全性。这个时间窗口也可以保持在Tomcat的响应超时以下。因此可以使用线程阻塞方法。
有两种方法可以解决这个问题:
对于方法1,浏览器通过Javascript对Tomcat上的web服务进行AJAX调用,通过Javascript轮询服务器;如果安卓应用程序通过身份验证,则AJAX调用返回True。优点:客户端,服务器上的实现最少,服务器上没有线程阻塞。缺点:在等待期间,您必须频繁地调用(可能每秒一次--用户不会注意到这个延迟),这相当于服务器上的大量调用和一些额外的负载。
对于方法2,也有选择:
Object.wait() (可选地将节点ID、IP或其他标识符存储在共享数据存储区中)阻止线程:如果是这样,接收安卓应用程序授权的节点需要:1. Either find the node that is currently blocking or broadcast to all nodes in the cluster
2. For each node in 1. above, send a message that identifies the user session to unblock. The message could be sent via: 1. Have an internal-only servlet on each node - this is called by the servlet performing the Android app authorization. The internal servlet will call `Object.notify` on the correct thread
2. Use a JMS pub-sub message queue to broadcast to all members of the cluster. Each node is a subscriber that, on receipt of a notification will call `Object.notify()` on the correct thread.
发布于 2012-12-23 12:03:58
使用等待/通知可能会很棘手。请记住,任何线程都可以随时挂起。因此,在等待之前调用通知是可能的,在这种情况下,等待将永远阻塞。
在您的情况下,我不会想到这一点,因为您涉及到了用户交互。但是对于您所做的同步类型,请尝试使用信号量。创建一个0(零)数量的信号量。等待的线程调用获取(),它将阻塞,直到另一个线程调用release()。
以这种方式使用信号量比等待/通知您描述的任务要健壮得多。
发布于 2012-12-23 12:08:51
在分析了您的问题之后,我得出结论,确切的问题在于集群环境中的多个JVM。
https://stackoverflow.com/questions/14010765
复制相似问题