使用线程和网络机器来处理大部分使用xml-rpc的工作
本文关键字:xml-rpc 大部分 工作 处理 机器 线程 网络 | 更新日期: 2023-09-27 18:27:50
我正在设计一个应用程序,它似乎可能会被某些必须发生的功能所淹没。基本上,在应用程序的某些部分中,必须在本地机器上使用shell脚本进行转换,对于用户对象来说,这可能需要很长的时间"长达10分钟"。因此,用户不必等待离开页面,因为服务器的响应需要很长时间,我想了两种方法来消除这个问题。
我的想法是,我可以在转换发生之前创建一个线程,并让子线程在主线程继续运行的同时运行shell脚本,这样用户就不会有加载屏幕了,因为我只在perl中做过多线程。启动该功能的过程如下:
public void RunShellScripts(string apppath, string fileargs)
{
System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo.FileName = apppath;
p.StartInfo.Arguments = fileargs;
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = false;
p.StartInfo.RedirectStandardOutput = false;
p.Start();
//after this is done the converted file would be saved in this current directory
//which is the in the value of the fileargs variable
}
此外,为了让托管web服务器的机器不会试图同时处理这么多转换过程,另一个想法是让网络机器从web服务器机器接收xml-rpc来进行文件转换。因此,基本上,Web服务器接收对象,然后向网络机器发送一个xml-rpc来进行转换,并将转换后的文件发送回主机。我也熟悉xml-rpc,但不确定是否可以让它发回一个文件。请注意,这些文件的总容量可能高达1GB。我的经验只是发送结果,而且只使用与C#不同的语言。
您似乎只需要一个并行的Task
,它要么在本地机器上运行shell脚本,要么向另一台机器发送XML-RPC请求。您也可以注册一个回调来通知父线程工作已经完成:
SendOrPostCallback callback = o => Console.WriteLine((string) o));
SynchronizationContext context = SynchronizationContext.Current;
Task t = Task.Factory.StartNew(
() =>
{
RunShellScripts(); // maybe also parallelize this method
// or XML-RPC
context.Post(callback, "Work finished!");
});
当然,回调代码可以是任何东西,我只是在这里打印了一条消息。
我以前使用过XML-RPC,但老实说,我记不太清楚了。我相信你知道如何处理那部分。
通常有不止一种剥猫皮的方法:)
我和我们的一个客户合作的一个项目最近上线了。该应用程序的一部分需要将文档转换为tiff。由于它也是一款基于网络的应用程序,所以与你想要实现的目标有一些相似之处。
然而,我们使用了我的开源服务总线(http://shuttle.codeplex.com/)尽管任何服务总线都可以,或者您可以使用某种排队机制滚动一些东西。
将要转换的文件复制到某个文件共享中。这是通过我们的应用程序服务DocumentConverter.Submit(source, outputMimeType)
执行的。然后,仍然是应用程序服务调用的一部分,在服务总线上发送ConvertDocumentCommand
命令。命令被路由到转换器机器,调用方继续执行它所做的一切。
转换器端点接收包含队列上相关数据(如文件名)的命令,并使用文件共享中的文件使用第三方转换器执行转换。一旦转换完成,转换器端点就会发布DocumentConvertedEvent
,或者在DocumentConversionErrorEvent
失败时发布。
发送方有一个订阅这两个事件的端点,如果可用,则使用转换后的文档。对我们来说,转换后的文档被放置在输入文档所在的文件共享的输出子文件夹中。
这听起来可能有点复杂,但它运行得很好,因为我们的转换器端点只关心转换文档和发布转换结果。幸运的是,它不知道任何其他应用程序。
如果您真的想平衡另一台计算机上的负载,可能的答案包括分布式计算和消息队列。
消息队列
看看RabbitMQ:
一旦服务器运行,客户端就可以发送和接收消息:web服务器发送脚本,处理服务器接收消息,然后再发送另一条消息。
以下是Java中的"Hello World":http://www.rabbitmq.com/tutorials/tutorial-one-java.html
C#客户端文档:https://github.com/rabbitmq/rabbitmq-tutorials/tree/master/dotnet
关于C#客户端的其他一些资源:
- .net中的RabbitMQ入门
- 将RabbitMQ与C结合使用#
分布式计算
这可能有些过头了,但它是可扩展的。关于网格计算的维基百科页面。
NGrid是一个"用C#编写的独立于平台的网格计算框架"。这是一个分布式排序示例。您可以将处理分布在N个节点的网格上,然后使用结果。
Wcf
我很少使用WCF,而且我使用它的几次经历非常烦人。你可能会深入研究,但我不确定它是否符合你的目标。
然而,有一个链接可能对传输大块数据有用:如何:启用流式
备选方案
也许一个简单的远程处理或套接字消息就足够了。它取决于多个因素:所需的可扩展性、计算能力。。。但消息队列看起来像是一条需要探索的路径。
我希望你会觉得它有用。
如果你想在没有xml-rpc的情况下完成,那么你可以尝试以下操作:
- 创建一个线程来启动转换过程
- 等待进程退出
-
当进程完成时引发一个事件,以便您可以对结果执行任何操作。
//step 1. To create a thread in .Net 2.0 and higher you could use the //ParameterizedThreadStart delegate. For example Thread t = new Thread (new ParameterizedThreadStart(RunShellScripts)); Hashtable args = new Hashtable();
//您可以使用任何其他您喜欢的技术来封装参数
hashtable[1] = apppath; hashtable[2] = fileargs; t.Start (args); static void RunShellScripts(object args) { //code to start the process //step 2. Wait for the process to exit while (!shellProcess.HasExited) { //call sleep (Thread.sleep()) or just do nothing } //step 3. raise event to notify the end of process. //shellProcess.ExitCode can tell you if the process exited with error or not }