如何在调用之前检查 Java Web 服务是不是已在 PL/SQL 中启动并运行
Posted
技术标签:
【中文标题】如何在调用之前检查 Java Web 服务是不是已在 PL/SQL 中启动并运行【英文标题】:How to Check if a java web service is up and running in PL/SQL before calling it如何在调用之前检查 Java Web 服务是否已在 PL/SQL 中启动并运行 【发布时间】:2015-09-29 18:23:32 【问题描述】:我有一个调用 java web 服务的 PL/SQL 函数。我们在 2 台不同的机器上有这个 java web 服务。我们称它们为 03 和 04。两台不同机器上的完全相同的 Web 服务,以防万一其中一台停机。
现在,我在我的 PL/SQL 函数中硬编码了 SOAP URL,以便始终调用 03。但是我想做的是检查 03 是否启动并运行,然后继续调用它,否则检查并调用 04。如果它们都已关闭,则返回错误状态,例如两台服务器都已关闭。
这是我的 PL/SQL 函数代码:
create or replace FUNCTION "CALL_IPVFBJAVA_WEBSERVICE" (JobID NUMBER) RETURN INT IS
--//URL CALL
SOAP_URL CONSTANT VARCHAR2(1000) := 'http://cdt0rwlm03.dev.gov:9001/mappownblahblah?wsdl';
SOAP_ENVELOPE CONSTANT VARCHAR2(2000) :=
'<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://blahblah">
<env:Header/>
<env:Body>
<ns1:runSeriatimValuation>
<arg0>$JobID</arg0>
<arg1>$JobID</arg1>
</ns1:runSeriatimValuation>
</env:Body>
</env:Envelope>';
--//LOCAL VARIABLES
SOAPENVELOPE VARCHAR2(2000);
v_Return NUMBER(1);
REQUEST UTL_HTTP.REQ;
RESPONSE UTL_HTTP.RESP;
BUFFER VARCHAR2(32767);
SOAPRESPONSE CLOB;
XMLRESPONSE XMLTYPE;
EOF BOOLEAN;
BEGIN
--// CREATE THE SOAP ENVELOPE
SOAPENVELOPE := REPLACE(SOAP_ENVELOPE, '$JobID', JobID);
--// MAKE THE POST CALL TO THE WEB SERVICE
UTL_HTTP.SET_TRANSFER_TIMEOUT(3600);
REQUEST := UTL_HTTP.BEGIN_REQUEST(SOAP_URL, 'POST', UTL_HTTP.HTTP_VERSION_1_1);
UTL_HTTP.SET_HEADER (REQUEST, 'Content-Type', 'text/xml; charset=utf-8');
UTL_HTTP.SET_HEADER (REQUEST, 'Content-Length', LENGTH(SOAPENVELOPE));
UTL_HTTP.SET_HEADER (REQUEST, 'SoapAction', '');
UTL_HTTP.WRITE_TEXT (REQUEST, SOAPENVELOPE);
--// READ THE WEB SERVICE HTTP RESPONSE
RESPONSE := UTL_HTTP.GET_RESPONSE(REQUEST);
DBMS_LOB.CREATETEMPORARY(SOAPRESPONSE, TRUE);
EOF := FALSE;
LOOP
EXIT WHEN EOF;
BEGIN
UTL_HTTP.READ_LINE(RESPONSE, BUFFER, TRUE);
IF LENGTH(BUFFER) > 0 THEN
DBMS_LOB.WRITEAPPEND(SOAPRESPONSE, LENGTH(BUFFER), BUFFER);
END IF;
EXCEPTION WHEN UTL_HTTP.END_OF_BODY THEN
EOF := TRUE;
END;
END LOOP;
UTL_HTTP.END_RESPONSE(RESPONSE);
--// AS THE SOAP RESPONDS WITH XML, WE CONVERT THE RESPONSE TO XML
XMLRESPONSE := XMLTYPE(SOAPRESPONSE);
DBMS_LOB.FREETEMPORARY(SOAPRESPONSE);
v_Return := TO_NUMBER(XMLRESPONSE.EXTRACT('//result/text()').getStringVal());
--// DBMS_OUTPUT.PUT_LINE('v_Return = ' || v_Return);
RETURN(v_Return);
EXCEPTION WHEN OTHERS THEN
IF SOAPRESPONSE IS NOT NULL THEN
DBMS_LOB.FREETEMPORARY(SOAPRESPONSE);
END IF;
RAISE;
END CALL_IPVFBJAVA_WEBSERVICE;
提前致谢,
【问题讨论】:
您需要在 3 上调用服务,等待超时/错误(取决于“down”的含义),然后针对 4 重新运行调用。您实际上想要编写一个将服务器名称作为参数的过程,这样您就可以在不重复自己的情况下实现该逻辑。但是,在调用者和知道哪台服务器启动的 Web 服务之间放置一些基础设施肯定是有意义的。例如 VIP 和负载均衡器。 我会强调@JustinCave 在上面的评论中提出的观点。将load balancing 用于failover 方案。您编写的所有应用程序级解决方案都将逊色。 【参考方案1】:由于您使用的是 PLSQL,您始终可以将值存储在一个小型配置表中。比如……
CREATE TABLE ENDPOINT_PRIORITY
(ENDPOINT_URL VARCHAR2(100),
STATUS VARCHAR2(30),
PRIORITY NUMBER);
编写一个实用函数,可以通过简单的 HTTP 请求快速检查每个端点的状态,并相应地更新表中的记录并最终返回 URL 或抛出异常。
如果由于记录锁定和上下文切换而每分钟多次调用此函数,您将遇到性能问题,但是如果 Web 服务调用是同步的,您也可以在会话中实现内存缓存。
【讨论】:
这只是一个想法——我可以使用 JobID 将 url 传递给函数,然后当引发异常时,我会使用新修改的 url (04) 再次调用该函数。基本上只有在引发异常时才递归调用该函数。但这意味着 04 url 将始终在异常中进行硬编码。那行得通吗?任何反馈都会很棒。 类似这样的:EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.put_line ('从 PL/SQL 函数调用 Java Web 服务时出错:' || SQLERRM); URL2 VARCHAR2(1000) := 'cdt0rwlm04.dev.gov:9001/mapp?wsdl'; v_Return2 NUMBER(1);计数器 = 计数器 + 1; IF SOAPRESPONSE IS NOT NULL THEN -- 当你使用 FREETEMPORARY 时,表空间中的临时段被释放 DBMS_LOB.FREETEMPORARY(SOAPRESPONSE);万一;如果计数器 >= 1 则返回;万一; v_Return2 := CALL_IPVFBJAVA_WEBSERVICE(JobID, URL2); 这肯定会起作用,但它违反了不按异常编码的最佳实践之一。如果您想创建故障转移代码,那么当抛出异常时,您应该使用嵌套函数并将其从 URL 表的结果中排除。因此,游标将包含 URL 表中端点的结果并尝试第一个,如果它返回像 1 这样的成功代码,那么您只需中断,否则它会移动到游标的下一条记录(下一个 URL)并尝试那个。如果你愿意,我可以用一个例子来更新我的答案。以上是关于如何在调用之前检查 Java Web 服务是不是已在 PL/SQL 中启动并运行的主要内容,如果未能解决你的问题,请参考以下文章