Ki jan ak poukisa nou te ekri yon gwo chaj évolutive sèvis pou 1C: Enterprise: Java, PostgreSQL, Hazelcast

Nan atik sa a nou pral pale sou ki jan ak poukisa nou devlope Sistèm entèraksyon – yon mekanis ki transfere enfòmasyon ant aplikasyon kliyan yo ak 1C:Enterprise sèvè - soti nan mete yon travay nan panse nan achitekti yo ak detay aplikasyon an.

Sistèm Entèaksyon an (ki refere yo kòm SV) se yon sistèm mesaj distribye ki toleran fay ak livrezon garanti. SV fèt kòm yon sèvis wo-chaj ak gwo évolutivité, ki disponib tou de kòm yon sèvis sou entènèt (bay pa 1C) ak kòm yon pwodwi an mas ki pwodui ki ka deplwaye sou enstalasyon sèvè pwòp ou yo.

SV itilize depo distribiye hazelcast ak motè rechèch Elasticsearch. Nou pral pale tou sou Java ak ki jan nou echèl orizontal PostgreSQL.
Ki jan ak poukisa nou te ekri yon gwo chaj évolutive sèvis pou 1C: Enterprise: Java, PostgreSQL, Hazelcast

Deklarasyon sou pwoblèm nan

Pou fè li klè poukisa nou te kreye Sistèm Entèraksyon an, mwen pral di w yon ti kras sou fason devlopman nan aplikasyon pou biznis nan 1C travay.

Pou kòmanse, yon ti kras sou nou pou moun ki poko konnen sa nou fè :) N'ap fè platfòm teknoloji 1C:Enterprise. Platfòm nan gen ladan yon zouti devlopman aplikasyon biznis, osi byen ke yon ègzekutabl ki pèmèt aplikasyon biznis yo kouri nan yon anviwònman kwa-platfòm.

Paradig devlopman kliyan-sèvè

Aplikasyon biznis ki te kreye sou 1C:Enterprise opere nan yon twa nivo kliyan-sèvè achitekti "DBMS - sèvè aplikasyon - kliyan". Kòd aplikasyon ekri nan bati nan lang 1C, ka egzekite sou sèvè aplikasyon an oswa sou kliyan an. Tout travay ak objè aplikasyon (anyè, dokiman, elatriye), osi byen ke lekti ak ekri baz done a, fèt sèlman sou sèvè a. Se fonksyonalite fòm ak koòdone kòmand tou aplike sou sèvè a. Kliyan an fè resevwa, ouvri ak montre fòm, "kominike" ak itilizatè a (avètisman, kesyon...), ti kalkil nan fòm ki mande pou yon repons rapid (pa egzanp, miltipliye pri a pa kantite), travay ak dosye lokal yo, travay ak ekipman.

Nan kòd aplikasyon an, tèt pwosedi yo ak fonksyon yo dwe endike klèman ki kote yo pral egzekite kòd la - lè l sèvi avèk direktiv &AtClient / &AtServer (&AtClient / &AtServer nan vèsyon angle lang lan). Devlopè 1C pral kounye a korije m 'pa di ke direktiv yo aktyèlman pi bon, men pou nou sa a pa enpòtan kounye a.

Ou ka rele kòd sèvè nan kòd kliyan, men ou pa ka rele kòd kliyan nan kòd sèvè. Sa a se yon limit fondamantal nou te fè pou yon kantite rezon. An patikilye, paske kòd sèvè yo dwe ekri nan yon fason ke li egzekite menm jan an pa gen pwoblèm kote yo rele li - soti nan kliyan an oswa nan sèvè a. Ak nan ka a nan rele kòd sèvè soti nan yon lòt kòd sèvè, pa gen okenn kliyan kòm sa yo. Epi paske pandan ekzekisyon kòd sèvè a, kliyan ki rele li a te kapab fèmen, sòti aplikasyon an, epi sèvè a pa ta gen okenn moun pou rele ankò.

Ki jan ak poukisa nou te ekri yon gwo chaj évolutive sèvis pou 1C: Enterprise: Java, PostgreSQL, Hazelcast
Kòd ki okipe yon bouton klike sou: rele yon pwosedi sèvè nan men kliyan an ap travay, rele yon pwosedi kliyan soti nan sèvè a pa pral

Sa vle di ke si nou vle voye kèk mesaj soti nan sèvè a nan aplikasyon kliyan an, pou egzanp, ke jenerasyon an nan yon rapò "ki dire lontan" fini epi yo ka wè rapò a, nou pa gen yon metòd konsa. Ou dwe itilize ke trik nouvèl, pou egzanp, detanzantan sondaj sèvè a soti nan kòd kliyan an. Men, apwòch sa a chaje sistèm nan ak apèl nesesè, epi jeneralman pa gade trè elegant.

E i osi annan en bezwen, par egzanp, ler en telefonn i arive SIP- Lè w ap fè yon apèl, notifye aplikasyon kliyan an sou sa pou li ka itilize nimewo moun k ap rele a pou jwenn li nan baz done kontrepati a epi montre enfòmasyon itilizatè a sou kontrepati k ap rele a. Oswa, pou egzanp, lè yon lòd rive nan depo a, notifye aplikasyon kliyan kliyan an sou sa. An jeneral, gen anpil ka kote yon mekanis konsa ta itil.

Pwodiksyon nan tèt li

Kreye yon mekanis mesaj. Vit, fyab, ak livrezon garanti, ak kapasite nan rechèch fleksib pou mesaj. Ki baze sou mekanis lan, aplike yon mesaje (mesaj, apèl videyo) kouri andedan aplikasyon 1C.

Konsepsyon sistèm nan pou li orizontal évolutive. Chaj la ogmante dwe kouvri pa ogmante kantite nœuds.

Aplikasyon

Nou deside pa entegre pati nan sèvè nan SV dirèkteman nan platfòm la 1C: Enterprise, men aplike li kòm yon pwodwi separe, API a ki ka rele nan kòd la nan solisyon aplikasyon 1C. Sa a te fè pou yon kantite rezon, youn nan prensipal la se ke mwen te vle fè li posib pou fè echanj mesaj ant diferan aplikasyon 1C (pa egzanp, ant Jesyon Komès ak Kontablite). Diferan aplikasyon 1C ka kouri sou diferan vèsyon 1C:Enterprise platfòm la, yo ka lokalize sou diferan serveurs, elatriye. Nan kondisyon sa yo, aplikasyon an nan SV kòm yon pwodwi separe ki sitiye "sou bò a" nan enstalasyon 1C se solisyon an pi bon.

Se konsa, nou deside fè SV kòm yon pwodwi separe. Nou rekòmande pou ti konpayi yo sèvi ak sèvè CB ke nou enstale nan nwaj nou an (wss://1cdialog.com) pou evite depans jeneral ki asosye ak enstalasyon lokal ak konfigirasyon sèvè a. Gwo kliyan ka jwenn li rekòmande pou yo enstale pwòp sèvè CB yo nan enstalasyon yo. Nou te itilize yon apwòch menm jan an nan pwodwi nwaj SaaS nou an 1cFresh - li pwodui kòm yon pwodwi an mas pou enstalasyon nan sit kliyan yo, epi li deplwaye tou nan nwaj nou an. https://1cfresh.com/.

Aplikasyon

Pou distribye chaj la ak tolerans fay, nou pral deplwaye pa yon sèl aplikasyon Java, men plizyè, ak yon balanse chaj devan yo. Si ou bezwen transfere yon mesaj soti nan ne nan ne, sèvi ak pibliye / abònman nan Hazelcast.

Kominikasyon ant kliyan an ak sèvè a se atravè websocket. Li byen adapte pou sistèm an tan reyèl.

Kachèt distribiye

Nou te chwazi ant Redis, Hazelcast ak Ehcache. Se 2015. Redis jis lage yon nouvo gwoup (twò nouvo, pè), gen Sentinel ak anpil restriksyon. Ehcache pa konnen ki jan yo rasanble nan yon gwoup (fonksyonalite sa a parèt pita). Nou deside eseye li ak Hazelcast 3.4.
Hazelcast reyini nan yon grap soti nan bwat la. Nan mòd ne sèl, li pa trè itil epi li ka itilize sèlman kòm yon kachèt - li pa konnen ki jan yo jete done sou disk, si ou pèdi ne a sèlman, ou pèdi done yo. Nou deplwaye plizyè Hazelcasts, ant ki nou backup done kritik. Nou pa fè bak kachèt la - nou pa gen pwoblèm li.

Pou nou, Hazelcast se:

  • Depo nan sesyon itilizatè yo. Li pran anpil tan pou ale nan baz done a pou yon sesyon chak fwa, kidonk nou mete tout sesyon yo nan Hazelcast.
  • Cache. Si w ap chèche yon pwofil itilizatè, tcheke kachèt la. Ekri yon nouvo mesaj - mete l nan kachèt la.
  • Sijè pou kominikasyon ant ka aplikasyon yo. Ne a jenere yon evènman epi mete l nan sijè Hazelcast la. Lòt nœuds aplikasyon ki abònman nan sijè sa a resevwa epi trete evènman an.
  • Gwoup kadna. Pou egzanp, nou kreye yon diskisyon lè l sèvi avèk yon kle inik (diskisyon sèl nan baz done a 1C):

conversationKeyChecker.check("БЕНЗОКОЛОНКА");

      doInClusterLock("БЕНЗОКОЛОНКА", () -> {

          conversationKeyChecker.check("БЕНЗОКОЛОНКА");

          createChannel("БЕНЗОКОЛОНКА");
      });

Nou tcheke ke pa gen okenn chanèl. Nou pran seri a, tcheke li ankò, epi kreye li. Si ou pa tcheke seri a apre ou fin pran seri a, Lè sa a, gen yon chans ke yon lòt fil tcheke tou nan moman sa a epi yo pral kounye a eseye kreye menm diskisyon an - men li deja egziste. Ou pa ka bloke lè l sèvi avèk senkronize oswa regilye java Lock. Atravè baz done a - li ralanti, epi li se yon pitye pou baz done a; atravè Hazelcast - se sa ou bezwen.

Chwazi yon DBMS

Nou gen eksperyans vaste ak siksè travay ak PostgreSQL ak kolabore ak devlopè DBMS sa a.

Li pa fasil ak yon gwoup PostgreSQL - gen XL, XC, Citus, men an jeneral sa yo se pa NoSQLs ki echèl soti nan bwat la. Nou pa t konsidere NoSQL kòm depo prensipal la; li te ase ke nou te pran Hazelcast, ki nou pa t 'te travay avèk anvan.

Si ou bezwen echèl yon baz done relasyon, sa vle di sharding. Kòm ou konnen, ak sharding nou divize baz done a an pati separe pou chak nan yo ka mete sou yon sèvè separe.

Premye vèsyon sharding nou an te sipoze abilite pou distribye chak tab aplikasyon nou an atravè diferan sèvè nan diferan pwopòsyon. Gen anpil mesaj sou sèvè A - tanpri, ann deplase yon pati nan tablo sa a nan sèvè B. Desizyon sa a tou senpleman rele sou optimize twò bonè, kidonk nou deside limite tèt nou nan yon apwòch milti-locataire.

Ou ka li sou plizyè lokatè, pou egzanp, sou sit entènèt la Done Citus.

SV gen konsèp aplikasyon ak abònen. Yon aplikasyon se yon enstalasyon espesifik nan yon aplikasyon biznis, tankou ERP oswa Kontablite, ak itilizatè li yo ak done biznis. Yon abònen se yon òganizasyon oswa yon moun sou non aplikasyon an anrejistre nan sèvè SV la. Yon abònen ka gen plizyè aplikasyon anrejistre, ak aplikasyon sa yo ka echanj mesaj youn ak lòt. Abònen an te vin yon lokatè nan sistèm nou an. Mesaj ki soti nan plizyè abonnés ka lokalize nan yon sèl baz done fizik; si nou wè ke yon abònen te kòmanse jenere anpil trafik, nou deplase li nan yon baz done fizik separe (oswa menm yon sèvè baz done separe).

Nou gen yon baz done prensipal kote yo estoke yon tab routage ak enfòmasyon sou kote tout baz done abònen yo.

Ki jan ak poukisa nou te ekri yon gwo chaj évolutive sèvis pou 1C: Enterprise: Java, PostgreSQL, Hazelcast

Pou anpeche baz done prensipal la se yon kou boutèy, nou kenbe tab la routage (ak lòt done ki nesesè souvan) nan yon kachèt.

Si baz done abònen an kòmanse ralanti, nou pral koupe l an patisyon andedan. Sou lòt pwojè nou itilize pg_pathman.

Piske pèdi mesaj itilizatè a pa bon, nou kenbe baz done nou yo ak kopi. Konbinezon an nan kopi synchrone ak asynchrone pèmèt ou asire tèt ou nan ka pèt baz done prensipal la. Pèt mesaj ap fèt sèlman si baz done prensipal la ak kopi synchrone li yo echwe ansanm.

Si yon kopi synchrone pèdi, kopi asynchrone a vin synchrone.
Si baz done prensipal la pèdi, kopi synchrone a vin baz done prensipal la, epi kopi asynchrone a vin tounen yon kopi synchrone.

Elasticsearch pou rechèch

Depi, pami lòt bagay, SV se tou yon mesaje, li mande pou yon rechèch rapid, pratik ak fleksib, pran an kont mòfoloji, lè l sèvi avèk alimèt enpresif. Nou deside pa reenvante volan an epi sèvi ak motè rechèch gratis Elasticsearch, ki te kreye baze sou bibliyotèk la. Lucene. Nou menm tou nou deplwaye Elasticsearch nan yon gwoup (mèt - done - done) pou elimine pwoblèm nan ka ta gen echèk nan aplikasyon nœuds.

Sou github nou jwenn Plugin mòfoloji Ris pou Elasticsearch epi sèvi ak li. Nan endèks Elasticsearch nou sere rasin mo (ki plugin a detèmine) ak N-gram. Kòm itilizatè a antre tèks pou rechèch, nou chèche tèks tape nan mitan N-gram. Lè yo sove nan endèks la, mo "tèks" yo pral divize an N-gram sa yo:

[sa yo, tek, tex, tèks, tèks, ek, ansyen, ext, tèks, ks, kst, ksty, st, sty, ou],

Epi rasin mo "tèks" la pral konsève tou. Apwòch sa a pèmèt ou fè rechèch nan kòmansman an, nan mitan an, ak nan fen mo a.

Foto a gwo

Ki jan ak poukisa nou te ekri yon gwo chaj évolutive sèvis pou 1C: Enterprise: Java, PostgreSQL, Hazelcast
Repete foto a depi nan konmansman an nan atik la, men ak eksplikasyon:

  • Balanse ekspoze sou entènèt la; nou gen nginx, li kapab nenpòt.
  • Enstans aplikasyon Java yo kominike youn ak lòt atravè Hazelcast.
  • Pou travay ak yon priz entènèt nou itilize Netty.
  • Aplikasyon Java a ekri nan Java 8 epi li konsiste de pakèt OSGi. Plan yo gen ladan migrasyon nan Java 10 ak tranzisyon nan modil.

Devlopman ak tès

Nan pwosesis pou devlope ak teste SV a, nou te rankontre yon kantite karakteristik enteresan nan pwodwi nou itilize yo.

Tès chaj ak fwit memwa

Liberasyon chak lage SV enplike tès chaj. Li gen siksè lè:

  • Tès la te travay pandan plizyè jou epi pa te gen okenn echèk sèvis
  • Tan repons pou operasyon kle yo pa t depase yon papòt konfòtab
  • Deteryorasyon pèfòmans konpare ak vèsyon anvan an pa plis pase 10%

Nou ranpli baz done tès la ak done - pou fè sa, nou resevwa enfòmasyon sou abònen ki pi aktif nan sèvè pwodiksyon an, miltipliye nimewo li yo pa 5 (kantite mesaj, diskisyon, itilizatè) epi teste li konsa.

Nou fè tès chaj nan sistèm entèraksyon an nan twa konfigirasyon:

  1. tès estrès
  2. Koneksyon sèlman
  3. Enskripsyon abònen

Pandan tès estrès la, nou lanse plizyè santèn fil, epi yo chaje sistèm nan san yo pa sispann: ekri mesaj, kreye diskisyon, resevwa yon lis mesaj. Nou simulation aksyon itilizatè òdinè (jwenn yon lis mesaj mwen pa li, ekri yon moun) ak solisyon lojisyèl (transmèt yon pake nan yon konfigirasyon diferan, trete yon alèt).

Pou egzanp, sa a se yon pati nan tès la estrès sanble:

  • Itilizatè konekte
    • Mande diskisyon ou pa li
    • 50% chans pou li mesaj
    • 50% chans pou voye tèks
    • Pwochen itilizatè:
      • Gen yon chans 20% pou kreye yon nouvo diskisyon
      • Owaza chwazi nenpòt nan diskisyon li yo
      • Ale anndan
      • Mande mesaj, pwofil itilizatè
      • Kreye senk mesaj ki adrese itilizatè o aza nan diskisyon sa a
      • Kite diskisyon
      • Repete 20 fwa
      • Logs soti, ale tounen nan kòmansman an nan script la

    • Yon chatbot antre nan sistèm nan (imite mesaj ki soti nan kòd aplikasyon an)
      • Gen yon chans 50% pou kreye yon nouvo chanèl pou echanj done (diskisyon espesyal)
      • 50% chans pou yo ekri yon mesaj nan nenpòt nan chanèl ki egziste deja yo

Senaryo "Koneksyon sèlman" te parèt pou yon rezon. Gen yon sitiyasyon: itilizatè yo konekte sistèm lan, men yo poko patisipe. Chak itilizatè limen òdinatè a a 09:00 nan maten, etabli yon koneksyon ak sèvè a epi rete an silans. Mesye sa yo danjere, gen anpil nan yo - pakè yo sèlman yo genyen se PING/PONG, men yo kenbe koneksyon an nan sèvè a (yo pa ka kenbe li - e si gen yon nouvo mesaj). Tès la repwodui yon sitiyasyon kote yon gwo kantite itilizatè sa yo eseye konekte nan sistèm lan nan yon demi èdtan. Li sanble ak yon tès estrès, men konsantre li se jisteman sou premye opinyon sa a - pou pa gen okenn echèk (yon moun pa sèvi ak sistèm nan, epi li deja tonbe - li difisil a panse a yon bagay ki pi mal).

Script enskripsyon abònen an kòmanse depi premye lansman an. Nou te fè yon tès estrès e nou te asire ke sistèm nan pa t ralanti pandan korespondans. Men itilizatè yo te vini ak enskripsyon an te kòmanse echwe akòz yon delè. Lè enskripsyon nou te itilize / dev / o aza, ki gen rapò ak entropi sistèm nan. Sèvè a pa t 'gen tan akimile entropi ase epi lè yo te mande yon nouvo SecureRandom, li te jele pou dè dizèn de segonn. Gen plizyè fason soti nan sitiyasyon sa a, pou egzanp: chanje nan mwens sekirite /dev/urandom, enstale yon tablo espesyal ki jenere entropi, jenere nimewo o aza davans epi estoke yo nan yon pisin. Nou tanporèman fèmen pwoblèm nan ak pisin lan, men depi lè sa a nou te fè yon tès separe pou anrejistre nouvo abonnés.

Nou itilize kòm yon dèlko chaj JMeter. Li pa konnen ki jan yo travay ak websocket; li bezwen yon Plugin. Premye nan rezilta rechèch la pou rechèch "jmeter websocket" yo se: atik ki soti nan BlazeMeter, ki rekòmande Plugin pa Maciej Zaleski.

Se la nou deside kòmanse.

Prèske imedyatman apre yo te kòmanse tès serye, nou te dekouvri ke JMeter te kòmanse koule memwa.

Plugin a se yon gwo istwa separe; ak 176 zetwal, li gen 132 fouchèt sou github. Otè a li menm pa te angaje nan li depi 2015 (nou te pran li an 2015, Lè sa a, li pa t 'leve sispèk), plizyè pwoblèm github konsènan fwit memwa, 7 demann rale ki pa fèmen.
Si ou deside fè tès chaj lè l sèvi avèk plugin sa a, tanpri peye atansyon sou diskisyon sa yo:

  1. Nan yon anviwònman milti-threaded, yo te itilize yon LinkedList regilye, ak rezilta a te NPE nan ègzekutabl. Sa a ka rezoud swa pa chanje nan ConcurrentLinkedDeque oswa pa senkronize blòk. Nou te chwazi premye opsyon pou tèt nou (https://github.com/maciejzaleski/JMeter-WebSocketSampler/issues/43).
  2. Fuit memwa; lè dekonekte, enfòmasyon koneksyon pa efase (https://github.com/maciejzaleski/JMeter-WebSocketSampler/issues/44).
  3. Nan mòd difizyon (lè websocket la pa fèmen nan fen echantiyon an, men yo itilize pita nan plan an), modèl repons pa travay (https://github.com/maciejzaleski/JMeter-WebSocketSampler/issues/19).

Sa a se youn nan moun ki sou github. Sa nou te fè:

  1. Te pran fouchèt Elyran Kogan (@elyrank) - li rezoud pwoblèm 1 ak 3
  2. Rezoud pwoblèm 2
  3. Mizajou jete soti nan 9.2.14 a 9.3.12
  4. Anvlope SimpleDateFormat nan ThreadLocal; SimpleDateFormat pa an sekirite nan fil, sa ki te mennen nan NPE nan ègzekutabl
  5. Fiks yon lòt fuit memwa (koneksyon an te fèmen mal lè dekonekte)

Men, li koule!

Memwa te kòmanse fini pa nan yon jou, men nan de. Pa te gen absoliman okenn tan kite, se konsa nou deside lanse mwens fil, men sou kat ajan. Sa a ta dwe ase pou omwen yon semèn.

De jou pase...

Koulye a, Hazelcast ap kouri soti nan memwa. Jounal yo te montre ke apre yon koup la jou nan tès, Hazelcast te kòmanse plenyen sou yon mank de memwa, epi apre kèk tan grap la tonbe apa, ak nœuds yo kontinye mouri youn pa youn. Nou konekte JVisualVM ak hazelcast epi nou wè yon "saw k ap monte" - li regilyèman rele GC a, men li pa t 'kapab efase memwa a.

Ki jan ak poukisa nou te ekri yon gwo chaj évolutive sèvis pou 1C: Enterprise: Java, PostgreSQL, Hazelcast

Li te tounen soti ke nan hazelcast 3.4, lè w ap efase yon kat / multiMap (map.destroy()), memwa pa konplètman libere:

github.com/hazelcast/hazelcast/issues/6317
github.com/hazelcast/hazelcast/issues/4888

Ensèk la fikse kounye a nan 3.5, men se te yon pwoblèm nan lè sa a. Nou kreye nouvo multiMaps ak non dinamik epi efase yo dapre lojik nou an. Kòd la te sanble yon bagay tankou sa a:

public void join(Authentication auth, String sub) {
    MultiMap<UUID, Authentication> sessions = instance.getMultiMap(sub);
    sessions.put(auth.getUserId(), auth);
}

public void leave(Authentication auth, String sub) {
    MultiMap<UUID, Authentication> sessions = instance.getMultiMap(sub);
    sessions.remove(auth.getUserId(), auth);

    if (sessions.size() == 0) {
        sessions.destroy();
    }
}

Rele:

service.join(auth1, "НОВЫЕ_СООБЩЕНИЯ_В_ОБСУЖДЕНИИ_UUID1");
service.join(auth2, "НОВЫЕ_СООБЩЕНИЯ_В_ОБСУЖДЕНИИ_UUID1");

multiMap te kreye pou chak abònman epi efase lè li pa t nesesè. Nou te deside ke nou ta kòmanse Map , kle a pral non abònman an, ak valè yo pral idantifyan sesyon (ki soti nan ki ou ka Lè sa a, jwenn idantifyan itilizatè, si sa nesesè).

public void join(Authentication auth, String sub) {
    addValueToMap(sub, auth.getSessionId());
}

public void leave(Authentication auth, String sub) { 
    removeValueFromMap(sub, auth.getSessionId());
}

Tablo yo amelyore.

Ki jan ak poukisa nou te ekri yon gwo chaj évolutive sèvis pou 1C: Enterprise: Java, PostgreSQL, Hazelcast

Ki lòt bagay nou te aprann sou tès chaj?

  1. JSR223 bezwen ekri nan groovy epi enkli kachèt konpilasyon - li pi vit. Link.
  2. Grafik Jmeter-Plugins yo pi fasil pou konprann pase graf estanda yo. Link.

Konsènan eksperyans nou ak Hazelcast

Hazelcast se te yon nouvo pwodwi pou nou, nou te kòmanse travay avèk li soti nan vèsyon 3.4.1, kounye a sèvè pwodiksyon nou an ap kouri vèsyon 3.9.2 (nan moman sa a nan ekri, vèsyon an dènye nan Hazelcast se 3.10).

jenerasyon ID

Nou te kòmanse ak idantifyan nonb antye relatif. Ann imajine ke nou bezwen yon lòt Long pou yon nouvo antite. Sekans nan baz done a pa apwopriye, tab yo patisipe nan sharding - li sanble ke gen yon mesaj ID = 1 nan DB1 ak yon mesaj ID = 1 nan DB2, ou pa ka mete ID sa a nan Elasticsearch, ni nan Hazelcast. , men bagay ki pi mal la se si ou vle konbine done ki soti nan de baz done nan yon sèl (pa egzanp, deside ke yon baz done se ase pou abonnés sa yo). Ou ka ajoute plizyè AtomicLongs nan Hazelcast epi kenbe kontwa a la, Lè sa a, pèfòmans nan jwenn yon nouvo ID se incrementAndGet plis tan pou yon demann nan Hazelcast. Men, Hazelcast gen yon bagay ki pi optimal - FlakeIdGenerator. Lè w kontakte chak kliyan, yo ba yo yon seri ID, pou egzanp, premye a - soti nan 1 a 10, dezyèm lan - soti nan 000 a 10, ak sou sa. Koulye a, kliyan an ka bay nouvo idantifyan poukont li jiskaske seri a bay li fini. Li travay byen vit, men lè ou rekòmanse aplikasyon an (ak kliyan Hazelcast la), yon nouvo sekans kòmanse - kidonk sote yo, elatriye. Anplis de sa, devlopè pa reyèlman konprann poukisa ID yo se nonb antye relatif, men yo tèlman konsistan. Nou te peze tout bagay ak chanje nan UUIDs.

By wout la, pou moun ki vle fè tankou Twitter, gen tankou yon bibliyotèk Snowcast - sa a se yon aplikasyon nan Snowflake sou tèt Hazelcast. Ou ka wè li isit la:

github.com/noctarius/snowcast
github.com/twitter/snowflake

Men, nou pa te rive nan li ankò.

TransactionalMap.replace

Yon lòt sipriz: TransactionalMap.replace pa travay. Men yon tès:

@Test
public void replaceInMap_putsAndGetsInsideTransaction() {

    hazelcastInstance.executeTransaction(context -> {
        HazelcastTransactionContextHolder.setContext(context);
        try {
            context.getMap("map").put("key", "oldValue");
            context.getMap("map").replace("key", "oldValue", "newValue");
            
            String value = (String) context.getMap("map").get("key");
            assertEquals("newValue", value);

            return null;
        } finally {
            HazelcastTransactionContextHolder.clearContext();
        }        
    });
}

Expected : newValue
Actual : oldValue

Mwen te oblije ekri pwòp ranplase mwen lè l sèvi avèk getForUpdate:

protected <K,V> boolean replaceInMap(String mapName, K key, V oldValue, V newValue) {
    TransactionalTaskContext context = HazelcastTransactionContextHolder.getContext();
    if (context != null) {
        log.trace("[CACHE] Replacing value in a transactional map");
        TransactionalMap<K, V> map = context.getMap(mapName);
        V value = map.getForUpdate(key);
        if (oldValue.equals(value)) {
            map.put(key, newValue);
            return true;
        }

        return false;
    }
    log.trace("[CACHE] Replacing value in a not transactional map");
    IMap<K, V> map = hazelcastInstance.getMap(mapName);
    return map.replace(key, oldValue, newValue);
}

Teste pa sèlman estrikti done regilye, men tou vèsyon tranzaksyon yo. Sa rive IMap travay, men TransactionalMap pa egziste ankò.

Mete yon nouvo JAR san D'

Premyèman, nou deside anrejistre objè nan klas nou yo nan Hazelcast. Pou egzanp, nou gen yon klas Aplikasyon, nou vle sove epi li li. Sove:

IMap<UUID, Application> map = hazelcastInstance.getMap("application");
map.set(id, application);

Nou li:

IMap<UUID, Application> map = hazelcastInstance.getMap("application");
return map.get(id);

Tout bagay ap travay. Lè sa a, nou deside bati yon endèks nan Hazelcast pou fè rechèch pa:

map.addIndex("subscriberId", false);

Epi lè yo ekri yon nouvo antite, yo te kòmanse resevwa ClassNotFoundException. Hazelcast te eseye ajoute nan endèks la, men pa t 'konnen anyen sou klas nou an epi li te vle yon JAR ak klas sa a yo dwe apwovizyone li. Nou te fè jis sa, tout bagay te travay, men yon nouvo pwoblèm parèt: ki jan yo mete ajou JAR la san yo pa konplètman sispann gwoup la? Hazelcast pa ranmase nouvo JAR la pandan yon aktyalizasyon nœud pa nœud. Nan pwen sa a nou te deside ke nou te kapab viv san rechèch endèks. Apre yo tout, si ou itilize Hazelcast kòm yon magazen kle-valè, Lè sa a, tout bagay ap travay? Pa vrèman. Isit la ankò konpòtman IMap ak TransactionalMap diferan. Kote IMap pa pran swen, TransactionalMap voye yon erè.

IMap. Nou ekri 5000 objè, li yo. Tout bagay espere.

@Test
void get5000() {
    IMap<UUID, Application> map = hazelcastInstance.getMap("application");
    UUID subscriberId = UUID.randomUUID();

    for (int i = 0; i < 5000; i++) {
        UUID id = UUID.randomUUID();
        String title = RandomStringUtils.random(5);
        Application application = new Application(id, title, subscriberId);
        
        map.set(id, application);
        Application retrieved = map.get(id);
        assertEquals(id, retrieved.getId());
    }
}

Men, li pa travay nan yon tranzaksyon, nou jwenn yon ClassNotFoundException:

@Test
void get_transaction() {
    IMap<UUID, Application> map = hazelcastInstance.getMap("application_t");
    UUID subscriberId = UUID.randomUUID();
    UUID id = UUID.randomUUID();

    Application application = new Application(id, "qwer", subscriberId);
    map.set(id, application);
    
    Application retrievedOutside = map.get(id);
    assertEquals(id, retrievedOutside.getId());

    hazelcastInstance.executeTransaction(context -> {
        HazelcastTransactionContextHolder.setContext(context);
        try {
            TransactionalMap<UUID, Application> transactionalMap = context.getMap("application_t");
            Application retrievedInside = transactionalMap.get(id);

            assertEquals(id, retrievedInside.getId());
            return null;
        } finally {
            HazelcastTransactionContextHolder.clearContext();
        }
    });
}

Nan 3.8, mekanis deplwaman klas itilizatè a te parèt. Ou ka deziyen yon sèl ne mèt epi mete ajou dosye JAR la sou li.

Koulye a, nou te konplètman chanje apwòch nou an: nou seri li tèt nou nan JSON epi sove li nan Hazelcast. Hazelcast pa bezwen konnen estrikti klas nou yo, epi nou ka mete ajou san D'. Se aplikasyon an ki kontwole vèsyon objè domèn. Diferan vèsyon aplikasyon an ka kouri an menm tan, ak yon sitiyasyon posib lè nouvo aplikasyon an ekri objè ak nouvo jaden, men ansyen an poko konnen sou jaden sa yo. Ak an menm tan, nouvo aplikasyon an li objè ekri pa ansyen aplikasyon an ki pa gen nouvo jaden. Nou jere sitiyasyon sa yo nan aplikasyon an, men pou senplisite nou pa chanje oswa efase jaden, nou sèlman elaji klas yo lè nou ajoute nouvo jaden.

Ki jan nou asire pèfòmans segondè

Kat vwayaj nan Hazelcast - bon, de nan baz done a - move

Ale nan kachèt la pou done se toujou pi bon pase ale nan baz done a, men ou pa vle sere dosye ki pa itilize tou. Nou kite desizyon an sou sa yo kachèt jouk dènye etap nan devlopman. Lè nouvo fonksyonalite a kode, nou aktive anrejistreman tout demann nan PostgreSQL (log_min_duration_statement a 0) epi fè tès chaj pou minit 20. Sèvi ak mòso bwa yo kolekte, sèvis piblik tankou pgFouine ak pgBadger ka bati rapò analitik. Nan rapò, nou prensipalman gade pou demann dousman ak souvan. Pou demann dousman, nou bati yon plan ekzekisyon (EXPLAIN) epi evalye si yon demann sa a ka akselere. Demann souvan pou menm done antre yo anfòm byen nan kachèt la. Nou eseye kenbe demann "plat", yon tab pou chak demann.

Operasyon

SV kòm yon sèvis sou entènèt te mete nan operasyon nan sezon prentan 2017, epi kòm yon pwodwi separe, SV te lage nan Novanm 2017 (nan moman sa a nan estati vèsyon beta).

Nan plis pase yon ane nan operasyon, pa te gen okenn pwoblèm grav nan operasyon an nan sèvis la CB sou entènèt. Nou kontwole sèvis la sou entènèt atravè Zabbix, kolekte epi deplwaye soti nan Banbou.

Se distribisyon an sèvè SV apwovizyone nan fòm pakè natif natal: RPM, DEB, MSI. Anplis de sa, pou Windows nou bay yon sèl enstale sou fòm yon sèl EXE ki enstale sèvè a, Hazelcast ak Elasticsearch sou yon sèl machin. Nou te okòmansman refere yo bay vèsyon sa a nan enstalasyon an kòm vèsyon an "demo", men kounye a li te vin klè ke sa a se opsyon deplwaman ki pi popilè.

Sous: www.habr.com

Add nouvo kòmantè