- 浏览: 56132 次
- 性别:
- 来自: 北京
文章分类
最新评论
ICE的AMI和AMD:
AMI:指的是客户端的调用.一般有一个代理类,一个回调类。 从服务端返回的数据在回调类中的ice_response函数中.
AMD:指的是服务端对客户端的调用分派.一般进行业务处理需要自己写一个类继承于_Disp类。重载method_async(AMD_CALLBACK __cb,arg1,arg2,...)函数.在这个函数中调用__cb的ice_response(result)往回调类中写result.这样客户端就能够接收到回写的结果
异步方法调用(Asynchronous Method Invocation,简称AMI)
下面这种情况就是AMI调用:“斧头帮”大哥(客户端)叫小弟(服务器端)去干收租的活(远程调用),并且给小弟一把烟花炮竹(回调类)。嘱咐说: “我还有其它事情要打扫打扫,如果你的事情办完了,就放'OK'烟花;如果遇到反抗,就放'斧头'烟花!”(服务器答复)。说完,这位大哥就可以放心的做 其它事去了,直到看到天上烟花盛开,根据"OK"或"斧头"状再作处理。
AMI是针对客户端而言的,当客户端使用AMI发出远程调用时,客户端需要提供一个实现了回调接口的类用于接收通知。然后不等待调用完成立即返回,这时可以继续其它活动,当得到服务器端的答复时,客户端的回调类中的方法就会被执行。
例:修改原Helloworld 客户端,使用异步方法远程调用printString。
首先,要修改原来的Printer.ice定义文件,在printString方法前加上["ami"]元标识符。
module Demo
{
interface Printer
{
["ami" ] void printString(string s);
};
};
同样,再用slice2cpp Printer.ice生成Printer.h和Printer.cpp文件,并把这两个文件加入原项目(如果是直接修改之前的代码的话,因为原先已经加入了这两个文件,这步可以跳过)。
观察生成的Printer.h文件,可以找到这个定义:
namespace Demo
{
class AMI_Printer_printString : public ::IceInternal::OutgoingAsync
{
public :
virtual void ice_response() = 0;
virtual void ice_exception( const ::Ice::Exception&) = 0;
...
};
}
这里的AMI_Printer_printString 就是printString方法的AMI回调接口,可以发现它AMI回调接口类名的规律是AMI_类名_方法名。
这个接口提供了两个方法:
void ice_response(<params>);
表明操作已成功完成。各个参数代表的是操作的返回值及out 参数。如果操作的有一个非 void返回类型,ice_response 方法的第一个参数就是操作的返回值。操作的所有out 参数都按照声明时的次序,跟在返回值的后面。
void ice_exception(const Ice::Exception &);
表明抛出了本地或用户异常。
同时,slice2cpp还为Printer代理类生成了异步版本的printString方法:
namespace IceProxy //是代理类
{
namespace Demo
{
class Printer : virtual public ::IceProxy::Ice::Object
{
...
public :
bool printString_async( const ::Demo::AMI_Printer_printStringPtr&,
const ::std::string&);
bool printString_async( const ::Demo::AMI_Printer_printStringPtr&,
const ::std::string&, const ::Ice::Context&);
...
};
}
}
结合这两样东西(AMI_Printer_printString 接口和printString_async 方法),我们的客户端AMI调用方法为:
- 实现AMI_Printer_printString接口的ice_response和ice_exception方法,以响应远程调用完成后的工作。
- 把上面实现的回调对象作为printString_async的参数启动远程调用,然后可以做其它事了。
- 当得到服务端答复后,AMI_Printer_printString接口的ice_response的方法被调用。
演示代码(客户端):
#include <ice/ice.h>
#include <printer.h>
using namespace std;
using namespace Demo;
//实现AMI_Printer_printString接口
struct APP : AMI_Printer_printString
{
virtual void ice_response()
{
cout << "printString完成" << endl;
}
virtual void ice_exception( const ::Ice::Exception& e)
{
cout << "出错啦:" << e << endl;
}
};
class MyApp: public Ice::Application{
public :
virtual int run( int argc, char *argv[])
{
Ice::CommunicatorPtr ic = communicator();
Ice::ObjectPrx base =
ic->stringToProxy("SimplePrinter:default -p 10000" );
Demo::PrinterPrx printer = PrinterPrx::checkedCast(base);
if (!printer) throw "Invalid Proxy!" ;
// 使用AMI异步调用
printer->printString_async(new APP, "Hello World!" );
cout << "做点其它的事情..." << endl;
system("pause" );
return 0;
}
};
int main( int argc, char * argv[])
{
MyApp app;
return app.main(argc,argv);
}
服务端代码不变,编译运行,效果应该是调用printer->printString_async之后还能"做点其它的事情...",当服务端完成后客户端收到通知,显示"printString完成"。
另外,为了突出异步效果,可以修改服务器端代码,故意把printString执行得慢一点:
- struct PrinterImp : Printer{
- virtual void printString( const ::std::string& s,
- const ::Ice::Current&)
- {
- Sleep(1000);
- cout << s << endl;
- }
- };
异步方法分派(Asynchronous Method Dispatch,简称AMD)
AMD是针对服务器端而言的,在同步的情况下,服务器端收到一个调用请求后,在线程池中拿出一个空闲线程用于执行这个调用。这样,服务器在同一时刻所能支持的同步请求数受到线程池大小的限制。
如果线程池内的线程都在忙于执行长时间的操作,那么新的请求到来时就会处于长时间得不到答复的状态,这可能会造成客户端长时间等待(如果客户端没使用AMI的话)。
ICE的解决方法是:服务器收到请求时并不马上执行具体工作,而是把执行这项工作所需的参数以及回调类保存到一个地方(比如队列)后就返回。而另外的线程(或线程池)负责取出保存的参数并执行之,执行结束后使用回调类通知客户端工作已完成(或异常)。
还是用上面“斧头帮”来举例:“斧头帮”大哥(客户端)叫小弟(服务器端)去干收租的活(远程调用),这位小弟并不是马上就去收租去了,而是把这件 工作记录到他的日程表里(同时还有好几个老板叫他干活呢,可怜的人啊~~)。然后等有空的时候再按日程表一项项的做(或者叫其它有空的弟兄帮忙做),做完 工作后该放烟花的就放烟花(回调智能客户端),该砍人的就放信号弹啥的。
例:修改原Helloworld 服务器端,使用异步方法分派处理printString方法。
首先,要修改原来的Printer.ice定义文件,在printString方法前加上["amd"]元标识符。
module Demo{
interface Printer
{
["amd" ] void printString(string s);
};
};
同样,再用slice2cpp Printer.ice生成Printer.h和Printer.cpp文件,并把这两个文件加入原项目(如果是直接修改之前的代码的话,因为原先已经加入了这两个文件,这步可以跳过)。
观察生成的Printer.h文件,可以发现和AMI类似的一个回调接口AMD_Printer_printString :
namespace Demo
{
class AMD_Printer_printString : virtual public ::IceUtil::Shared
{
public :
virtual void ice_response() = 0;
virtual void ice_exception( const ::std::exception&) = 0;
virtual void ice_exception() = 0;
};
...
}
这个回调接口由ICE自己实现,我们只要拿来用就可以了。在哪里用呢?马上就会发现:我们要实现的Printer接口的printString 方法不见了,取而代之的是printString_async 方法:
namespace Demo
{
class Printer : virtual public ::Ice::Object
{
...
virtual void printString_async(
const ::Demo::AMD_Printer_printStringPtr&,
const ::std::string&, const ::Ice::Current& = ::Ice::Current()) = 0;
...
};
}
这个printString_async 方法就是我们要实现的异步分派方法,它的第一个参数就是由ICE实现的回调类AMD_Printer_printString ,在这个方法里,我们要两种方案:
- 直接做具体工作,完成后在末尾调用回调类的ice_response方法告知客户端已完成。这种方案就和之前普通版的服务端一样,是同步执行的。
- 把 回调类和请求所需要的参数放入一个指定的位置,再由其它线程取出执行和通知客户端。这种方案就是异步分派方法,具体实现时还可以有多种方式,如使用命令模 式把参数和具体操作直接封装成一个对象放入队列,然后由另一线程(或线程池)取出执行。后面的示例代码为了简单起见直接使用了Windows API中的线程池功能,而且也没有使用队列。
示例代码
#include <ice/ice.h>
#include "printer.h"
using namespace std;
using namespace Demo;
// 传递给线程函数的参数
struct CallbackEntry{
AMD_Printer_printStringPtr callback;
string str;
};
// 线程函数
DWORD WINAPI DoPrintString( LPVOID lpParameter)
{
// 取得参数
CallbackEntry *pCE = (CallbackEntry *)lpParameter;
// 工作:打印字符(延时1秒模拟长时间操作)
Sleep(1000);
cout << pCE->str << endl;
// 回调,工作完成。如果工作异常,则调用ice_exception();
pCE->callback->ice_response();
// 删除参数(这里使用堆直接传递,其实更好的方法是使用队列)
delete pCE;
return TRUE;
}
struct PrinterImp : Printer{
virtual void printString_async(
const AMD_Printer_printStringPtr &callback,
const string& s, const Ice::Current&)
{
// 参数打包(回调类和pringString方法的参数)
CallbackEntry *pCE = new CallbackEntry;
pCE->callback = callback;
pCE->str = s;
// 让Windows线程池来执行具体任务
::QueueUserWorkItem(DoPrintString,pCE,WT_EXECUTEDEFAULT);
}
};
class MyApp : public Ice::Application{
public :
virtual int run( int n, char * v[]){
Ice::CommunicatorPtr& ic = communicator();
Ice::ObjectAdapterPtr adapter
= ic->createObjectAdapterWithEndpoints("SP" , "default -p 10000" );
Ice::ObjectPtr object = new PrinterImp;
adapter->add(object, ic->stringToIdentity("SimplePrinter" ));
adapter->activate();
ic->waitForShutdown();
return 0;
}
};
int main( int argc, char * argv[])
{
MyApp app;
return app.main(argc, argv);
}
客户端不需要改变,编译运行服务器然后用客户端测试效果。(其实效果不是很明显,因为AMD提高的是服务器的负荷能力)
发表评论
-
C++ 返回值 协变问题
2012-05-20 12:38 1614今天代码遇到了返回值协变问题,不知如何解决,发出来与大家讨论一 ... -
ubuntu ICE install
2011-12-12 22:40 1071转自; http://www.linuxidc.com/Li ... -
ICE在Linux下的完整编译安装
2011-12-07 15:35 3363ICE在Linux下的完整编译安装 安装平台要求:最好用g ... -
ICE开发环境搭建 全
2011-12-07 15:34 1390ICE作为一种无平台的中间件,提供了最灵活的编译方式, ... -
ICE 属性配置相关
2011-11-24 10:51 928在前一篇文章中,大家 ... -
ICE开发环境搭建
2011-11-16 11:12 1723mark一下 转载自 http://bbs.chinaunix ... -
ice 的 Nonmutating 和 Idempotent
2011-11-15 10:37 1013转载地址:http://duckweeds.b ...
相关推荐
总结来说,“ICE异步调用Demo源码”是一个很好的学习资源,可以帮助开发者理解ICE中的异步调用机制,掌握adm和ami的使用方法,以及如何在C++环境中实现这种分布式通信。通过深入研究这个Demo,不仅可以提升对ICE的...
Ice 是一种针对客户端和服务器进行通信的面向对象的中间件平台。Ice 为构建面向对象的客户-服务器应用提供了工具、API 和库支持。...客户和服务器可以分别部署,可以运行在...本代码为ice同步调用和异步调用实例代码。
ICE 异步调用 按照网上已有的例子,客户端调用需要加入["ami"]元数据指定,但ICE 3.4以后的版本不支持,所以对于ICE3.4以后的版本可以用begin_API进行异步调用。本资源的ICE的版本为3.6.1,所以需要提前下载好ICE...
这个demo旨在帮助初学者理解并掌握ICE在winform应用中的异步调用方法。 【描述】中提到,这是一个作者经过深入研究后创建的示例,特别适合那些刚开始接触ICE和异步编程的开发者。异步调用是提高应用程序性能和响应...
标题"ice异步模式源码实例"指的是通过C++在Linux环境下使用ICE框架实现AMD和AMI模式的服务端和客户端,以便进行双向通信。这种通信方式允许服务端和客户端同时处理多个请求,提高系统的响应速度和效率。 描述中的...
7. 性能优化:ICE设计时考虑了性能,支持二进制协议、多线程和异步调用,可以根据应用需求进行优化。 8. 配置和管理:ICE允许配置连接参数,如端口、超时等,也可以使用ICE管理工具监控和管理运行中的服务。 总的...
Ice的详细图解安装过程,入门教程以及示例代码
在这个例子中,我们使用oneway方式来异步调用sayHello方法,然后使用twoway方式来同步调用returnHello方法,以获取事务状态。 在使用ICE中间件时,我们需要注意一些重要的概念。例如,我们需要了解 Slice文件的作用...
二:异步调用 不会阻塞启动操作的调用线程,调用程序必须通过轮流检测,或者等待完成信号来发现调用的完成 三:同步调用WebService 同步调用WebService就是我们平常的调用的写法 1:AsynCall.asmx的...
`ice_oneway`用于异步调用,而`ice_datagram`适用于无连接的UDP通信。如果需要安全连接,还可以设置`ice_secure`为`true`。 5. **通信模式**:在PHP中,`oneway`调用不会等待Python服务端的响应,适合于不需要...
5. **定义回调函数**: ICE支持异步调用,可以使用回调函数处理服务响应。例如,你可以创建一个实现了特定接口的类,并将其实例作为回调参数传递给调用方法。 ```python class MyCallback(ice.OnewayCallback): def...
7. **异步调用**:ICE允许异步调用,提高应用的响应速度和并发处理能力。 在这个“ICE Demo”项目中,你可能会发现以下关键组件和概念: 1. **Slice定义**:项目中可能包含Slice文件,定义了服务接口和数据类型。...
- **AsynResult类**:代表异步调用的状态,可以用来检查调用是否完成或获取结果。 - **轮询方式的完成通知**:通过不断查询AsynResult来检测调用完成。 - **通用的完成通知回调**:为所有类型的异步调用提供通用...
4. **异步调用**:除了同步调用,Ice还提供了异步调用模型,可以避免阻塞主线程,提高程序响应速度。 5. **自动内存管理**:通过引用计数和垃圾回收机制,Ice实现了自动内存管理,减少了内存泄漏的风险。 6. **...
5. **异步调用**:ICE支持同步和异步调用模式,异步调用允许客户端在等待服务端响应的同时执行其他任务,提高应用的响应速度。 6. **负载均衡与故障转移**:ICE客户端可以配置为使用负载均衡策略,将请求分散到多个...
3. **异步调用**: 提供同步和异步两种调用模式,满足不同场景的需求。 4. **事件模型**: 内置事件发布/订阅模型,便于实现基于事件的应用。 5. **调试工具**: 提供了强大的调试工具,帮助开发者定位和解决问题。 ...