Stabilny ServiceMix 3.3 i smx-arch/maven
Standardowo nie działa. Apache udostępnia artefakty w wersji 3.2.3. Rozwiązanie: użyć rzeczy udostępnianych przez FUSE ESB.-DremoteRepositories=http://repo.fusesource.com/maven2/
protected LinkedBlockingQueue<Connection> pool = new LinkedBlockingQueue<Connection>();
public Connection getConnection() throws SQLException {
long timeToGo = connAcquireTimeout;
long start = System.currentTimeMillis();
Connection conn = null;
int size = poolSize.get();
workerThread.orderConnections(size < poolMinSize ?
poolMinSize - size : 1);
// wkladamy do kolejki roboczej watku
// ilosc polaczen do zrobienia;
// watek w metodzie run wyjmuje Integer-a n,
// robi n polaczen i wklada je do pool-a
while (true) {
try {
conn = pool.poll(timeToGo, TimeUnit.MILLISECONDS);
break;
}
catch (InterruptedException ie) {
if (conn==null) {
long runTime = System.currentTimeMillis()-start;
if (runTime < timeToGo)
timeToGo -= runTime;
}
}}
return conn;
}
Trzeba napisać klasę bazującą na org.apache.servicemix.jbi.audit.AbstractAuditor. Proste i ładne.
<bean name="messageAuditor" class="pl.ivmx.smx.MessageAuditor" method="start" method="stop">
<property name="container" ref="jbi">
</bean>
A może usługi "E" realizować jako jedno Service Assembly (BPEL-SE + DBBC)?
Z zainstalowanego OpenESB potrzebujemy następujące pliki, które umieścimy w katalogu smx3.3/lib/optional: commons-logging-1.1.jar, grizzly-1.0.17.jar, httpbc-ext.jar, javaee.jar, javaws-rt-2.1.2, saaj-impl-1.3.jar, sjsxp-1.0.jar, stax-ex-1.0.jar, streambuffer-0.4.jar.
Do hotdeploy wrzucimy databasebc.jar i httpbc.jar. Demo usługi jest tutaj.
W servicemix.xml dodajemy wpis import resource z classpath o nazwie ds.xml, a tam już definicję DataSource-a:
<bean id="oraEAIDataSource" class="oracle.jdbc.xdriver.OracleDataSource" destroy-method="close">
<property name="driverType" value="thin"/>
<property name="networkProtocol" value="tcp"/>
<property name="serverName" value="localhost"/>
<property name="portNumber" value="1521"/>
<property name="serviceName" value="EAI"/>
<property name="user" value="soatest"/>
<property name="password" value="soatest"/>
<property name="connectionCachingEnabled" value="true"/>
</bean>
Trzeba pamiętać o dodaniu wpisu JNDI w jndi.xml.
Dlaczego DataSource pochodzi z Oracle XDrivera? Bo Sun w OpenESB nie wspiera oryginalnego sterownika oracle-owego i nie zamierza wspierać. Database-bc i komponenty design-time NetBeansa (dawny SOA Pack) napisane są tak celowo, żeby OpenESB nie nadawało się do zastosować profesjonalnych i nie próbowało konkurować z produktem Oracle Fusion. OpenESB ma niby otwarty kod, ale Sun nie chce poprawek przystosowujących darmowe ESB do działania z bazą Oracle.
Dokumentacja DBBC jest tutaj.
Przy większych projektach albo projektach mających GUI będzie problem z czytelnością. Całe szczęście jest funkcjonalność Hide/Show. Czy to pomaga dowiedzieć się co jest grane w obiektowym kodzie? Trochę...
BPEL w OpenESB wcale nie jest taki wolny. Wołanie procedury NOOP w bazie powoduje, że są sprawdzane jej parametry poprzez oracle.jdbc.OracleDatabaseMetaData.getProcedureColumns, a to natomiast tworzy nowego PreparedStatement-a:
SELECT package_name AS procedure_cat, owner AS procedure_schem, object_name AS procedure_name, argument_name AS column_name,
DECODE(position, 0, 5, DECODE(in_out, 'IN', 1, 'OUT', 4, 'IN/OUT', 2, 0)) AS column_type,
DECODE (data_type, 'CHAR', 1, 'VARCHAR2', 12, 'NUMBER', 3, 'LONG', -1,
'DATE', 91, 'RAW', -3, 'LONG RAW', -4, 'TIMESTAMP', 93, 'TIMESTAMP WITH TIME ZONE', -101, 'TIMESTAMP WITH LOCAL TIME ZONE', -102, 'INTERVAL YEAR TO MONTH', -103,
'INTERVAL DAY TO SECOND', -104, 'BINARY_FLOAT', 100, 'BINAvRY_DOUBLE', 101,
1111) AS data_type,
DECODE(data_type, 'OBJECT', type_owner || '.' || type_name, data_type) AS type_name,
DECODE (data_precision, NULL, data_length, data_precision) AS precision,
data_length AS length, data_scale AS scale, 10 AS radix, 1 AS nullable,
NULL AS remarks, default_value AS column_def, NULL as sql_data_type,
NULL AS sql_datetime_sub,
DECODE(data_type, 'CHAR', 32767, 'VARCHAR2', 32767, 'LONG', 32767, 'RAW', 32767, 'LONG RAW', 32767,
NULL) AS char_octet_length, (sequence - 1) AS ordinal_position,
'YES' AS is_nullable, NULL AS specific_name, sequence, overload,
default_value
FROM all_arguments
WHERE owner LIKE :1 ESCAPE '/' AND object_name LIKE :2 ESCAPE '/' AND data_level = 0
AND package_name LIKE :3 ESCAPE '/' "+
ORDER BY procedure_schem, procedure_name, overload, sequence
który jest strasznie wolny. Należy to wsadzić w cache (org.glassfish.openesb.databasebc.JDBCDenormalizer.populateProcedure):
private static HashMap<String,List<ProcMetaData>> procMetaDataCache = new HashMap<String,List<ProcMetaData>>();
String key = "pcatalog="+pcatalog+",pschema="+pschema+",procName="+procName;
List<ProcMetaData> pmdList = procMetaDataCache.get(key);
if (pmdList==null) {
try
{ pmdList = new LinkedList<ProcMetaData>();
rs = dbmeta.getProcedureColumns(pcatalog, pschema, procName, "%");
while (rs.next()) {
String columnName = rs.getString("COLUMN_NAME");
if(columnName.charAt(0) == '@')
columnName = columnName.substring(1);
int targetSqlType = rs.getInt("DATA_TYPE");
int colType = rs.getShort("COLUMN_TYPE");
String type_Name = rs.getString("TYPE_NAME");
short numericScale = rs.getShort("SCALE");
ProcMetaData pmd = new ProcMetaData(columnName, targetSqlType, colType, type_Name, numericScale);
pmdList.add(pmd);
}
procMetaDataCache.put(key, pmdList); // no sync since it would be difficult or could hurt performance
rs.close();
}
Szczytowy zapis na wirtualny dysk VMware z punktu widzenia systemu gościa (W2K8 32-bit) to prawie 5MB/s, średnio poniżej 400KB/s. System działa z wyłączonym swapem i włączonym write cache-em.
A teraz wyniki testu Filesystems SiSoft Sandra:
Buffered read: 562 MB/s
Sequential read: 98.43 MB/s
Random read: 44.83 MB/s
Buffered write: 122.38 MB/s
Sequential write: 90.65 MB/s
Random write: 42.65 MB/s
Random access time: 12.15 ms
Tak więc podsystem dyskowy nie powoduje ograniczenia wydajności.
Średni czas dla usługi PobierzDaneKlienta to 472ms.
Po zmianie dysku na preallocated scsi independent-persistent (plus tuning pliku vmx: MemTrimRate=0, logging="FALSE") polepszyła się wydajność w benchmarku (system wirtualny ma dysk szybszy od pojedyńczego Seagate-a; dwa takie dyski tworzą RAID0, na którym umieszczone są wirtualki), ale nie polepszyły się wyniki BizTalka.
Pod BizTalka można podłączyć YourKit Profilera i wtedy widać, że mamy sporo czekających wątków.
Tutaj widać, że sporo czasu zajmuje SendPort.
A od strony IIS-a wygląda to tak:
A co robi baza?
W czasie testu mamy około 5000 blokad SQL na sekundę i 200 transakcji.
Uproszczona definicja ESB:
Grailsy dodatkowo mają ładny webowy interfejs użytkownika i są tanie (OpenSource + Tomcat + Apache mod_proxy).
A co z szybkością? grails run-app: 29ms, grails prod run-app 25ms.
Na BEA JRockit(R) (build R27.6.5-32_o-121899-1.6.0_14-20091001-2107-windows-ia32, compiled mode) udaje się zejść do 16.5ms pod warunkiem jednej poprawki (Grailsy próbują używać metody, która nie została jeszcze skompilowana do kodu maszynowego - błąd w JVM):
Klasa org.codehaus.groovy.grails.cli.GrailsScriptRunner z grails-bootstrap-1.2.0.jar, metoda private int callPluginOrGrailsScript(String scriptName), workaround:
Project p = antBuilder.getAntProject();Przypominam, że właścicielem Grails-ów jest VMware.
try {
p.setDefaultInputStream(System.in);
}
catch (NoSuchMethodError e) {
try {
Field f = p.getClass().getDeclaredField("defaultInputStream");
f.setAccessible(true);
f.set(p, System.in);
}
catch (Exception ex) {
ex.printStackTrace();
}
}