从Java Web应用程序控制C应用程序

时间:2014-11-12 06:56:30

标签: java c tcp middleware

我的C应用程序将在不同站点的多台计算机上运行。

现在我想控制和监控这些C应用程序。为此,我正在考虑使用Servlet / JSP的Java Web应用程序。

我认为C应用程序将通过TCP连接到Java Web应用程序。在我的Web应用程序中,我正在考虑实现通过TCP与C应用程序通信的管理器。我将在Web应用程序作为单独的线程启动时启动管理器。经理将通过Context和Session与servlet请求进行通信。因此,每当用户在浏览器上执行某些操作时,我希望在服务器上使用我的经理的功能,使用ServetContext作为接口的会话。

所以这就是我的想法。所以,我想知道是否有更好的方法,或者我做错了什么?任何人都可以建议我更好的解决方案吗?

修改

当前工作流程:每当我需要启动/停止C应用程序时,我必须SSH远程机器puTTY终端,输入长命令,然后启动/停止它。每当出现问题时,我都需要滚动很长的日志文件。还有其他一些事情,例如应用程序正在进行的实时状态/每秒处理所有事情,我无法始终记录在日志文件中。

所以我发现这些工作流程很难。像生活状态这样的东西我无法监控。

现在我想拥有Web应用程序界面。我可以修改我的C应用程序并从头开始实现Web应用程序。

要实施的新工作流程:我想从网页启动/停止C应用程序。我想在网页上查看日志和实时状态报告/实时图表(监控C应用程序正在做什么)。我也希望在网页上监控机器状态。

我认为使用JSP / servlets在Java中设计的Web界面。

因此,我将修改我的C应用程序,以便它可以与Web应用程序进行通信。

问题:

只需要制定新工作流程的指南/最佳做法。

编辑2

很抱歉控制器经理之间存在混淆。两者都是一样的。

我的想法: 系统将包括在不同站点运行的C应用程序,在Tomcat服务器和DB中并行运行的Java控制器和Java Web应用程序。

1)C应用程序将通过TCP连接到控制器。因此,这里的控制器成为服务器和C应用程序客户端。

2)C应用程序将是多线程的,将从控制器接收任务并生成新线程以执行该任务。当控制器告诉停止任务时,C应用程序将停止该任务的线程。此外,C应用程序会将工作进度(日志)每秒发送到控制器。

3)Controller从Web应用程序接收任务命令(因为两者都在Tomcat服务器上并行运行,在JVM上的同一实例中),Web应用程序将通过HTTP从用户接收命令。

4)从C应用程序到控制器每秒收到的工作进度(日志),然后控制器会在DB中插入日志以供以后分析(需要考虑是否在MySQL RDBMS中插入日志好,可能需要做很多事情插入物,可以是每秒100或1000,永远)。 Web应用程序还可以从控制器请求最近5分钟的日志,并通过HTTP发送给用户。如果用户正在监视日志,那么Web应用程序必须每秒从控制器检索日志并通过HTTP发送给用户。

5)用户监控C应用程序任务,将在图表中看到进度,每秒更新一次。另外,在C应用程序中偶尔会发生的信息/错误事件日志的文本行。

6)C应用程序将是每台机器,它将执行用户从Web浏览器发送的任何任务。 C应用程序将作为服务在机器中运行,它将在机器启动时启动,将连接到服务器,并将永远保持与服务器的连接。如果没有要执行的任务,可以空闲运行。

2 个答案:

答案 0 :(得分:2)

这是一种有效的方法,我相信套接字是大多数分布式系统进行通信的方式,而且即使是同一个盒子上的不同服务也经常这样沟通。另外我相信你对java web服务的建议是非常典型的并且运行良好(它的复杂程度可能超出你目前的想法,但你所描述的结构是一个良好的开端)。

如果您的C服务也独立于管理系统运行,那么您可能想要撤消它并让管理系统连接到服务(除非您的防火墙阻止它)。

您肯定需要一个小巧,定义明确的协议。如果您要发送大量字段,您甚至可以制作发送JSON或xml的所有内容,因为它们已经有解析器来验证格式。

小心安全!在C端确保您不会获得任何缓冲区溢出,如果您自己解析信息,请严格丢弃(并记录!)看起来不正确的数据。在Java上,缓冲区溢出不是问题,但请确保您记录的数据包不完全符合您的协议以检测错误和入侵。

您可能会考虑的另一个解决方案 - 您的系统共享数据库已经可以通过数据库发送命令和响应(假设命令/响应不常发生)。我们并没有完全这样做,但我们共享一个变量表,我们在其中放置名称/值对,表示我们系统性能和配置的不同方面(它是双向的),这可能不是最佳但是由于它允许我们在运行时重新配置我们的系统(这些值在每个服务中本地缓存并且每30秒重新读取/更新),因此具有非常灵活性。

如果我知道您希望做什么更具体的细节,我可能会给您更多信息 - 例如,您的浏览器多久更新一次字段,什么样的命令信号或数据请求将会被发送,你期望什么样的数据?虽然你肯定不必在这里发布这些东西,但你必须考虑它 - 我建议你嘲笑你的浏览器页面。


根据评论进行编辑: 听起来不错,只有几条评论:

2)任何好的数据库都应该能够处理该数据量以进行日志记录,但您可能希望在数据库之上使用一个好的缓存。

5)您可能希望Web框架呈现图形并管理更新。有很多,大多数可以很容易地做你正在说的话,但是如果没有某种框架的话,尝试自己做这件事可能会很困难。我只是这样说,因为你没有提到它。

6)确保您可以处理断开连接并重新连接。在测试时,拔下服务器上的插头(至少是网线),然后将其拔出10分钟,然后确保在重新插入时获得预期的结果(客户端是否应自动重新连接?是否应该重新连接?抓住原木或将它们扔掉?它能在原木上保留多长时间?)

你可能希望建立一种方式来重建"重启"你的C服务。由于它们是作为服务启动的,因此只需发送一个告诉它们终止/退出的命令通常就会起作用,因为系统会重新启动它们。您可能还需要一个小监视循环,在某些条件下重新启动它们(就像它们没有从服务器获取命令n分钟)。当你早上10点在加利福尼亚州尝试使用Austraillia的C服务时,这可以派上用场。

另外,请考虑攻击者可以在您的客户端和服务器之间插入自己。如果您使用的是SSL套接字,那么您应该没问题,但如果它是原始套接字,您必须非常小心。


校正:

将许多记录放入MySQL数据库时可能会遇到问题。如果它没有编入索引并且您最小化对它的查询,那么您可能没问题。您可以通过将所有日志的最后5分钟保留在内存中来实现此目的,这样您就不必索引数据库,也可以对插入进行分组或调整缓存。

更好的方法可能是放弃数据库,只使用预过滤到单个用户可能想要查看的平面日志文件,因此如果用户要求最后5分钟"警告"和#34; DEBUG"来自计算机的消息,您只需将该计算机中的日志文件读入内存,跳过除警告/调试消息之外的所有消息,然后显示这些消息。这有其自身的问题,但应该比索引数据库更具可扩展性。这还可以让您压缩旧数据(用户不再需要查询),以节省70-90%的磁盘空间。

答案 1 :(得分:2)

以下是我对您当前设计的建议,因为您尚未为此项目定义具体范围:

  • 定义用于在C应用程序和监视器应用程序之间进行通信的协议。可能您不需要相同格式的所有C应用程序中的相同信息,或者某些C应用程序的重要指标比其他应用程序更重要。我建议使用普通的JSON,并定义一个最小的模式,以便C生成数据和Java消费并验证它。
  • 使用数据库存储监控C应用的结果。通用选项将使用RDBMS,可能是开源,如MySQL或PostgreSQL,或者如果您(或您的公司)可以获得许可证,则可以使用SQL Server或Oracle或其他版本。如果您需要维护结果的历史记录,并且可以定期清除数据。
  • 您可能希望/需要在某种缓存中获得监控的最新结果(因为此时性能至关重要),因此您可以使用内存数据库,如Hazelcast或Redis,或只是一个简单的缓存像EhCache或Infinispan。将数据存储在外部元素中比将其存储在普通ServletContext中更好,因为这些技术知道多线程和支持ACID,这不是ServletContext的主要用例,但似乎监视器所必需的。
  • 将从Web应用程序中分离将从C应用程序接收数据的监视器。如果监视器出现故障或执行某些操作需要太多时间,Web应用程序仍然可以工作,而无需从C应用程序接收和管理数据的开销。另一方面,如果Web应用程序开始变慢(由于应用程序的实现中的问题或应该使用分析器发现的东西),那么您可以重新启动它,并且通过这样做,您的监视器应该继续收集数据从C应用程序中将它们存储在您的数据源中。
  • 对于监视器应用程序中的线程,由于它似乎将基于Java,因此请使用ExecutorService而不是手动创建和管理线程。

对于这部分:

用户监控C应用程序任务,将在图表中看到进度,每秒更新一次。此外,在C应用程序中偶尔会发生的信息/错误事件日志的文本行

您可以使用Rx Java来更新您的视图(JSP,Facelet,纯HTML或您将使用的任何内容)或其他反应式编程模型(如Play Framework)以从数据库(和缓存)连续读取数据如果您使用它)并以直接方式为Web应用程序的用户更新视图。如果您不想使用此编程模型,那么至少使用推送技术,如cometWebSockets。如果这部分不那么重要,那么使用一个简单的刷新计时器,如下所述:How to reload page every 5 second?

对于这部分:

C应用程序将是每台计算机,它将执行用户从Web浏览器发送的任何任务

您可以重复使用协议将使用JSON的C应用程序与监视器和每个C应用程序中的另一个线程进行通信,以转换操作并执行它。