【问题标题】:Control C application from Java web application从 Java Web 应用程序控制 C 应用程序
【发布时间】:2015-01-08 22:52:54
【问题描述】:

我有可以在不同站点的多台机器上运行的 C 应用程序。

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

我认为 C 应用程序将通过 TCP 连接到 Java Web 应用程序。在我的 Web 应用程序中,我正在考虑实现通过 TCP 与 C 应用程序通信的管理器。当 Web 应用程序作为单独的线程启动时,我将启动管理器。管理器将通过 Context 和 Session 与 servlet 请求进行通信。所以每当用户在浏览器上做某事时,我想在服务器上使用我的管理器的功能,用 ServetContext 一个 Session 作为接口。

所以这就是我的想法。所以,我想知道是否有更好的方法,或者我做错了什么?谁能建议我更好的解决方案?

编辑

当前工作流程:每当我需要启动/停止 C 应用程序时,我必须通过 SSH 远程机器 puTTY 终端,输入长命令,然后启动/停止它。每当出现问题时,我都必须滚动长长的日志文件。还有其他一些事情,比如应用程序正在做什么/每秒处理所有事情的实时状态,我不能总是在日志文件中登录。

所以我发现这些工作流程很困难。还有我无法监控的直播状态等。

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

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

我想使用 JSP/servlets 用 Ja​​va 设计的 Web 界面。

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

问题:

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

编辑 2

对于控制者经理之间的混淆,我们深表歉意。两者都是一样的。

我的想法: 系统将由运行在不同站点的 C 应用程序、在 Tomcat 服务器中并行运行的 Java 控制器和 Java Web 应用程序以及 DB 组成。

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

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

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

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

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

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

【问题讨论】:

  • 如果我的问题不清楚,请告诉我。
  • 因此,基本上,您的 Java Web 应用程序中会有一个不同的线程从 C 应用程序收集数据,然后您的 Web 应用程序将从线程中查询这些数据。对吗?
  • @LuiggiMendoza 是的,我正在考虑实现使用 ServletContext/HttpSession 与 Web 应用程序通信并通过 TCP 连接与 C 应用程序通信的管理器(控制器)。当 Web 应用程序启动时,我将在单独的线程中启动管理器。可能在 contextInitialized 事件中启动它。
  • 提示:不要使用 ServletContext 或 Session 来存储这些数据。相反,使用第三个组件,如数据库(关系或内存中,可能内存中更适合更快地访问数据),因为它们都不是真正的缓存,并且它们不支持多线程添加/删除元素。此外,我会将管理器应用(从 C 应用接收数据)和网络应用分开。
  • @LuiggiMendoza 当然,我将有数据库来存储数据。但是为了分享一些最近的日志数据,我想直接分享到网络应用程序(同步)。

标签: java c tcp middleware


【解决方案1】:

这是一种有效的方法,我相信套接字是大多数分布式系统进行通信的方式,而且在同一个盒子上的不同服务也经常以这种方式进行通信。此外,我相信您对 java Web 服务的建议非常典型并且会运行良好(它的复杂性可能会超出您目前的想法,但您描述的架构是一个好的开始)。

如果您的 C 服务也被设置为独立于管理系统运行,那么您可能需要反转它并让管理系统连接到服务(除非您的防火墙阻止它)。

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

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

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

如果我知道更多关于你期望做什么的细节,我或许可以为你提供更多信息——例如,你的浏览器多久更新一次它的字段,将发送什么样的命令信号或数据请求以及什么您希望返回什么样的数据?尽管您当然不必在此处发布这些内容,但您必须考虑一下——我建议您先模拟您的浏览器页面。


基于 cmets 的编辑: 听起来不错,只需几个 cmets:

2) 任何优秀的数据库都应该能够处理用于记录的大量数据,但您可能希望在数据库之上使用良好的缓存。

5) 您可能需要一个 Web 框架来呈现图形和管理更新。有很多,大多数人都可以很容易地做到你所说的,但是在没有某种框架的情况下尝试自己做这一切可能会很困难。我之所以这么说,是因为你没有提到。

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

您可能希望构建一种“重启”您的 C 服务的方式。由于它们是作为服务启动的,因此只需发送一个告诉它们终止/退出的命令通常会起作用,因为系统将重新启动它们。您可能还需要一个小监控循环,在某些条件下重新启动它们(例如它们在 n 分钟内没有从服务器获得命令)。当您早上 10 点在加利福尼亚尝试凌晨 2 点在澳大利亚使用 C 服务时,这会派上用场。

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


更正:

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

一个更好的方法可能是放弃数据库,只使用预先过滤到单个用户可能希望看到的平面日志文件,因此如果用户要求最后 5 分钟的“WARN”和“DEBUG”消息来自一台机器,您可以将日志文件从该机器读入内存,跳过除警告/调试消息之外的所有消息,并显示这些消息。这有它自己的问题,但应该比索引数据库更具可扩展性。这还允许您压缩旧数据(用户不想再查询),从而节省 70-90% 的磁盘空间。

【讨论】:

  • 非常感谢您的宝贵回答。是的,所以我开始在控制器和 C 应用程序之间建立 TCP 连接。 DB方法似乎也不错。但是 C 应用程序也会出现在不同的站点,例如澳大利亚、加拿大、美国、印度,那么 DB 在这里会有所帮助吗?
  • 当然我必须考虑 C 应用程序和控制器之间的协议,这将防止版本增加。
  • 你能看看我更新的问题,并请提供一些建议吗?
  • 再次感谢您提供有用的提示。每秒生成的日志将是每秒的某种样本,例如发送/接收数据速率,各种数据错误的数量等。是的,大量的数据库插入对我来说似乎并不好,它可以是现在还好,但谁知道未来。我正在考虑将持续时间为 5 分钟或小时的日志压缩为 BLOB 或 TEXT,并插入到按日期时间索引的数据库中。
  • 关于 (6),是的,我需要重新连接 TCP 连接和恢复状态的机制。我将需要 C 应用程序中的机制来在 TCP 连接断开时将日志保存在临时文件中。我需要检测 C 应用程序和控制器。
【解决方案2】:

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

  • 定义一个协议以在 C 应用程序和监视器应用程序之间进行通信。可能您不需要来自所有 C 应用程序的相同格式的相同信息,或者某些 C 应用程序比其他应用程序有更重要的指标。我建议为此使用纯 JSON,并定义要实现的最小架构,以便 C 生成数据,Java 使用和验证数据。
  • 使用数据库存储监控 C 应用程序的结果。通用选项将使用 RDBMS,可能是开源的,如 MySQL 或 PostgreSQL,或者如果您(或您的公司)可以获得 SQL Server 或 Oracle 或其他许可证的许可证。这以防您需要维护结果历史记录,并且可以定期清除数据。
  • 可能您希望/需要在某种缓存中获得最新的监控结果(因为此时性能至关重要),因此您可以使用像 Hazelcast 或 Redis 这样的内存数据库,或者只是一个简单的缓存比如 EhCache 或 Infinispan。将数据存储在外部元素中比将其存储在普通的ServletContext 中要好,因为这些技术知道多线程并支持ACID,这不是ServletContext 的主要用例,但对于监视器来说似乎是必要的。
  • 将将从 C 应用程序接收数据的监视器与 Web 应用程序分开。如果监视器发生故障或执行某些操作需要花费太多时间,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 应用程序中的另一个线程进行通信,以转换操作并执行它。

【讨论】:

  • 非常感谢您的宝贵建议。是的,我将在 C 应用程序和控制器之间使用 RDBMS 和协议。使用内存数据库似乎更好,而不是使用 hashmaps/lists 并自己管理它以实现线程安全。
  • 对于 C 应用程序将是每台机器,它将执行用户从 Web 浏览器发送的任何任务,抱歉我的意思不是直接从浏览器到 C 应用程序通信,而是通过 Web 应用程序和控制器。
  • 对于用户监控 C 应用程序任务,将在图表中看到进度,每秒更新一次。此外,在 C 应用程序中可能偶尔发生的信息/错误事件日志的文本行,现在我正在考虑在客户端使用 AJAX/jquery,并且 Web 服务器从内存数据库中提取最近的日志数据。由于大部分时间用户将实时监控,我可能不需要经常访问 MySQL。
  • 为了分离网络应用程序和控制器应用程序,您能否建议我如何使控制器应用程序与网络应用程序通信?网页服务? Web 应用程序可能需要多次调用控制器,例如 100 次/秒。分离是指在单独的 JVM 上?
  • @Huko 通信将通过关系数据库和内存数据库进行。由于两者都支持 ACID 事务并支持多线程,因此在您需要的任何时候检索一致的数据都不会出现问题。
猜你喜欢
  • 2010-11-24
  • 2016-03-07
  • 2019-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多