使用 gSoap 链接多个 SOAP 服务时启用保持活动
Enabling keep-alive when chaining multiple SOAP services with gSoap
我们有一个执行 soap 方法代理的 C++ windows 项目。我们使用 gSoap 来实现输入/服务器服务以通过 SOAP 方法接受数据,并使用输出/客户端服务来代理对远程系统的传入调用。
SOAP 服务是在固定的遗留规范中定义的,我们无法控制我们从中接收数据的客户端系统或我们将数据代理到的服务器。
SOAP 服务在多个 WSDL 规范中定义,我们的系统必须在一个服务器端口/端点后面实现所有服务。 gSoap 文档涵盖了此要求(第 How to Chain C++ Server Classes to Accept Messages on the Same Port 部分)并且我们的代码严格遵循该指南。
总的来说,系统运行良好,我们有一个独立部署的集成轻量级解决方案。
但是代码部署在一些密集的高容量/高调用频率的情况下,这给我们带来了几个问题。我相信如果服务器端服务允许 HTTP keep-alive,我们的问题就会得到解决,但是用于链接多个服务的记录的 gSoap 方法特别建议不要启用 HTTP keep-alive:
Do not enable keep-alive support, as the socket may stay open
indefinitely afterwards as a consequence.
我们多次尝试通过使用 SOAP_IO_KEEPALIVE 标志启动服务/gSoap 来忽略此建议,但 gSoap HTTP 连接处理中似乎有代码强制在每个 SOAP 事务完成后关闭连接完成。
这些是此限制导致的问题类型:
- 对于在大容量情况下需要为每个唯一事务建立新的 HTTP 连接效率低下的普遍担忧。对短暂端口耗尽的担忧。
- 一些客户端尝试使用 HTTP Expect: 100-continue 调用具有部分数据负载的 SOAP 方法。这些事务总是失败,因为连接被 gSoap 服务器关闭,使客户端没有机会继续。
- 有时需要使用安全的 SSL 通信。但是如果没有 HTTP keep-alive,客户端需要为每个事务协商一个 SSL 连接,这在高调用频率的情况下会带来高得令人望而却步的开销。
关于我们实施的一些细节:
我们使用 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 支持的回复:
The approach is fine to make sure HTTP keep-alive is enabled while
running the server loop.
The example in the documentation is a simplified approach to show the
logic of chaining multiple attempted dispatches, but it has the
keep-alive limitation you stated.
But that does not prevent the use of the same strategy we use for a
non-changed service dispatching. The code you are using is fine,
replacing the gist of the loop body by the dispatch attempts.
Wondering if we should say something in the documentation about this
limitation, since it does not mention this.
我们有一个执行 soap 方法代理的 C++ windows 项目。我们使用 gSoap 来实现输入/服务器服务以通过 SOAP 方法接受数据,并使用输出/客户端服务来代理对远程系统的传入调用。
SOAP 服务是在固定的遗留规范中定义的,我们无法控制我们从中接收数据的客户端系统或我们将数据代理到的服务器。
SOAP 服务在多个 WSDL 规范中定义,我们的系统必须在一个服务器端口/端点后面实现所有服务。 gSoap 文档涵盖了此要求(第 How to Chain C++ Server Classes to Accept Messages on the Same Port 部分)并且我们的代码严格遵循该指南。
总的来说,系统运行良好,我们有一个独立部署的集成轻量级解决方案。
但是代码部署在一些密集的高容量/高调用频率的情况下,这给我们带来了几个问题。我相信如果服务器端服务允许 HTTP keep-alive,我们的问题就会得到解决,但是用于链接多个服务的记录的 gSoap 方法特别建议不要启用 HTTP keep-alive:
Do not enable keep-alive support, as the socket may stay open indefinitely afterwards as a consequence.
我们多次尝试通过使用 SOAP_IO_KEEPALIVE 标志启动服务/gSoap 来忽略此建议,但 gSoap HTTP 连接处理中似乎有代码强制在每个 SOAP 事务完成后关闭连接完成。
这些是此限制导致的问题类型:
- 对于在大容量情况下需要为每个唯一事务建立新的 HTTP 连接效率低下的普遍担忧。对短暂端口耗尽的担忧。
- 一些客户端尝试使用 HTTP Expect: 100-continue 调用具有部分数据负载的 SOAP 方法。这些事务总是失败,因为连接被 gSoap 服务器关闭,使客户端没有机会继续。
- 有时需要使用安全的 SSL 通信。但是如果没有 HTTP keep-alive,客户端需要为每个事务协商一个 SSL 连接,这在高调用频率的情况下会带来高得令人望而却步的开销。
关于我们实施的一些细节: 我们使用 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 支持的回复:
The approach is fine to make sure HTTP keep-alive is enabled while running the server loop.
The example in the documentation is a simplified approach to show the logic of chaining multiple attempted dispatches, but it has the keep-alive limitation you stated.
But that does not prevent the use of the same strategy we use for a non-changed service dispatching. The code you are using is fine, replacing the gist of the loop body by the dispatch attempts.
Wondering if we should say something in the documentation about this limitation, since it does not mention this.