puetz_SOA_AQ_XML

Werbung
TAG DER DATENBANKEN
20.06.2013
Udo Pütz
Dr. Andreas Kumpf
Advanced Queues und XML-DB
Integration von Oracle in einer SOA
mit Hilfe von asynchroner Kommunikation und
XML-Verarbeitung
Übersicht
Motivation
ESB
XML-DB
Advanced Queues
Gewachsene IT-Landschaft
• Vorhandene Legacy-Systeme
• Verschiedene Technologien
• Viele Punkt-zu-Punkt Schnittstellen
(intern, extern)
• Oft: Datenbanken-Sst., Datei-Sst., propr. APIs,
etc.
• synchrone und asynchrone Kommunikation
• Einzeloperationen und Batchverarbeitung
Service Orientierte Architektur (SOA)
• Einführung eines zentralen Enterprise Service
Bus (ESB)
• Verwaltung von Endpunkten
(Service-Virtualisierung)
• Eine Schnittstelle pro System zwischen ESB
und Legacy System
• ESB routet Messages zwischen den Systemen
• Standard: XML-Austausch über WebServices
(SOAP) und Queues (z.B. JMS)
Oracle Schnittstellen
• Reine DML Schnittstelle (select, insert,
update, delete)
• OCI, OCCI, ODBC, JDBC
• Aufruf von Stored Procedures (synchron)
• Verwendung von WebServices (synchron)
• Queueing von Messages (asnychron)
• Verarbeitung von XML
Business Interface
Option 1
XMLs
ESB
Legacy System
BI
DB
„reincompiliert“
Option 2
XMLs
ESB
Option 3
API
BI
DB
DB-Sst.
XMLs
ESB
Legacy System
BI
DB
Legacy System
SOA-Beispielszenario
ESB
enqueue
(AQ) ESB_2_BI
dequeue
XML
ESB
dequeue
(AQ) BI_2_ESB
enqueue
Business
Interface
(PL/SQL)
Legacy
System
XML-DB
XML
DB
XML-Verarbeitung
• XML wird binär gespeichert (innerhalb BLOB)
• XML wird geparsed und relational gespeichert
• XML wird als XMLType-Spalte abgelegt
(d.h. als DOM)
Oracle XML-DB
•
•
•
•
•
•
Seit 8i XML-Funktionen und Schnittstellen in der DB
Speichern und Manipulieren von XML
Datentyp XMLType (seit 9iR1)
XPath
XML DB Repository für XML Schemata (seit 9iR2)
Weiterer Ausbau der Funktionalität in 10g (Performance,
direct load...)
• XMLElement, XMLAgg, XMLForest,XMLConcat,XMLAgg
erzeugen XML aus einem relationalem Modell
• Extract, ExistsNode, Extractvalue zum Selektieren aus
XMLType
Beispiel: XML-Erzeugung
FILIALE
FilNo
Name
Ort
1
Kundencenter
Koeln
2
Verwaltung
Bonn
MITARBEITER
PersonalNo
Name
FilNo
10
Fox Mulder
1
11
Dana Scully
1
12
Olivia Dunham
2
13
Walter Bishop
2
SELECT f.name filial_name,
f.ort einsatz_ort,
m.name mitarbeiter_name
FROM
filiale f, mitarbeiter m
WHERE m.filNo = f.filNo
filial_name
einsatz_ort
mitarbeiter_name
Kundencenter
Koeln
Fox Mulder
Kundencenter
Koeln
Dana Scully
Verwaltung
Bonn
Olivia Dunham
Verwaltung
Bonn
Walter Bishop
Beispiel: XML-Erzeugung
SELECT
XMLElement("FILIALE", XMLAttributes(f.name AS "name"),
XMLElement("ANGESTELLTE",
XMLForest(f.ort AS "EINSATZORT"),
(SELECT XMLAgg(XMLElement("ANGESTELLTER",
XMLAttributes(m.name AS "name")))
FROM mitarbeiter m
WHERE m.filNo = f.filNo
)
<FILIALE name="Kundencenter">
)
<ANGESTELLTE>
) report_xml
<EINSATZORT>Koeln</EINSATZORT>
FROM
filiale f ► 2 Zeilen als Ergebnis
<ANGESTELLTER name="Fox Mulder"/>
<ANGESTELLTER name="Dana Scully"/>
</ANGESTELLTE>
</FILIALE>
<FILIALE name="Verwaltung">
<ANGESTELLTE>
<EINSATZORT>Bonn</EINSATZORT>
<ANGESTELLTER name="Olivia Dunham"/>
<ANGESTELLTER name="Walter Bishop"/>
</ANGESTELLTE>
</FILIALE>
Beispiel: XML-Selektion über XPath
SELECT COUNT(*)
FROM
dual
WHERE existsNode(XMLType('
<FILIALE name="Kundencenter">
<ANGESTELLTE>
<EINSATZORT>Koeln</EINSATZORT>
<ANGESTELLTER name="Fox Mulder"/>
<ANGESTELLTER name="Dana Scully"/>
</ANGESTELLTE>
</FILIALE>'),
'//FILIALE') = 1
SELECT COUNT(*)
FROM
dual
WHERE extractValue(XMLType('
<FILIALE name="Kundencenter">
<ANGESTELLTE>
<EINSATZORT>Koeln</EINSATZORT>
<ANGESTELLTER name="Fox Mulder"/>
<ANGESTELLTER name="Dana Scully"/>
</ANGESTELLTE>
</FILIALE>'),
'//FILIALE/ANGESTELLTE/EINSATZORT/text()') = 'Koeln'
Oracle XML Query Rewrite
• Optimierung beim Selektieren und
Extrahieren von Daten
• Ohne Query Rewrite wird das XML aus der DB
gelesen, dann erst in DOM gewandelt und
weiter extrahiert/manipuliert
• Mit Query Rewrite wird indizierter Zugriff auf
das relationale DB-Modell möglich
Bsp. Query Rewrite
CREATE VIEW mitarbeiter_liste AS
SELECT
XMLElement("FILIALE", XMLAttributes(f.name AS "name"),
XMLElement("ANGESTELLTE",
XMLForest(f.ort AS "EINSATZORT"),
(SELECT XMLAgg(XMLElement("ANGESTELLTER",
XMLAttributes(m.name AS "name")))
FROM mitarbeiter m
WHERE m.filNo = f.filNo
)
)
) report_xml
FROM filiale f
<FILIALE name="Kundencenter">
<ANGESTELLTE>
<EINSATZORT>Koeln</EINSATZORT>
<ANGESTELLTER name="Fox Mulder"/>
<ANGESTELLTER name="Dana Scully"/>
</ANGESTELLTE>
</FILIALE>
<FILIALE name="Verwaltung">
<ANGESTELLTE>
<EINSATZORT>Bonn</EINSATZORT>
<ANGESTELLTER name="Olivia Dunham"/>
<ANGESTELLTER name="Walter Bishop"/>
</ANGESTELLTE>
</FILIALE>
SELECT *
FROM
mitarbeiter_liste
WHERE existsNode(report_xml,
'//FILIALE/ANGESTELLTE/ANGESTELLTER[@name="Walter Bishop"]') = 1
SELECT *
FROM
mitarbeiter_liste WHERE
mitarbeiter.name = ‘Walter Bishop‘
Oracle Advanced Queues (AQ)
•
•
•
•
FIFO: first in first out
Sender macht enqeue
Empfänger macht dequeue
Oracle stellt sicher, dass Messages nicht
verlorengehen durch:
– Persistenz
– Transaktionshandling
Advanced Queue
ORACLE AQ
enqueue
Diverse Schnittstellen:
• PL/SQL
• VB (Oracle Objects for OLE)
• Java (oracle.AQ, oracle.jms)
• HTTP, HTTPS, SMTP
…
dequeue
Features wie:
• Exception handling
• Rules
• Transformation
• Statistic Views
AQ: Point to Point
ORACLE AQ
Sender
enqueue
dequeue
Consumer
Publish-Subscribe
Sender 1
Sender n
pu
bli
sh
lish
b
pu
ORACLE AQ
be
i
r
sc
b
su
sub
sc
ribe
Consumer 1
Consumer n
Package DBMS_AQADM
• Administrieren von AQs
• Anlegen / Entfernen von Queues und Queue
Tables
• Starten / Stoppen von Queue
• Festlegen der Prioritätssteuerung
AQ: Codebeispiel
-- Definition des Payload-Typs
CREATE OR REPLACE
TYPE typ_my_aq_message AS OBJECT(message XMLTYPE)
-- Erstellen der Queue-Table
EXECUTE DBMS_AQADM.CREATE_QUEUE_TABLE(
QUEUE_TABLE => 'QT_MY_QUEUE_1',
QUEUE_PAYLOAD_TYPE=> 'typ_my_aq_message');
-- Erstellen der Queue
EXECUTE DBMS_AQADM.CREATE_QUEUE (
QUEUE_NAME=>'QU_MY_QUEUE_1',
QUEUE_TABLE=>'QT_MY_QUEUE_1');
-- Starten/Stoppen der Queue
EXECUTE DBMS_AQADM.START_QUEUE(
QUEUE_NAME=>'QU_MY_QUEUE_1');
Package DBMS_AQ
• PL/SQL Schnittstelle zu AQ
• Enqueue und dequeue von Messages
• Exception Handling
Codebeispiel Enqueue
DECLARE
v_myXmlString
xml_message
VARCHAR2(1000);
XMLTYPE;
mymessage
TYP_MY_AQ_MESSAGE;
message_properties
dbms_aq.message_properties_t;
enqueue_options
dbms_aq.enqueue_options_t;
msgid
RAW(16);
BEGIN
v_myXmlString := '
<MyMessage>
<MyText>This is my Data</MyText>
</MyMessage>';
xml_message := xmltype(v_myXmlString);
mymessage := TYP_MY_AQ_MESSAGE(NULL);
mymessage.message := xml_message.getClobVal();
dbms_aq.enqueue(
queue_name
message_properties
enqueue_options
payload
msgid
END;
=>
=>
=>
=>
=>
'QU_MY_QUEUE_1',
message_properties,
enqueue_options,
mymessage,
msgid);
Codebeispiel Dequeue
DECLARE
v_myXmlString
message_xml
VARCHAR2(1000);
XMLTYPE;
mymessage
TYP_MY_AQ_MESSAGE;
message_properties
dbms_aq.message_properties_t;
dequeue_options
dbms_aq.dequeue_options_t;
msgid
RAW(16);
BEGIN
mymessage := TYP_MY_AQ_MESSAGE(NULL);
msgid := NULL;
message_xml := NULL;
--vaqDequeueOpt.wait := DBMS_AQ.FOREVER); --wartet
dequeue_options.wait := (10); --gibt nach 10 sec auf
dbms_aq.dequeue(
queue_name
message_properties
dequeue_options
payload
msgid
=>
=>
=>
=>
=>
'QU_MY_QUEUE_1',
message_properties,
dequeue_options,
mymessage,
msgid);
message_xml := mymessage.message;
v_myXmlString := message_xml.getStringVal();
dbms_output.put_line (substr(v_myXmlString, 1, 256));
END;
Dequeue Exception Handling
DECLARE
MyDequeueNotEnabled EXCEPTION;
MyDequeueTimout
EXCEPTION;
PRAGMA EXCEPTION_INIT(MyDequeueNotEnabled, -25226); -- Code ist
festgelegt
PRAGMA EXCEPTION_INIT(MyDequeueTimout, -25228);
-- Code ist
festgelegt
...
BEGIN
...
dequeue...
...
EXCEPTION
WHEN MyDequeueTimout THEN
dbms_output.put_line('Zu lange auf Queue gewartet');
WHEN MyDequeueNotEnabled THEN
dbms_output.put_line('Queue ist nicht gestartet');
END;
AQ: Publish Subscribe Beispiel Anlegen
-- Erstellen der Queue-Table
EXECUTE DBMS_AQADM.CREATE_QUEUE_TABLE(
QUEUE_TABLE => 'QT_MY_TOPIC_1',
QUEUE_PAYLOAD_TYPE=> ‘RAW‚
multiple_consumers => TRUE);
-- Erstellen der Queue
EXECUTE DBMS_AQADM.CREATE_QUEUE (
QUEUE_NAME=>'QU_MY_TOPIC_1',
QUEUE_TABLE=>'QT_MY_TOPIC_1');
-- Starten/Stoppen der Queue
EXECUTE DBMS_AQADM.START_QUEUE(
QUEUE_NAME=>'QU_MY_TOPIC_1');
AQ: Publish Subscribe Beispiel Subscriber
-- Definition der Subscriber
DECLARE
subscriber sys.aq$_agent;
BEGIN
subscriber := sys.aq$_agent(
'SUBSCRIBER1',
'QU_MY_TOPIC_1',
null);
dbms_aqadm.add_subscriber(
queue_name
=> 'QU_MY_TOPIC_1',
subscriber
=> subscriber,
delivery_mode => dbms_aqadm.buffered);
END;
DECLARE
subscriber sys.aq$_agent;
BEGIN
subscriber := sys.aq$_agent(
'SUBSCRIBER2',
'QU_MY_TOPIC_1',
null);
dbms_aqadm.add_subscriber(
queue_name
=> 'QU_MY_TOPIC_1',
subscriber
=> subscriber,
delivery_mode => dbms_aqadm.buffered);
END;
AQ: Publish Subscribe Beispiel Enqueue
CREATE OR REPLACE PROCEDURE do_enqueue(p_hexamsg varchar2) IS
enqueue_options
DBMS_AQ.enqueue_options_t;
message_properties DBMS_AQ.message_properties_t;
recipients
DBMS_AQ.aq$_recipient_list_t;
message_handle
RAW(16);
message
RAW(10);
BEGIN
message := hextoraw(p_hexamsg);
recipients(1) := sys.aq$_agent('SUBSCRIBER1', 'QU_MY_TOPIC_1', NULL);
recipients(2) := sys.aq$_agent('SUBSCRIBER2', 'QU_MY_TOPIC_1', NULL);
message_properties.recipient_list := recipients;
enqueue_options.delivery_mode := dbms_aq.PERSISTENT;
dbms_aq.enqueue(
queue_name
enqueue_options
message_properties
payload
msgid
COMMIT;
END;
=>
=>
=>
=>
=>
'QU_MY_TOPIC_1',
enqueue_options,
message_properties,
message,
message_handle);
AQ: Publish Subscribe Beispiel Dequeue
CREATE OR REPLACE PROCEDURE do_dequeue(p_subscriber varchar2) IS
dequeue_options
dbms_aq.dequeue_options_t;
message_properties
dbms_aq.message_properties_t;
message_handle
RAW(16);
message
RAW(10);
MyDequeueTimout
EXCEPTION;
PRAGMA EXCEPTION_INIT(MyDequeueTimout, -25228);
BEGIN
dequeue_options.wait
:= dbms_aq.no_wait;
dequeue_options.consumer_name := p_subscriber;
dequeue_options.navigation
:= dbms_aq.first_message;
dequeue_options.delivery_mode := dbms_aq.PERSISTENT;
dbms_aq.dequeue(
queue_name
=> 'QU_MY_TOPIC_1',
dequeue_options
=> dequeue_options,
message_properties => message_properties,
payload
=> message,
msgid
=> message_handle);
dbms_output.put_line('Message: '|| hextoraw(message) );
EXCEPTION WHEN MyDequeueTimout THEN
dbms_output.put_line('Queue empty');
COMMIT;
END;
AQ: Publish Subscribe Beispiel Verwendung
exec do_enqueue('1');
exec do_enqueue('2');
exec do_enqueue('3');
exec
exec
exec
exec
exec
exec
exec
exec
do_dequeue('SUBSCRIBER1');
do_dequeue('SUBSCRIBER1');
do_dequeue('SUBSCRIBER1');
do_dequeue('SUBSCRIBER1');
do_dequeue('SUBSCRIBER2');
do_dequeue('SUBSCRIBER2');
do_dequeue('SUBSCRIBER2');
do_dequeue('SUBSCRIBER2');
->
->
->
->
->
->
->
->
“1“
“2“
“3“
“Queue empty“
“1“
“2“
“3“
“Queue empty“
Kontakt
telexiom AG
Spichernstr. 6 B
50672 Köln
www.telexiom.de
www.health-care24.de
facebook.com/telexiom
Tel. 0221 888840-0
Fax. 0221 888840-40
[email protected]
xing.com
linkedin.com
Herunterladen