Бид 1С: Enterprise: Java, PostgreSQL, Hazelcast-д зориулсан өндөр ачаалалтай өргөтгөх боломжтой үйлчилгээг хэрхэн, яагаад бичсэн бэ

Энэ нийтлэлд бид хэрхэн, яагаад хөгжсөн тухай ярих болно Харилцааны систем – Үйлчлүүлэгчийн программууд болон 1C: Enterprise серверүүдийн хооронд мэдээлэл дамжуулах механизм - даалгавар өгөхөөс эхлээд архитектур, хэрэгжилтийн нарийн ширийн зүйлийг бодох хүртэл.

Харилцааны систем (цаашид SV гэх) нь баталгаатай хүргэлттэй, түгээсэн, алдааг тэсвэрлэх чадвартай мессежийн систем юм. SV нь онлайн үйлчилгээ (1С-ээс хангагдсан) болон өөрийн серверийн байгууламжид байршуулах боломжтой бөөнөөр үйлдвэрлэгдсэн бүтээгдэхүүн болгон ашиглах боломжтой, өргөтгөх боломжтой өндөр ачаалалтай үйлчилгээ хэлбэрээр бүтээгдсэн.

SV нь хуваарилагдсан хадгалах санг ашигладаг Хазелкаст болон хайлтын систем Elasticsearch. Бид мөн Java-ийн талаар болон PostgreSQL-г хэвтээ байдлаар хэрхэн масштаблах талаар ярилцах болно.
Бид 1С: Enterprise: Java, PostgreSQL, Hazelcast-д зориулсан өндөр ачаалалтай өргөтгөх боломжтой үйлчилгээг хэрхэн, яагаад бичсэн бэ

Асуудлын тодорхойлолт

Бид яагаад Харилцааны системийг бий болгосноо тодорхой болгохын тулд 1С дахь бизнесийн хэрэглээний программуудыг хэрхэн хөгжүүлэх талаар бага зэрэг хэлье.

Юу хийдгээ мэдэхгүй байгаа хүмүүст зориулж бидний тухай товчхон хэлье :) Бид 1С: Enterprise технологийн платформыг хийж байна. Энэхүү платформ нь бизнесийн хэрэглээний программ хөгжүүлэх хэрэгсэл, түүнчлэн бизнесийн программуудыг платформ хоорондын орчинд ажиллуулах боломжийг олгодог ажиллах цагийг агуулдаг.

Үйлчлүүлэгч-серверийн хөгжлийн парадигм

1С: Enterprise дээр бүтээгдсэн бизнесийн програмууд нь гурван түвшинд ажилладаг үйлчлүүлэгч-сервер архитектур "DBMS - програмын сервер - клиент". Програмын код бичсэн суурилуулсан 1С хэл, програмын сервер эсвэл үйлчлүүлэгч дээр ажиллах боломжтой. Хэрэглээний объект (лавлах, баримт бичиг гэх мэт), мөн мэдээллийн санг унших, бичих зэрэг бүхий л ажил зөвхөн сервер дээр хийгддэг. Маягт болон тушаалын интерфейсийн функцийг сервер дээр хэрэгжүүлдэг. Үйлчлүүлэгч маягт хүлээн авах, нээх, харуулах, хэрэглэгчтэй "харилцах" (сануулга, асуултууд ...), хурдан хариу өгөх шаардлагатай маягтуудын жижиг тооцоолол (жишээлбэл, үнийг тоо хэмжээгээр үржүүлэх), дотоод файлуудтай ажиллах, тоног төхөөрөмжтэй ажиллах.

Хэрэглээний кодын процедур ба функцуудын толгой хэсэгт код хаана хийгдэхийг тодорхой зааж өгөх ёстой - &AtClient / &AtServer удирдамж (&AtClient / &AtServer хэлний англи хувилбар дээр). 1С-ийн хөгжүүлэгчид зааврыг үнэн зөв гэж хэлээд намайг засах болно түүнээс дээш, гэхдээ бидний хувьд энэ нь одоо чухал биш юм.

Та серверийн кодыг үйлчлүүлэгчийн кодоос дуудаж болох боловч серверийн кодоос үйлчлүүлэгчийн код руу залгах боломжгүй. Энэ бол хэд хэдэн шалтгааны улмаас бидний хийсэн үндсэн хязгаарлалт юм. Ялангуяа серверийн код нь үйлчлүүлэгчээс эсвэл серверээс хаана ч дуудагдахаас үл хамааран ижил аргаар ажиллахаар бичигдсэн байх ёстой. Мөн өөр серверийн кодоос серверийн кодыг дуудах тохиолдолд ийм үйлчлүүлэгч байхгүй болно. Учир нь серверийн кодыг ажиллуулах явцад түүнийг дуудсан клиент хаагдаж, програмаас гарах боломжтой бөгөөд серверт залгах хүн байхгүй болно.

Бид 1С: Enterprise: Java, PostgreSQL, Hazelcast-д зориулсан өндөр ачаалалтай өргөтгөх боломжтой үйлчилгээг хэрхэн, яагаад бичсэн бэ
Товчлуур товшихыг зохицуулдаг код: үйлчлүүлэгчээс серверийн процедурыг дуудах нь ажиллах болно, серверээс клиент процедурыг дуудах нь ажиллахгүй.

Энэ нь хэрэв бид серверээс клиент програм руу мессеж илгээхийг хүсвэл, жишээлбэл, "удаан ажиллаж байгаа" тайланг үүсгэж дууссан, тайланг үзэх боломжтой гэсэн мессежийг илгээхийг хүсвэл бидэнд ийм арга байхгүй гэсэн үг юм. Та заль мэх ашиглах хэрэгтэй, жишээлбэл, үйлчлүүлэгчийн кодоос серверээс үе үе санал асуулга авах хэрэгтэй. Гэхдээ энэ арга нь системийг шаардлагагүй дуудлагаар ачаалдаг бөгөөд ерөнхийдөө тийм ч гоёмсог харагддаггүй.

Мөн түүнчлэн, жишээлбэл, утасны дуудлага ирэх үед шаардлагатай байдаг SIP- дуудлага хийхдээ энэ тухай үйлчлүүлэгчийн аппликейшнд мэдэгдээрэй, ингэснээр тэр залгагчийн дугаарыг эсрэг талын мэдээллийн сангаас олж, хэрэглэгчдэд залгаж буй эсрэг талын мэдээллийг харуулах боломжтой. Эсвэл, жишээлбэл, агуулахад захиалга ирэхэд энэ тухай үйлчлүүлэгчийн үйлчлүүлэгчийн өргөдөлд мэдэгдээрэй. Ерөнхийдөө ийм механизм ашигтай байх тохиолдол олон байдаг.

Үйлдвэрлэл өөрөө

Мессежийн механизмыг бий болгох. Хурдан, найдвартай, баталгаатай хүргэлттэй, мессежийг уян хатан хайх чадвартай. Механизм дээр үндэслэн 1С програм дотор ажилладаг мессенжерийг (мессенжер, видео дуудлага) хэрэгжүүл.

Системийг хэвтээ байдлаар өргөжүүлэх боломжтой болгох. Өсөн нэмэгдэж буй ачааллыг зангилааны тоог нэмэгдүүлэх замаар нөхөх ёстой.

Реализация

Бид SV-ийн серверийн хэсгийг 1C: Enterprise платформд шууд нэгтгэхгүй, харин API-ийг 1С програмын шийдлүүдийн кодоос дуудаж болох тусдаа бүтээгдэхүүн болгон хэрэгжүүлэхээр шийдсэн. Үүнийг хэд хэдэн шалтгааны улмаас хийсэн бөгөөд тэдгээрийн гол нь би өөр өөр 1С програмуудын хооронд (жишээлбэл, Худалдааны менежмент ба Нягтлан бодох бүртгэлийн хооронд) мессеж солилцох боломжтой болгохыг хүссэн явдал байв. Өөр өөр 1С програмууд нь 1C: Enterprise платформын өөр өөр хувилбарууд дээр ажиллах боломжтой, өөр сервер дээр байрлах гэх мэт. Ийм нөхцөлд SV-ийг 1С суурилуулалтын "хажуу талд" байрлах тусдаа бүтээгдэхүүн болгон хэрэгжүүлэх нь оновчтой шийдэл юм.

Тиймээс бид SV-г тусдаа бүтээгдэхүүн болгохоор шийдсэн. Бид жижиг компаниудад серверийн дотоод суурилуулалт, тохиргоотой холбоотой нэмэлт зардлаас зайлсхийхийн тулд үүлэн дээрээ суулгасан CB серверийг (wss://1cdialog.com) ашиглахыг зөвлөж байна. Томоохон үйлчлүүлэгчид өөрсдийн CB серверийг өөрийн байгууламжид суулгахыг зөвлөж байна. Бид үүлний SaaS бүтээгдэхүүндээ ижил төстэй аргыг ашигласан 1c Шинэ – энэ нь үйлчлүүлэгчдийн сайтад суурилуулах зорилгоор олноор үйлдвэрлэгдсэн бүтээгдэхүүн бөгөөд мөн манай үүлэн дээр байрлуулсан. https://1cfresh.com/.

Програм

Ачаалал болон эвдрэлийг тэсвэрлэх чадварыг хуваарилахын тулд бид нэг Java програмыг биш, харин хэд хэдэн ачааллын тэнцвэржүүлэгчийг өмнө нь байрлуулна. Хэрэв та зангилаанаас зангилаа руу мессеж дамжуулах шаардлагатай бол Hazelcast-д publish/subscribe ашиглана уу.

Үйлчлүүлэгч болон серверийн хоорондох холбоо нь вэбсокетээр дамждаг. Энэ нь бодит цагийн системд маш тохиромжтой.

Түгээсэн кэш

Бид Redis, Hazelcast, Ehcache хоёрын хооронд сонголт хийсэн. 2015 он боллоо. Редис саяхан шинэ кластер гаргасан (хэтэрхий шинэ, аймшигтай), маш олон хязгаарлалттай Sentinel байдаг. Ehcache нь кластерт хэрхэн угсрахаа мэддэггүй (энэ функц хожим гарч ирсэн). Бид үүнийг Hazelcast 3.4-тэй туршиж үзэхээр шийдсэн.
Hazelcast-ыг хайрцагнаас нь кластер болгон угсардаг. Нэг зангилааны горимд энэ нь тийм ч ашигтай биш бөгөөд зөвхөн кэш болгон ашиглах боломжтой - энэ нь өгөгдлийг диск рүү хэрхэн буулгахаа мэдэхгүй, хэрэв та цорын ганц зангилаа алдвал өгөгдлийг алддаг. Бид хэд хэдэн Hazelcast-уудыг байрлуулж, тэдгээрийн хооронд чухал өгөгдлийг нөөцлдөг. Бид кэшийг нөөцлөхгүй - бид үүнд дургүйцэхгүй.

Бидний хувьд Hazelcast бол:

  • Хэрэглэгчийн сешнүүдийг хадгалах. Мэдээллийн сан руу сесс бүрт очиход их хугацаа шаардагддаг тул бид бүх сессүүдийг Hazelcast-д тавьдаг.
  • Кэш. Хэрэв та хэрэглэгчийн профайл хайж байгаа бол кэшийг шалгана уу. Шинэ мессеж бичсэн - кэшэд оруулна уу.
  • Хэрэглээний тохиолдлуудын хооронд харилцах сэдвүүд. Зангилаа нь үйл явдлыг үүсгэж, Hazelcast сэдэвт байрлуулна. Энэ сэдэвт бүртгүүлсэн бусад програмын зангилаа үйл явдлыг хүлээн авч боловсруулдаг.
  • Кластер түгжээ. Жишээлбэл, бид өвөрмөц түлхүүрийг ашиглан хэлэлцүүлэг үүсгэдэг (1С мэдээллийн сан дахь ганцхан хэлэлцүүлэг):

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

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

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

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

Бид суваг байхгүй эсэхийг шалгасан. Бид цоожыг авч, дахин шалгаж, үүсгэсэн. Хэрэв та түгжээг авсны дараа түгжээг шалгахгүй бол тухайн үед өөр хэлхээ шалгасан байх магадлалтай бөгөөд одоо ижил хэлэлцүүлэг үүсгэхийг оролдох болно - гэхдээ энэ нь аль хэдийн байна. Та синхрончлогдсон эсвэл ердийн java түгжээг ашиглан түгжих боломжгүй. Мэдээллийн сангаар дамжуулан - энэ нь удаан бөгөөд мэдээллийн санд харамсалтай байна; Hazelcast-аар дамжуулан - энэ нь танд хэрэгтэй зүйл юм.

DBMS сонгох

Бид PostgreSQL-тэй ажиллаж, энэхүү DBMS-ийн хөгжүүлэгчидтэй хамтран ажиллаж байсан арвин бөгөөд амжилттай туршлагатай.

PostgreSQL кластертай байх нь тийм ч хялбар биш юм XL, XC, Цитус, гэхдээ ерөнхийдөө эдгээр нь хайрцгаас гарч томордог NoSQL биш юм. Бид NoSQL-ийг үндсэн санах ой гэж үзээгүй бөгөөд өмнө нь ажиллаж байгаагүй Hazelcast-ыг авахад хангалттай.

Хэрэв та харилцааны мэдээллийн санг масштаблах шаардлагатай бол энэ нь гэсэн үг юм хуваах. Та мэдэж байгаагаар, sharding ашиглан бид мэдээллийн санг тус тусад нь хуваадаг бөгөөд ингэснээр тус бүрийг тусдаа сервер дээр байрлуулах боломжтой болно.

Манай sharding-ийн эхний хувилбар нь манай програмын хүснэгт бүрийг өөр өөр серверүүдэд өөр өөр хувь хэмжээгээр хуваарилах чадвартай гэж үзсэн. А сервер дээр маш олон мессежүүд байна - энэ хүснэгтийн хэсгийг В сервер рүү шилжүүлье. Энэ шийдвэр нь дутуу оновчлолын талаар хашгирч байсан тул бид өөрсдийгөө олон түрээслэгчийн арга барилаар хязгаарлахаар шийдсэн.

Та олон түрээслэгчийн тухай, жишээлбэл, вэбсайтаас уншиж болно Citus өгөгдөл.

SV нь программ ба захиалагч гэсэн ойлголттой. Аппликейшн гэдэг нь ERP эсвэл Нягтлан бодох бүртгэл гэх мэт бизнесийн хэрэглээний программуудыг хэрэглэгчид болон бизнесийн өгөгдөлтэй нь тусгайлан суулгах явдал юм. Захиалагч нь SV серверт нэрийн өмнөөс програм бүртгүүлсэн байгууллага эсвэл хувь хүн юм. Захиалагч хэд хэдэн програм бүртгүүлсэн байж болох бөгөөд эдгээр програмууд хоорондоо мессеж солилцох боломжтой. Захиалагч манай системд түрээслэгч болсон. Хэд хэдэн захиалагчдын мессежийг нэг физик мэдээллийн санд байрлуулж болно; Хэрэв бид захиалагч маш их траффик үүсгэж эхэлснийг харвал бид үүнийг тусдаа физик мэдээллийн сан (эсвэл бүр тусдаа мэдээллийн сангийн сервер) рүү шилжүүлдэг.

Бидэнд бүх захиалагч мэдээллийн сангийн байршлын талаарх мэдээлэл бүхий чиглүүлэлтийн хүснэгт хадгалагддаг үндсэн мэдээллийн сан бий.

Бид 1С: Enterprise: Java, PostgreSQL, Hazelcast-д зориулсан өндөр ачаалалтай өргөтгөх боломжтой үйлчилгээг хэрхэн, яагаад бичсэн бэ

Үндсэн мэдээллийн санд саад учруулахгүйн тулд бид чиглүүлэлтийн хүснэгтийг (болон байнга шаардлагатай бусад өгөгдлийг) кэшэд хадгалдаг.

Хэрэв захиалагчийн мэдээллийн сан удааширч эхэлбэл бид үүнийг дотор нь хуваах болно. Бидний ашигладаг бусад төслүүд дээр pg_pathman.

Хэрэглэгчийн мессежийг алдах нь муу учраас бид мэдээллийн санг хуулбарладаг. Синхрон ба асинхрон хуулбаруудын хослол нь үндсэн мэдээллийн сан алдагдсан тохиолдолд өөрийгөө даатгах боломжийг олгодог. Зөвхөн үндсэн мэдээллийн сан болон түүний синхрон хуулбар нэгэн зэрэг бүтэлгүйтсэн тохиолдолд мессеж алдагдах болно.

Хэрэв синхрон хуулбар алдагдсан бол асинхрон хуулбар синхрон болно.
Хэрэв үндсэн мэдээллийн сан алдагдсан бол синхрон хуулбар нь үндсэн мэдээллийн сан болж, асинхрон хуулбар нь синхрон хуулбар болно.

Хайлтын Elasticsearch

Бусад зүйлсийн дотор SV нь мессенжер учраас морфологийг харгалзан хурдан, тохиромжтой, уян хатан хайлтыг нарийн тааруулахгүй байхыг шаарддаг. Бид дугуйг дахин зохион бүтээхгүй байхаар шийдсэн бөгөөд номын санд үндэслэн бүтээсэн Elasticsearch үнэгүй хайлтын системийг ашиглахаар шийдсэн Люкс. Бид мөн Elasticsearch-ийг кластерт (мастер - өгөгдөл - өгөгдөл) байрлуулж, програмын зангилаа бүтэлгүйтсэн тохиолдолд асуудлыг арилгах болно.

Github дээр бид олсон Оросын морфологийн залгаас Elasticsearch-д зориулж, үүнийг ашиглана уу. Elasticsearch индекст бид үгийн язгуур (plugin тодорхойлдог) болон N-граммуудыг хадгалдаг. Хэрэглэгч хайлт хийхийн тулд текст оруулах үед бид бичсэн текстийг N-граммуудын дунд хайдаг. Индекс рүү хадгалах үед "текстүүд" гэсэн үг нь дараах N-граммд хуваагдана.

[тэдгээр, tek, tex, текст, текст, ek, ex, ext, текст, ks, kst, ksty, st, sty, you],

Мөн "текст" гэдэг үгийн үндэс нь хадгалагдах болно. Энэ арга нь үгийн эхэнд, дунд, төгсгөлд хайлт хийх боломжийг олгодог.

Том зураг

Бид 1С: Enterprise: Java, PostgreSQL, Hazelcast-д зориулсан өндөр ачаалалтай өргөтгөх боломжтой үйлчилгээг хэрхэн, яагаад бичсэн бэ
Өгүүллийн эхнээс зургийг давт, гэхдээ тайлбартай:

  • Интернет дээр ил гарсан тэнцвэржүүлэгч; Бидэнд nginx байгаа, энэ нь ямар ч байж болно.
  • Java програмын жишээнүүд хоорондоо Hazelcast-аар холбогддог.
  • Вэб залгууртай ажиллахын тулд бид ашигладаг цэвэр.
  • Java програм нь Java 8 дээр бичигдсэн бөгөөд багцуудаас бүрдэнэ OSGi. Төлөвлөгөөнд Java 10 руу шилжих, модуль руу шилжих зэрэг орно.

Хөгжүүлэлт ба туршилт

SV-г боловсруулж, турших явцад бидний хэрэглэж буй бүтээгдэхүүний хэд хэдэн сонирхолтой шинж чанаруудтай танилцсан.

Ачааллын туршилт, санах ойн алдагдал

SV хувилбар бүрийг гаргахад ачааллын туршилт орно. Энэ нь дараах тохиолдолд амжилттай болно:

  • Туршилт хэд хоног ажилласан бөгөөд үйлчилгээний доголдол гараагүй
  • Гол үйлдлүүдэд хариу өгөх хугацаа нь тав тухтай босгыг давсангүй
  • Өмнөх хувилбартай харьцуулахад гүйцэтгэлийн бууралт 10% -иас ихгүй байна

Бид тестийн мэдээллийн санг өгөгдлөөр дүүргэдэг - үүнийг хийхийн тулд бид үйлдвэрлэлийн серверээс хамгийн идэвхтэй захиалагчийн тухай мэдээллийг хүлээн авч, түүний тоог 5-аар (мессеж, хэлэлцүүлэг, хэрэглэгчдийн тоо) үржүүлж, үүнийг туршиж үздэг.

Бид харилцан үйлчлэлийн системийн ачааллын туршилтыг гурван тохиргоогоор хийдэг.

  1. стресс тест
  2. Зөвхөн холболтууд
  3. Захиалагчийн бүртгэл

Стресс тестийн үеэр бид хэдэн зуун хэлхээг ажиллуулдаг бөгөөд тэдгээр нь системийг зогсоохгүйгээр ачаалдаг: мессеж бичих, хэлэлцүүлэг үүсгэх, мессежийн жагсаалтыг хүлээн авах. Бид энгийн хэрэглэгчдийн үйлдлийг дуурайдаг (миний уншаагүй мессежүүдийн жагсаалтыг авах, хэн нэгэнд бичих) болон програм хангамжийн шийдлүүд (өөр тохиргооны багцыг дамжуулах, сэрэмжлүүлэг боловсруулах).

Жишээлбэл, стресс тестийн хэсэг нь дараах байдалтай байна.

  • Хэрэглэгч нэвтэрч байна
    • Таны уншаагүй хэлэлцүүлгийг хүсч байна
    • 50% нь мессеж унших магадлалтай
    • 50% нь мессеж бичих магадлалтай
    • Дараагийн хэрэглэгч:
      • Шинэ хэлэлцүүлэг үүсгэх магадлал 20% байна
      • Хэлэлцүүлгийн аль нэгийг нь санамсаргүй байдлаар сонгодог
      • Дотор нь ордог
      • Хүсэлтийн зурвас, хэрэглэгчийн профайл
      • Энэ хэлэлцүүлгээс санамсаргүй хэрэглэгчдэд зориулсан таван мессежийг үүсгэнэ
      • Хэлэлцүүлгийг орхиж байна
      • 20 удаа давтана
      • Гарч, скриптийн эхэнд буцаж очно

    • Чатбот системд нэвтэрнэ (програмын кодоос мессежийг дуурайдаг)
      • Мэдээлэл солилцох шинэ суваг үүсгэх магадлал 50% байна (тусгай хэлэлцүүлэг)
      • 50% нь одоо байгаа аль ч суваг руу мессеж бичих магадлалтай

"Зөвхөн холболтууд" хувилбар тодорхой шалтгааны улмаас гарч ирэв. Нөхцөл байдал бий: хэрэглэгчид системд холбогдсон боловч хараахан оролцоогүй байна. Хэрэглэгч бүр өглөөний 09:00 цагт компьютерээ асаагаад сервертэй холбогдож, чимээгүй байна. Эдгээр залуус аюултай, тэдний олонх нь байдаг - тэдэнд байгаа цорын ганц багц нь PING/PONG, гэхдээ тэд сервертэй холболтоо хадгалдаг (тэд үүнийг үргэлжлүүлж чадахгүй - хэрэв шинэ мессеж байвал яах вэ). Туршилт нь ийм олон тооны хэрэглэгчид хагас цагийн дотор системд нэвтрэхийг оролддог нөхцөл байдлыг дахин бүтээдэг. Энэ нь стресс тесттэй төстэй боловч ямар ч алдаа гарахгүйн тулд (хүн системийг ашигладаггүй бөгөөд энэ нь аль хэдийн унасан - үүнээс илүү муу зүйлийн талаар бодоход хэцүү байдаг) энэ нь эхний оролт дээр анхаарлаа төвлөрүүлдэг.

Захиалагчийн бүртгэлийн скрипт нь анхны нээлтээс эхэлдэг. Бид стресс тест хийсэн бөгөөд захидал харилцааны явцад систем удаашрахгүй гэдэгт итгэлтэй байсан. Гэвч хэрэглэгчид ирж, хугацаа хэтэрсэн тул бүртгэл амжилтгүй болж эхэлсэн. Бүртгүүлэхдээ бид ашигласан / dev / санамсаргүй, энэ нь системийн энтропитэй холбоотой. Серверт хангалттай энтропи хуримтлуулах цаг байсангүй бөгөөд шинэ SecureRandom хүсэлт тавихад хэдэн арван секундын турш хөлдсөн. Энэ байдлаас гарах олон арга бий, жишээлбэл: хамгаалалт багатай /dev/urandom руу шилжих, энтропи үүсгэдэг тусгай самбар суулгаж, санамсаргүй тоонуудыг урьдчилан гаргаж, санд хадгалах. Бид усан сантай холбоотой асуудлыг түр хаасан боловч түүнээс хойш шинэ захиалагчдыг бүртгэхийн тулд тусдаа тест хийж байна.

Бид ачаалал үүсгэгч болгон ашигладаг JMeter. Энэ нь вэбсокеттэй хэрхэн ажиллахаа мэдэхгүй, түүнд залгаас хэрэгтэй. "jmeter websocket" хайлтын илэрцүүдийн эхнийх нь: BlazeMeter-ийн нийтлэлүүд, санал болгож байна Maciej Zaleski-ийн залгаас.

Эндээс л бид эхлэхээр шийдсэн.

Ноцтой туршилт хийж эхэлсний дараа бид JMeter санах ой алдагдаж эхэлснийг олж мэдсэн.

Plugin нь тусдаа том түүх бөгөөд 176 одтой, github дээр 132 сэрээтэй. Зохиогч өөрөө 2015 оноос хойш үүнийг амлаагүй (бид үүнийг 2015 онд авсан, дараа нь энэ нь сэжиг төрүүлээгүй), санах ой алдагдсантай холбоотой хэд хэдэн github асуудал, 7 хаалттай татах хүсэлт.
Хэрэв та энэ залгаасыг ашиглан ачааллын туршилт хийхээр шийдсэн бол дараах хэлэлцүүлэгт анхаарлаа хандуулна уу.

  1. Олон урсгалтай орчинд ердийн LinkedList ашигласан бөгөөд үр дүн нь гарсан NPE ажиллах хугацаанд. Үүнийг ConcurrentLinkedDeque руу шилжих эсвэл синхрончлогдсон блокуудаар шийдэж болно. Бид өөрсдөө эхний сонголтыг сонгосон (https://github.com/maciejzaleski/JMeter-WebSocketSampler/issues/43).
  2. Санах ой алдагдсан; салгах үед холболтын мэдээлэл устахгүй (https://github.com/maciejzaleski/JMeter-WebSocketSampler/issues/44).
  3. Урсгалын горимд (түүврийн төгсгөлд вэб залгуур хаагдахгүй, гэхдээ дараа нь төлөвлөгөөнд ашиглагдах үед) хариу өгөх загвар ажиллахгүй (https://github.com/maciejzaleski/JMeter-WebSocketSampler/issues/19).

Энэ бол github дээрх хүмүүсийн нэг юм. Бидний хийсэн зүйл:

  1. Авсан сэрээ Элиран Коган (@elyrank) - энэ нь 1 ба 3-р асуудлыг засдаг
  2. Шийдсэн асуудал 2
  3. 9.2.14-ээс 9.3.12 хүртэл усан онгоцны зогсоолыг шинэчилсэн
  4. ThreadLocal-д SimpleDateFormat-ыг ороосон; SimpleDateFormat нь урсгалд аюулгүй биш бөгөөд энэ нь ажиллах үед NPE-д хүргэсэн
  5. Өөр санах ойн алдагдлыг зассан (холболтыг салгах үед буруу хаагдсан)

Гэсэн хэдий ч энэ нь урсдаг!

Ой тогтоолт нэг өдрийн дотор биш хоёрхон хугацаанд дуусч эхлэв. Цаг хугацаа үлдсэнгүй, тиймээс бид цөөн тооны сэдвийг эхлүүлэхээр шийдсэн, гэхдээ дөрвөн агент дээр. Энэ нь дор хаяж долоо хоног хангалттай байх ёстой.

Хоёр хоног өнгөрчээ...

Одоо Хазелкаст санах ой дуусч байна. Бүртгэлээс харахад хэд хоногийн турш туршилт хийсний дараа Хазелкаст санах ой дутмаг гэж гомдоллож эхэлсэн бөгөөд хэсэг хугацааны дараа кластер задарч, зангилаанууд нэг нэгээр нь үхсээр байв. Бид JVisualVM-г hazelcast-тай холбож, "өсөж буй хөрөө" -ийг харсан - энэ нь GC-г байнга дууддаг боловч санах ойг цэвэрлэж чадсангүй.

Бид 1С: Enterprise: Java, PostgreSQL, Hazelcast-д зориулсан өндөр ачаалалтай өргөтгөх боломжтой үйлчилгээг хэрхэн, яагаад бичсэн бэ

Hazelcast 3.4-д газрын зураг / multiMap (map.destroy()) устгах үед санах ой бүрэн чөлөөлөгддөггүй нь тогтоогджээ.

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

Алдааг одоо 3.5-д зассан, гэхдээ тэр үед асуудал байсан. Бид динамик нэртэй шинэ multiMaps үүсгэж, логикийн дагуу устгасан. Код нь иймэрхүү харагдаж байв.

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

Дуудлага:

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

multiMap-ыг захиалга тус бүрээр үүсгэсэн бөгөөд шаардлагагүй үед устгасан. Бид Газрын зураг эхлүүлэхээр шийдсэн , түлхүүр нь захиалгын нэр байх ба утгууд нь сесс танигч байх болно (шаардлагатай бол та хэрэглэгчийн танигчийг авах боломжтой).

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

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

Графикууд сайжирсан.

Бид 1С: Enterprise: Java, PostgreSQL, Hazelcast-д зориулсан өндөр ачаалалтай өргөтгөх боломжтой үйлчилгээг хэрхэн, яагаад бичсэн бэ

Бид ачааллын туршилтын талаар өөр юу сурсан бэ?

  1. JSR223-ыг нарийн бичигдсэн байх ёстой бөгөөд эмхэтгэлийн кэшийг багтаасан байх ёстой - энэ нь илүү хурдан юм. холбоос.
  2. Jmeter-Plugins графикууд нь стандартаас илүү ойлгомжтой байдаг. холбоос.

Hazelcast-тай хийсэн бидний туршлагын талаар

Hazelcast бол бидний хувьд шинэ бүтээгдэхүүн байсан, бид 3.4.1 хувилбараас эхлэн түүнтэй ажиллаж эхэлсэн, одоо манай үйлдвэрлэлийн сервер 3.9.2 хувилбарыг ажиллуулж байна (бичиж байх үед Hazelcast-ын хамгийн сүүлийн хувилбар нь 3.10).

ID үүсгэх

Бид бүхэл тоо тодорхойлогчоор эхэлсэн. Шинэ аж ахуйн нэгжийн хувьд бидэнд өөр урт хэрэгтэй гэж төсөөлөөд үз дээ. Өгөгдлийн сан дахь дараалал тохиромжгүй, хүснэгтүүд нь хуваахад оролцдог - DB1-д ID=1, DB1-д ID=2 гэсэн мессеж байгаа тул та энэ ID-г Elasticsearch болон Hazelcast-д оруулах боломжгүй. , гэхдээ хамгийн муу зүйл бол хэрэв та хоёр өгөгдлийн сангаас өгөгдлийг нэг болгон нэгтгэхийг хүсч байвал (жишээлбэл, эдгээр захиалагчдад нэг мэдээллийн сан хангалттай гэж шийдэх). Та Hazelcast-д хэд хэдэн AtomicLongs нэмж, тоолуурыг тэнд байлгаж болно, дараа нь шинэ ID авах гүйцэтгэл нь incrementAndGet дээр нэмээд Hazelcast-д хүсэлт гаргах хугацаа болно. Гэхдээ Hazelcast-д илүү оновчтой зүйл бий - FlakeIdGenerator. Үйлчлүүлэгч бүртэй холбоо тогтоохдоо тэдэнд ID хязгаарыг өгдөг, жишээлбэл, эхнийх нь - 1-ээс 10 хүртэл, хоёр дахь нь - 000-ээс 10 хүртэл гэх мэт. Одоо үйлчлүүлэгч өөрт нь олгосон хүрээ дуусах хүртэл шинэ танигчийг өөрөө гаргаж болно. Энэ нь хурдан ажилладаг, гэхдээ та програмыг (мөн Hazelcast клиент) дахин эхлүүлэх үед шинэ дараалал эхэлдэг - иймээс алгасах гэх мэт. Нэмж дурдахад, хөгжүүлэгчид яагаад ID нь бүхэл тоо байдгийг сайн ойлгодоггүй, гэхдээ маш их зөрчилтэй байдаг. Бид бүгдийг жинлэж, UUID-д шилжсэн.

Дашрамд хэлэхэд, Твиттер шиг байхыг хүсдэг хүмүүст зориулж ийм Snowcast номын сан байдаг - энэ бол Hazelcast-ийн орой дээрх Snowflake-ийн хэрэгжилт юм. Та эндээс үзэх боломжтой:

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

Гэхдээ бид үүнтэй ойртож чадаагүй байна.

TransactionalMap.replace

Өөр нэг гэнэтийн зүйл: TransactionalMap.replace ажиллахгүй байна. Энд тест байна:

@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

Би 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);
}

Зөвхөн ердийн өгөгдлийн бүтэц төдийгүй тэдгээрийн гүйлгээний хувилбаруудыг туршиж үзээрэй. IMap ажилладаг ч TransactionalMap байхгүй болсон.

Сул зогсолтгүйгээр шинэ JAR оруулна уу

Эхлээд бид ангийнхаа объектуудыг Hazelcast-д бичихээр шийдсэн. Жишээлбэл, манайд Хэрэглээний анги байдаг, бид үүнийг хадгалж, уншихыг хүсч байна. Хадгалах:

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

Бид уншсан:

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

Бүх зүйл ажиллаж байна. Дараа нь бид Hazelcast-д индекс үүсгэхээр шийдсэн:

map.addIndex("subscriberId", false);

Мөн шинэ нэгж бичихдээ тэд ClassNotFoundException хүлээн авч эхэлсэн. Хазелкаст индексийг нэмэхийг оролдсон боловч манай ангийн талаар юу ч мэдэхгүй байсан бөгөөд энэ ангитай JAR-г түүнд нийлүүлэхийг хүссэн. Бид үүнийг л хийсэн, бүх зүйл ажилласан, гэхдээ шинэ асуудал гарч ирэв: кластерыг бүрэн зогсоохгүйгээр JAR-г хэрхэн шинэчлэх вэ? Hazelcast шинэ JAR-г зангилаа бүрээр шинэчлэх үед авдаггүй. Энэ үед бид индекс хайлтгүйгээр амьдарч чадна гэж шийдсэн. Эцсийн эцэст, хэрэв та Hazelcast-ийг гол үнэ цэнийн дэлгүүр болгон ашиглавал бүх зүйл ажиллах болно? Үнэхээр биш. Энд дахин IMap болон TransactionalMap-ийн үйлдэл өөр байна. IMap хамаагүй тохиолдолд TransactionalMap алдаа гаргадаг.

IMap. Бид 5000 объект бичдэг, тэдгээрийг уншдаг. Бүх зүйл хүлээгдэж байна.

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

Гэхдээ энэ нь гүйлгээнд ажиллахгүй, бид 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();
        }
    });
}

3.8-д Хэрэглэгчийн ангиллын байршуулалтын механизм гарч ирэв. Та нэг мастер зангилааг тодорхойлж, JAR файлыг шинэчлэх боломжтой.

Одоо бид арга барилаа бүрэн өөрчилсөн: бид үүнийг өөрсдөө JSON болгон цуврал болгож, Hazelcast-д хадгалдаг. Hazelcast манай ангиудын бүтцийг мэдэх шаардлагагүй бөгөөд бид завсарлагагүйгээр шинэчлэх боломжтой. Домэйн объектуудын хувилбарыг программ удирддаг. Програмын өөр өөр хувилбарууд нэгэн зэрэг ажиллаж болох бөгөөд шинэ програм нь шинэ талбар бүхий объектуудыг бичих нөхцөл байдал үүсч болзошгүй боловч хуучин нь эдгээр талбаруудын талаар хараахан мэдэхгүй байна. Үүний зэрэгцээ шинэ програм нь шинэ талбаргүй хуучин програмын бичсэн объектуудыг уншдаг. Бид ийм нөхцөл байдлыг програм дотор зохицуулдаг боловч хялбар болгох үүднээс талбаруудыг өөрчлөх эсвэл устгахгүй, зөвхөн шинэ талбар нэмэх замаар ангиудыг өргөжүүлдэг.

Бид хэрхэн өндөр гүйцэтгэлийг баталгаажуулдаг

Hazelcast руу дөрвөн аялал - сайн, хоёр мэдээллийн сан руу - муу

Мэдээллийн кэш рүү орох нь мэдээллийн сан руу орохоос үргэлж дээр байдаг, гэхдээ та ашиглагдаагүй бүртгэлээ хадгалахыг хүсэхгүй байна. Бид юуг кэшлэх тухай шийдвэрийг хөгжлийн сүүлийн шат хүртэл үлдээдэг. Шинэ функцийг кодчилсны дараа бид PostgreSQL дээрх бүх асуулгын бүртгэлийг (log_min_duration_statement 0 хүртэл) асааж, ачааллын тестийг 20 минутын турш ажиллуулна. Цуглуулсан бүртгэлийг ашиглан pgFouine, pgBadger зэрэг хэрэгслүүд аналитик тайлан гаргах боломжтой. Тайлан дээр бид ихэвчлэн удаан бөгөөд байнга асуудаг асуултуудыг хайдаг. Удаан асуулгын хувьд бид гүйцэтгэлийн төлөвлөгөөг (ТАЙЛБАР) боловсруулж, ийм хүсэлтийг хурдасгах боломжтой эсэхийг үнэлдэг. Ижил оролтын өгөгдлийн байнгын хүсэлтүүд нь кэшэд сайн нийцдэг. Бид асуулга бүрт нэг хүснэгтийг "хавтгай" байлгахыг хичээдэг.

Ашиглалт

SV нь онлайн үйлчилгээний хувьд 2017 оны хавар ашиглалтад орсон бөгөөд тусдаа бүтээгдэхүүн болох SV нь 2017 оны XNUMX-р сард (тэр үед бета хувилбарын статустай байсан) гарсан.

Үйл ажиллагаа явуулснаас хойш жил гаруйн хугацаанд СБ онлайн үйлчилгээний үйл ажиллагаанд ноцтой хүндрэл гараагүй байна. Бид онлайн үйлчилгээгээр дамжуулан хянадаг Заббик, -аас цуглуулж байрлуулна Хулсан.

SV серверийн түгээлт нь RPM, DEB, MSI гэсэн үндсэн багц хэлбэрээр нийлүүлэгддэг. Дээрээс нь Windows-д зориулж бид сервер, Hazelcast болон Elasticsearch-ийг нэг машин дээр суулгадаг нэг EXE хэлбэрээр нэг суулгагчийг өгдөг. Бид анх суулгацын энэ хувилбарыг "демо" хувилбар гэж нэрлэж байсан боловч одоо энэ нь хамгийн түгээмэл байршуулах хувилбар болох нь тодорхой болсон.

Эх сурвалж: www.habr.com

сэтгэгдэл нэмэх