如何在调用之前检查 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 中启动并运行的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Web 驱动程序中检查页面是不是已完全加载?

如何检查数据库中是不是已存在该值?

如何检查 APK 是不是已签名或“调试构建”?

如何检查以太坊交易是不是已被挖掘

如何检查组件是不是已卸载到功能组件中?

如何检查服务是不是正在运行[重复]