Hello,
Adott a következő stack:
- Apache Wicket 1.5
- Spring 3.0.5
- Hibernate 3.6.10
- Postgres 8.4.11 (8.4-702.jdbc4)
A fejembe vettem, hogy adatbázis független app-ot fogok gyártani.
Kisebb, nagyobb szívások eddig is voltak, de most picit "idegállapotba" kerültem.
3 db entity egy-egy lob mezővel.
A gondom az, hogy nagyobb terhelésnél jdbc driver különféle egzotikus hibaüzenettel borítja meg a tranzakcióimat.
Nagyjából arra utalnak, hogy nem tudja felolvasni a táblában lévő blob-ot. A heap-et megnöveltem, de nem segített. Olvastam pár okosságot, de eddig egy sem jött be illetve egyet még nem próbáltam. (Tegyem a blobot egy külön entity-be, tegyek rá One-To-One-t és akkor majd tényleg működik a FetchType.Lazy).
Az utolsó hibaüzenettel ellentétben a driver _nincs_ autocommit módban.
A lob-okban képek vannak. Egyik sem nagyobb 3Mb-nál.
Ha valakinek lenne ötlete azt szívesen fogadnám!
Köszi!!!
MyClass.entity
.....
@Lob
@Fetch(org.hibernate.annotations.FetchMode.SELECT)
@Type(type="org.hibernate.type.PrimitiveByteArrayBlobType")
@Column(name = "KEP")
private byte[] kep;
....
A hibaüzenetek:
18:16:28,492 WARN JDBCExceptionReporter:233 - SQL Error: 0, SQLState: 42704
18:16:28,493 ERROR JDBCExceptionReporter:234 - ERROR: invalid large-object descriptor: 0
18:15:54,286 WARN DataHelper:181 - IOException occurred closing input stream
16:37:48,043 ERROR HrpCustomDaoImpl:100 - IOException occurred reading a binary value
org.postgresql.util.PSQLException: Large Objects may not be used in auto-commit mode.
- 8860 megtekintés
Hozzászólások
"nagyobb terhelésnél" nem biztos, hogy jo dolog azokat a 3mb-s kepeket meg egy rdbms+jvm-en is atrangatni fajlrendszer+http frontend mellett...
----------------------
"ONE OF THESE DAYS I'M GOING TO CUT YOU INTO LITTLE PIECES!!!$E$%#$#%^*^"
- A hozzászóláshoz be kell jelentkezni
A képeket szeretném adatbázisban tárolni. Tőlem lehet lassú is, de ilyen hibákat ne produkáljon :(.
- A hozzászóláshoz be kell jelentkezni
Miert szeretned?
--
Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal
- A hozzászóláshoz be kell jelentkezni
Nos. A rendszer ezen része már (majdnem) készen van. Három táblám van, ahol lob-ot használok. Személyes adatok (képpel), Hírek (rich text). Fájlok. Nem szerettem volna még könyvtárstruktúra kialakításával foglalkozni az app szerver oldalon.
Az adatok egy részét (személyes adatol) apache cxf-el szinkronizálom egy másik rendszerrel. Teljesen jól működik a képek átvitele. Az adatbázisokat egyben elmentve nem kell külön a képek mentésével is foglalkozni.
Tudom, hogy sosem lesz olyan gyors, mint fs-ből. A kérdés az, hogy rossz e a megközelítés (ember még nem kezelt sosem így képeket a fenti stack-el) vagy van megoldható így csak én nem jöttem rá hogyan.
A 3Mb/képet a maximumnak írtam tippre. De mondjuk egy 20 mondatos cikk 1 képpel biztosan nincs ennyi.
A "nagy terhelés" már néhány száz rekord insertálása közbeni használatot jelenti.
- A hozzászóláshoz be kell jelentkezni
Hat, hallottam mar, hogy valaki PDF-eket tarolt DB-ben, konkretan CV-ket, szoval nem teljesen elrugaszkodott az otlet. De az is igaz, hogy az nem Java/JDBC volt. A konkret hibara nincs tipp.
--
Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal
- A hozzászóláshoz be kell jelentkezni
Evvel most futok egy kört. http://vwjunks.blogspot.hu/2009/12/jpa-hibernate-and-lazy-loading-of-lo…
Ha nem, akkor kirakom külön entity-be. Ha az sem akkor nem tudom.
- A hozzászóláshoz be kell jelentkezni
"sosem lesz olyan gyors, mint fs-ből" - és most nagyon finoman fogalmaztál... Persze ha redis/memcached is kerül mellé, akkor azért lehet gyors is :-D
- A hozzászóláshoz be kell jelentkezni
Tegnap éjszaka óta a következők történtek:
- Upgrade hibernate 4.1.3-ra illetve spring 3.1.1-re
- Lezáratlan tranzakciók lezárása a bo-kban, kivétel esetén rollback stb.
- Postgres JDBC csere (nem segített, 4-5 hit/sec-nél már kivételt dobott.)
- Az összes lob mező átállítása Fetchtype.Lazy-re
- rdbms csere oracle xe-re
Ez részben segített. Most "csak" ilyet dob, ha terhelem, a lob olvasással nincs probléma.
16:15:34,688 ERROR DefaultExceptionMapper:105 - Connection lost, give up responding.
org.apache.wicket.protocol.http.servlet.ResponseIOException: org.mortbay.jetty.EofException
at org.apache.wicket.protocol.http.servlet.ServletWebResponse.write(ServletWebResponse.java:123)
at org.apache.wicket.protocol.http.HeaderBufferingWebResponse.write(HeaderBufferingWebResponse.java:181)
at org.apache.wicket.request.resource.PackageResource$1.writeData(PackageResource.java:287)
at org.apache.wicket.request.resource.AbstractResource.respond(AbstractResource.java:497)
at org.apache.wicket.request.handler.resource.ResourceRequestHandler.respond(ResourceRequestHandler.java:74)
at org.apache.wicket.request.handler.resource.ResourceReferenceRequestHandler.respond(ResourceReferenceRequestHandler.java:105)
at org.apache.wicket.request.cycle.RequestCycle$HandlerExecutor.respond(RequestCycle.java:784)
at org.apache.wicket.request.RequestHandlerStack.execute(RequestHandlerStack.java:64)
at org.apache.wicket.request.cycle.RequestCycle.execute(RequestCycle.java:255)
at org.apache.wicket.request.cycle.RequestCycle.processRequest(RequestCycle.java:212)
at org.apache.wicket.request.cycle.RequestCycle.processRequestAndDetach(RequestCycle.java:283)
at org.apache.wicket.protocol.http.WicketFilter.processRequest(WicketFilter.java:188)
at org.apache.wicket.protocol.http.WicketFilter.doFilter(WicketFilter.java:244)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:322)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:116)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:146)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilter(BasicAuthenticationFilter.java:150)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter.doFilter(DefaultLoginPageGeneratingFilter.java:91)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:182)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:184)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:155)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388)
at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:440)
at org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:230)
at org.mortbay.jetty.handler.HandlerCollection.handle(HandlerCollection.java:114)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.Server.handle(Server.java:326)
at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:926)
at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:549)
at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:212)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:410)
at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)
Caused by: org.mortbay.jetty.EofException
at org.mortbay.jetty.HttpGenerator.flush(HttpGenerator.java:789)
at org.mortbay.jetty.AbstractGenerator$Output.blockForOutput(AbstractGenerator.java:550)
at org.mortbay.jetty.AbstractGenerator$Output.flush(AbstractGenerator.java:571)
at org.mortbay.jetty.HttpConnection$Output.flush(HttpConnection.java:1010)
at org.mortbay.jetty.AbstractGenerator$Output.write(AbstractGenerator.java:650)
at org.mortbay.jetty.AbstractGenerator$Output.write(AbstractGenerator.java:590)
at org.apache.wicket.protocol.http.servlet.ServletWebResponse.write(ServletWebResponse.java:119)
... 60 more
Caused by: java.io.IOException: A felépített kapcsolatot az állomás szoftvere megszakította
at sun.nio.ch.SocketDispatcher.write0(Native Method)
at sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:33)
at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:69)
at sun.nio.ch.IOUtil.write(IOUtil.java:26)
at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:334)
at org.mortbay.io.nio.ChannelEndPoint.flush(ChannelEndPoint.java:179)
at org.mortbay.io.nio.SelectChannelEndPoint.flush(SelectChannelEndPoint.java:221)
at org.mortbay.jetty.HttpGenerator.flush(HttpGenerator.java:723)
... 66 more
- A hozzászóláshoz be kell jelentkezni
Te... ennyi ido alatt mar atirtad volna fajlrendszeresre...
--
Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal
- A hozzászóláshoz be kell jelentkezni
Így igaz. Egy állat vagyok. Nem bírom elengedni a problémát, mivel tudom, h működnie kellene.
Nem tudom ezt minek hívják, de néha kórósnak érzem egy idő után..
- A hozzászóláshoz be kell jelentkezni
Azért az adatbázisban tárolásnak van egy csomó előnye, http clusternél nem kell osztott filerendszerrel foglalkoznod, a modern adatbáziskezelők viszonylag jol kezelik Blob-okat. A hiba szerintem nem a blobkezelésnél van, hanem valami nincs jól tunningolva, conn pool adatbázis max connection, stb. Egyébként ha gyorsan akarod kezelni a jdbc-n keresztül is tudsz stream-eltem írni olvasni. A JPA kényelmes, de nem mindig gyors.
- A hozzászóláshoz be kell jelentkezni
Egy NFS-sel mi a probléma? Normális teljesítményű storage, aztán hajrá. Egyébként meg a fájlok tárolását is szét lehet dobni n darab hostra (egy fájl csak egy hoston van meg), és alkalmazásból, vagy akár valamilyen terhelésmegosztóval odadobni a kérést, ahol a fájl ténylegesen található.
- A hozzászóláshoz be kell jelentkezni
Persze meg lehet oldani úgy is, bár ha már professionális megoldás kell akkor rendes content manager software-t kell használni, pl Alfesco, vagy IBM ContentMangere amikkel én találkoztam mind kombinált db +fs-t használnak. Ezek a megoldások clusterezhetőek, és jól skálazódnak, kereshetőek meatadatok alapján stb.
- A hozzászóláshoz be kell jelentkezni
Mondjuk úgy, hogy láttam már ilyesmit - sacc/kb. 70 millió képpel :)
- A hozzászóláshoz be kell jelentkezni
Ja az más ha gyakorlatban működik akkor jó. Ahogy látom az informatikában sok jó megoldás van, és akár mind müködhet jól.
- A hozzászóláshoz be kell jelentkezni
Köszöni szépen, jól működik: metaadatok több gépre szétosztott db-ben, a képek meg n darab képkiszolgálón helyi diszkeken. Plusz memcached, hogy a gyakran használt adatok gyorsan elérhetőek legyenek.
- A hozzászóláshoz be kell jelentkezni
Már az is érdekes hogy lehetnek lezáratlan tranzakcióid. Nem az lehet, hogy a lezáratlan kapcsolatok megették a conn poolt.
- A hozzászóláshoz be kell jelentkezni
Hibernate+Spring párosnál (Spring-es tranzakció kezelést használva) már találkoztam olyan esettel (igaz two-phase commit-nál), hogy a Hibernate nem zárta le a nyitott connection-öket, és elfogyott a pool.
- A hozzászóláshoz be kell jelentkezni
Ha 4-5 hit/sec-ig tokeletesen mukodik, akkor nincs semmi gond sem a DB-vel, sem az elvvel, "csupan" egy kicsit lassu az overhead miatt. (ahogy fent mar emlitettek)
Az egyetemi DB tanarom emlitette, hogy nagysagrendi sebessegkulonbsegek lehetnek a DB engine-ek kozott. O akarmilyen lassu RDBMS-t tud irni, viszont a cel a masik hatar. Ugy tunik neked mindenkeppen az a celod, hogy nagy legyen az overhead, szoval a kepeidet ne egyszeruen blobokban tarold, hanem xml-be agyazott PDF-be csomagolva, es valahova mindenkepp iktass meg be egy PHP-ban irt Brainfuck interpretert! Igy mar akar 1 hit/sec is tul nagy terhelesse valhat.
--
ezt tényleg ennyire nem értitek? - turdus :)
- A hozzászóláshoz be kell jelentkezni
Attol függ milyen overhead, ha van 200 ms overhead, az a UI-on nem észrevehető. Ilyenkor hogy gyors legyen ez úgy szokták hatékonyan megoldani, hogy csinálnak egy külön megjelenítő servletet, ami streameli a tartalmat közvetlen jdbc streamből, így nincs dupla tárolás a memoriában..
- A hozzászóláshoz be kell jelentkezni
Igen, direkt olyan megoldást választottam, amivel nagy overhead-et lehet elérni :[. Válaszokat keresek a felvázolt problémára. (A tárold fs-ben a képeidet nem válasz, csak javaslat.)
- A hozzászóláshoz be kell jelentkezni
Szerintem ha 3MB-os blobokat rángatsz át az egészen, az már tud performance problémákat okozni.
1. SZVSZ ilyenkor nem biztos, hogy a Hibernate lesz a megfelelő ORM, én megpróblnám mit csinál egy iBatis/MyBatis.
2. 5 TPS-nél (Transactions per sec) 15MB-nyi blob-od lesz másodpercenként, heap, stack, permgen-t növelni, ne legyél szégyenlős, amit oda tudsz neki adni, azt lökd oda neki.
3. Lődd be a connection pool-t. C3P0-t használsz? Lehet érdemes lenne megpróbálni, hogy mi lesz ha lecseréled másra, pl. Apache DBCP egy elég egyszerű megoldás.
4. Próbálj ki más Postgres-hez való JDBC drivereket (if any). Esetleg autocommit-ot.
5. Ha van ThreadPool-od valahol, akkor azzal is lehet megérné kísérletezni.
6. Lehet érdemes kipróbálni, hogy tutod-e növelni a performance-t, ha spring-gel cache-et raksz az enttity-re/blob-ra.
___________________________
http://lorem.hu
Az emberi tudás mindenkié!
- A hozzászóláshoz be kell jelentkezni
Alapvetően egyetértek az előttem szólóval csak kiegészíteném egy két dologgal:
1. Menteni nyugodtan menthetsz JPA-val, de a megjelenítés lehet jdbc stream közvetlenül.
2. VisualVM programmal, és PrintGC paraméterel tudsz gc-teljesítményt nézni.
3. Használj rendes conn poolt, a megfelelő beállításokkal.
4. Nekem még nem volt problémám a Portgres jdbc driverével, mindig jó volt teljesítményben.
5. A threadpoolt, connPoolt szépen együtt kell tuninngolni, sokan beleesnek abba hibába, hogy terhelési teszteknél konfigurációs hibát programhibának néznek. A visualVm-ben jól fogod látni, hol a hiba, megterheled n szálon, és figyeled hol akadnak be az előforrások, ilyenkor érdemes n+1 poolméretet beállítani mindennek.
- A hozzászóláshoz be kell jelentkezni
@ivanov, @szipka: Köszönöm a _konstruktív_ válaszokat. Nyomozok tovább, kipróbálom a javasolt megoldásokat.
- A hozzászóláshoz be kell jelentkezni
Az archívum kedvéért. Nem jdbc, blob kezelés, connection pool satöbbi probléma volt.
Az alábbiak szerint egy
AbstractReadOnlyModel-be ágyaztam bele a ImageResource-t, így az reload esetén nem működött jól.
NonCachingImage nci = new NonCachingImage("kep", new AbstractReadOnlyModel() {
@Override
public Object getObject() {
if (model.getObject() != null) {
if (model.getObject().getKep() != null) {
ImageResource im = new ImageResource(model.getObject().getKep(), "jpg");
ThumbnailImageResource img = new ThumbnailImageResource(im, Integer.valueOf(new ResourceModel("application.thumbnailimagesize").getObject()));
if (img != null) {
return img;
} else {
return "/images/nia.jpg";
}
} else {
return "/images/nia.jpg";
}
}
return "/images/nia.jpg";
}
});
Helyesen:
ImageResource im = null;
if (model != null) {
if (model.getObject() != null) {
if (model.getObject().getKep() != null) {
im = new ImageResource(model.getObject().getKep(), "jpg");
}
}
}
NonCachingImage nci;
if (model != null && im!=null) {
nci = new NonCachingImage("kep",
new ThumbnailImageResource(im, Integer.valueOf(new ResourceModel("application.thumbnailimagesize").getObject())));
} else {
nci = new NonCachingImage("kep", "/images/nia.jpg");
}
Köszönöm mindenkinek még egyszer a segítséget!
- A hozzászóláshoz be kell jelentkezni
Az uj kod azert is jobb, mert kevesebb a return benne...
--
Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal
- A hozzászóláshoz be kell jelentkezni