高级异步 Web 服务





4.00/5 (16投票s)
2004年4月21日
4分钟阅读

80088

411
高级异步 Web 服务。
引言
本应用程序展示了如何在您的应用程序中使用异步 Web 服务以及如何使用回调方法。我创建这个应用程序是为了计算在多台机器上运行长进程与在单台机器上运行长进程时的加速比。
这台机器显示了哪个作业正在运行,哪个任务,以及最新的任务以红色显示。
我的方法
我使用了 .NET/C#/SOAP 和 Web 服务技术来实现。使用异步 .NET Web 服务的好处是,当另一台机器上的函数完成时,它们会调用回调函数,这大大简化了项目的复杂性。特别是,当我们需要分派 400 个作业时,我只需要检查哪台机器调用了回调,意味着那台机器现在空闲了,所以我将下一个任务分派给那台机器。
异步 Web 服务
当您创建任何 Web 方法时,它也会为您创建一个异步方法,该方法在 Web 方法名称前有一个“Begin
”关键字。
例如,我有一个 SortMachine1
Web 方法,所以我这样调用它
BeginSortMachine1(parameter,CallBackFunction,0);
这是一个回调函数,当异步 Web 服务完成时,会调用此函数。
public void OnCBMachine1(IAsyncResult ar)
{
try
{
if (false == bIsBtn400Clicked)
{
mylist1[0] = st.EndSortMachine1(ar);
bMachineDone[0] = true;
eTime[0] = System.DateTime.Now;
timeDiff[0] = eTime[0].Subtract(sTime[0]);
lblMachine1Time.Text = timeDiff[0].TotalMilliseconds.ToString();
lblMsg1.Text = "Finished Machine 1 Job.";
if ( bMachineDone[1] == true && bMachineDone[2] == true &&
bMachineDone[3] == true )
{
timeDiff[4] = eTime[0].Subtract(sTime[0]);
lblTimeTaken.Text = timeDiff[4].TotalMilliseconds.ToString();
double dTime = timeDiff[4].TotalMilliseconds / Int32.Parse(datasize4.Text);
avg4.Text = dTime.ToString();
task4.Text = (timeDiff[4].TotalMilliseconds / 4).ToString();
lblInfo.Text = "Job Completed";
}
}
else
{
mylist400[nCounterMachine1] = st.EndSortMachine1(ar);
bMachineDone[0] = true;
eTime[0] = System.DateTime.Now;
timeDiff[0] = eTime[0].Subtract(sTime[0]);
TotalTimeFor400Tasks += timeDiff[0].TotalMilliseconds;
lblMachine1Time.Text = timeDiff[0].TotalMilliseconds.ToString();
lblMsg1.Text = "Finished Machine 1 Job # " + (nCounterMachine1+1).ToString();
lblTimeTaken.Text = TotalTimeFor400Tasks.ToString();
double dTime = TotalTimeFor400Tasks / Int32.Parse(datasize400.Text);
avg400.Text = dTime.ToString();
task400.Text = (TotalTimeFor400Tasks / nCurrentJobIndex).ToString();
if ( nCurrentJobIndex == 400)
{
lblInfo.Text = "Job Completed";
dTime = TotalTimeFor400Tasks / Int32.Parse(datasize400.Text);
avg400.Text = dTime.ToString();
task400.Text = (TotalTimeFor400Tasks / nCurrentJobIndex).ToString();
}
else
ServiceJobs();
}
}
catch(Exception ex)
{
lblInfo.Text = ex.Message.ToString();
}
}
项目组成部分
我将项目分为两个部分。
服务器:这是一个 XML Web 服务,它有四个 Web 方法,使用 (O)n² 算法对数据进行排序。在 .NET 中创建 XML Web 服务是一项非常容易的任务。棘手的部分是我希望异步使用这些方法。当您在 .NET 中创建 Web 服务时,它会同时创建异步和同步方法。您只需要添加一个 Begin
关键字,如果您想将该方法用作异步。此外,您需要指定一个回调函数,该函数在 Web 方法完成后由 Web 方法调用。
我创建了运行在四台不同机器上的 XML Web 服务,这些 Web 服务包含用于数据排序(On²)算法的函数。这个 Web 服务称为 DataProcess
,并包含四个函数。
客户端应用程序(基于 Windows 的应用程序):这是我制作的第二个应用程序。这是一个简单的 C# .NET Windows 应用程序。我为我放在办公室局域网不同计算机上的服务添加了 Web 引用。在 .NET 中搜索所有可用的 Web 服务非常容易。
应用程序的屏幕截图
点击 添加引用 按钮将显示此对话框
如果您点击 本地计算机,它会在您的机器上搜索,并列出您计算机上可用的 Web 服务。
这是一个基于 Windows 的应用程序。它是一个简单的应用程序。它有 3 个选项
- 单线程:这意味着应用程序作为完整任务在同一台机器上运行并估算时间。
- 4 个任务:由于我们有四台机器,创建 4 个任务,并将作业分配给每台机器并开始计时,当所有作业完成时,计算时间。从开始时间减去这个时间,这就是该方法所花费的总时间。
- 400 个任务:这是一个有点棘手的 part。我按以下顺序解决了这个问题。创建 400 个任务。
- 启动计时器。
- 将前四个任务发送到四台机器,并保持当前作业的计数器。
- 我们将所有作业异步调用,所以一旦收到来自机器的回调函数,我就发送另一个作业上线并增加计数器。
- 继续这样做,直到计数器达到 400(意味着所有作业都已分派)。
- 现在等待最后一个作业完成,一旦收到回调,就标记该时间。
- 计算该时间与开始时间的差值,这就是该方法所花费的总时间。
分析
- 单机测试分析
所有时间单位为毫秒。
单机测试
当我第一次阅读这个问题时,我以为 400 个任务的性能会比 4 个任务好,即使在单台机器上。但结果完全相反。原因:当我在同一台机器上运行 400 个任务时,它占用了全部 CPU 时间,CPU 使用率为 100%,这极大地降低了整个系统的性能。该项目旨在运行在 4 台不同的机器上,所以您在同一台机器上运行时可能不会获得预期的结果。
- 多机测试分析
在这种情况下,我们为 400 个任务获得了更好的结果,但对于 4 个任务,改进并不明显。我认为有两个原因。
- 对于四个任务,我们为每台机器创建一个连接对象,以便我们可以调用 Web 服务,这会在第一次调用时引入减速。
- 每台从属机器只调用了一次函数,所以在这一点上没有任何东西在缓存中。
在 400 个任务的情况下获得更好结果的原因。
- 我们只创建一次连接对象,然后反复调用 Web 服务,这提高了性能。
Tt = Total time to execute job one as single program. Tp = Time of that part of job, that can be broken down into independent tasks. Speed Up = S(k) = Tt / Tk = 7232.6224 / 2214.7874 = 3.265
理论加速比:
1 S(k) = --------------------- (1-b) + b/k Here K = 4, lets assume b = 1, which is an ideal case, when everything is distributed. Then S(k) = 4. If b = .96 S(k) = 1/ (.04+ .24) = 1/ .28 = 3.57