środa, stycznia 27, 2010

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/

wtorek, stycznia 26, 2010

LinkedBlockingQueue czyli jak napisać pulę JDBC

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;
}

sobota, stycznia 23, 2010

Śledzenie komunikatów w ServiceMix-ie

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)?

Database-bc z OpenESB w ServiceMix-ie

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.

piątek, stycznia 15, 2010

HA-JDBC a Oracle

Fajnie by było mieć magiczny sterownik JDBC, który wie, że są dwa Oracle-a w konfiguracji active-standby. Jeśli połączenie się zepsuje w momencie, gdy aplikacja chce np. wykonać zbuforowany PreparedStatement, sterownik mógłby transparentnie przełączyć się na drugą bazę, tak żeby w żadnym momencie nie pojawił się wyjątek SQLException. Gdy pierwsza baza wróci do życia, sprytny sterownik mógłby zrobić synchronizację i przełączyć się na pierwszą bazę.

HA-JDBC nie obsługuje buforowanych PreparedStatementów - żeby taką funkcjonalność dodać trzeba napisać własnego DataSource-a i wszystko w dół. Drugi problem to problemy w obsłudze synchronizacji Oracle-a (przetwarzanie zbyt wielu obiektów, w tym takich, do których użytkownik nie ma uprawnień oraz nieprawidłowa gramatyka zapytań SQL). Trzeci problem to synchronizacja wewnątrz sterownika. Wątek aktywujący bazy współzawodniczy z wątkiem deaktywującym na tym samym obiekcie Javy, będącym zbiorem obiektów Database - w rezultacie mamy wyjątki przy używaniu iteratora...

Wersja testowa poprawionego HA-JDBC z plikiem konfiguracyjnym, który wyłącza wątek deaktywujący (nie jest potrzebny, bo jest sprytny DataSource) znajduje się tutaj.
HA-JDBC jest na licencji LGPL.

czwartek, stycznia 14, 2010

Oracle XDriver

  • See executed sql commands (also internal PreparedStatements of Oracle driver)
  • Cache statements and database metadata for better performance
  • Easy to switch solution: oracle.jdbc.xdriver.OracleDataSource
  • Lowers GlassFish ESB response time in Oracle operations up to 10x
  • Added metadata operations not supported by Oracle driver
  • DriverManager.getConnection("x:jdbc:oracle:@host:1521:SID")

środa, stycznia 13, 2010

Quick and dirty wrapper generator

niedziela, stycznia 10, 2010

UML by reverse engineering (Borland Together)

 



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ę...

piątek, stycznia 08, 2010

Analiza wydajności OpenESB

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();
}

Teraz mamy 22 ms! Quick and dirty fix is here.

wtorek, stycznia 05, 2010

Monitoring pracy systemu podczas obciążenia BizTalka


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.

poniedziałek, stycznia 04, 2010

Testy wirtualizacji 2.0

Ten sam projekt testowy OpenESB, ale tym razem na najnowszym procesorze AMD: 4 rdzenie 2.6GHz, 95W TDP.



Począwszy od Barcelony 32-bitowe systemy goście działają ze sprzętową wirtualizacją. Na starszych procesorach wirtualizacja realizowana przez procesor była mało wydajna, dlatego VMware włączał ją tylko w przypadku 64-bitowych gości (inaczej nie można by było ich uruchomić), a preferowanym trybem była parawirtualizacja VMI. Linux na AMD-V jest gorszy o 1% od natywnego windowsowego procesu z nałożoną maską afiniczności na jeden rdzeń. RVI (Rapid Virtualization Indexing / nested paging) przynosi niewielki wzrost wydajności w przypadku OpenSolarisa, ale nie w przypadku Linuksa - wygląda na to, że bardzo dobrze zoptymalizowano dla niego tryb AMD-V, a być może nie przyłożono się do RVI. VMware obecnie zapowiada, że w następnych ESX-ach i Linuksie 2.6.37 zrezygnuje z obsługi VMI a skupi się na RVI.

AMD robi świetne procesory. Ciągłe używanie WebService'u przez 10 wątków powodujące pełne obciążenie wszystkich 4 rdzeni, a procesor ma tylko 45 stopni Celsjusza. Intel robi lepsze CPU? No mam wątpliwości...

Offtopic: Grails+JRockit: średni czas 4ms, przy 20 wątkach średni czas 6ms :)
Gdy procesor się nudzi przyjmuje częstotliwość 800MHz na wszystkich rdzeniach i napięcie 1.150V.

Jeszcze jedna informacja: Oracle dobrze radzi sobie z wirtualizacją (albo inaczej: VMware dobrze sobie radzi z Oraclem).

piątek, stycznia 01, 2010

Z Grails-ów też można zrobić ESB

Uproszczona definicja ESB:

  • można podłączyć się do wszystkiego za pomocą wtyczek (grails install-plugin)
  • tą samą usługę możemy wystawić po wielu transportach (WebService: static expose=['cxf'])
  • usługi wewnętrznie wołane są po natywnym protokole szyny (Service.metoda)
  • mamy routing komunikatów (grails install-plugin camel).

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();
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();
}
}
Przypominam, że właścicielem Grails-ów jest VMware.

Update 03.03.2010: mamy naprawione Grailsy na JRockit-cie. Niestety Oracle zamierza skasować JRockita jako produkt i przenieść GC firmy BEA do SUN JVM.