我们有一个执行soap方法代理的C ++ windows项目。我们使用gSoap实现输入/服务器服务以通过SOAP方法接受数据,并使用输出/客户端服务来代理对远程系统的传入调用。
SOAP服务在固定的遗留规范中定义,我们无法控制从我们接收数据的客户端系统或我们代理数据的服务器。
SOAP服务在多个WSDL规范中定义,我们的系统必须在一个服务器端口/端点后面实现所有服务。 gSoap文档涵盖了此要求(部分How to Chain C++ Server Classes to Accept Messages on the Same Port),我们的代码严格遵循指南。
总的来说,系统运行良好,我们有一个独立部署的集成轻量级解决方案。
但是代码部署在一些密集的高音量/高呼叫频率情况下,这给我们带来了一些问题。我相信如果服务器端服务允许HTTP保持活动,我们的问题就会得到解决,但是用于链接多个服务的文档gSoap方法特别建议不要启用HTTP keep-alive:
不要启用keep-alive支持,因为socket可能会在之后无限期地保持打开状态。
我们已经多次尝试通过使用SOAP_IO_KEEPALIVE标志启动services / gSoap来忽略此建议,但似乎gSoap HTTP连接处理中的代码强制在每个SOAP事务完成后关闭连接。
这些是此限制导致的问题类型:
关于我们实现的一些细节:我们使用gSoap WSDL2H组合服务:
wsdl2h -NServTest -s -o ServTestWebServices.h Service1.wsdl Service2.wsdl Service3.wsdl
然后,生成的gSoap定义用于实现服务器端服务类:
soapcpp2 -S -j -w -qServTestWSIn -x ServTestWebServices.h
通常,在没有服务链的情况下实现gSoap集成HTTP连接处理时,代码只需接受连接并调用soap_serve来处理连接的整个生命周期:
struct soap gsoap;
soap_init2(&gsoap, SOAP_IO_KEEPALIVE, SOAP_IO_KEEPALIVE);
SOAP_SOCKET m = soap_bind(gsoap, NULL, port, backlog);
while (soap_valid_socket(soap_accept(gsoap)))
{
soap_serve(gsoap);
soap_destroy(gsoap);
soap_end(gsoap);
}
链接多个服务时,soap_serve()不起作用,因为它无法将调用定向到正确的服务。而是使用以下方法:
struct soap gsoap;
//SOAP_IO_KEEPALIVE does not help here:
soap_init2(&gsoap, SOAP_IO_KEEPALIVE, SOAP_IO_KEEPALIVE);
Service1 srv1(gsoap);
Service2 srv2(gsoap);
Service3 srv3(gsoap);
SOAP_SOCKET m = soap_bind(gsoap, NULL, port, backlog);
while (soap_valid_socket(soap_accept(gsoap)))
{
if (soap_begin_serve(gsoap))
soap_stream_fault(gsoap, std::cerr);
else
{
if (srv1.dispatch() == SOAP_NO_METHOD)
if (srv2.dispatch() == SOAP_NO_METHOD)
srv3.dispatch();
if (soap->error)
soap_send_fault(gsoap);
}
}
我意识到这是gSoap系统的文档限制,但我觉得其他人可能遇到过类似的问题。有没有人找到他们可以分享的解决方案/解决方案?
我在这里分享我自己问题的答案。我最终得到了gSoap人员的一些帮助,他们证实了我找到的解决方案应该没问题。这是我现在使用的代码的要点(基于问题中的代码):
gsoap->keep_alive = gsoap->max_keep_alive + 1;
do
{
if ((gsoap->keep_alive > 0) && (gsoap->max_keep_alive > 0))
gsoap->keep_alive--;
if (soap_begin_serve(gsoap))
{
if (gsoap->error >= SOAP_STOP)
continue;
else
break;
}
if ((SoapServeResult = srv1.dispatch()) == SOAP_NO_METHOD)
if ((SoapServeResult = srv2.dispatch()) == SOAP_NO_METHOD)
if ((SoapServeResult = srv3.dispatch()) == SOAP_NO_METHOD)
{
//no method found - send fault to client
soap_send_fault(srv3.soap);
}
} while (m_pSoap->keep_alive);
这是Genivia / gSoap支持的回应:
这种方法可以确保在运行服务器循环时启用HTTP keep-alive。
文档中的示例是一种简化的方法,用于显示链接多个尝试调度的逻辑,但它具有您声明的保持活动限制。
但这并不妨碍使用我们用于未更改的服务调度的相同策略。您正在使用的代码很好,通过调度尝试替换循环体的要点。
想知道我们是否应该在文档中说出有关此限制的内容,因为它没有提到这一点。