ãã®èšäºã§ã¯ãéçºã®æ¹æ³ãšçç±ã«ã€ããŠèª¬æããŸãã
ã€ã³ã¿ã©ã¯ã·ã§ã³ ã·ã¹ãã (以äžãSV ãšåŒã³ãŸã) ã¯ãé ä¿¡ãä¿èšŒãããåæ£åã®èé害æ§ã¡ãã»ãŒãžã³ã° ã·ã¹ãã ã§ãã SV ã¯ãé«ãã¹ã±ãŒã©ããªãã£ãåããé«è² è·ãµãŒãã¹ãšããŠèšèšãããŠããããªã³ã©ã€ã³ ãµãŒãã¹ (1C ãæäŸ) ãšããŠããç¬èªã®ãµãŒããŒæœèšã«å°å ¥ã§ããéç£è£œåãšããŠãå©çšã§ããŸãã
SV ã¯åæ£ã¹ãã¬ãŒãžã䜿çšããŸã
åé¡ã®å®åŒå
ã€ã³ã¿ã©ã¯ã·ã§ã³ ã·ã¹ãã ãäœæããçç±ãæ確ã«ããããã«ã1C ã§ã®ããžãã¹ ã¢ããªã±ãŒã·ã§ã³ã®éçºãã©ã®ããã«è¡ããããã«ã€ããŠå°ã説æããŸãã
ãŸããç§ãã¡ãäœãããŠããã®ããŸã ç¥ããªã人ã®ããã«ãç§ãã¡ã«ã€ããŠå°ã説æããŸã :) ç§ãã¡ã¯ 1C:Enterprise ãã¯ãããžãŒ ãã©ãããã©ãŒã ãäœæããŠããŸãã ãã®ãã©ãããã©ãŒã ã«ã¯ãããžãã¹ ã¢ããªã±ãŒã·ã§ã³éçºããŒã«ãšãããžãã¹ ã¢ããªã±ãŒã·ã§ã³ãã¯ãã¹ãã©ãããã©ãŒã ç°å¢ã§å®è¡ã§ããã©ã³ã¿ã€ã ãå«ãŸããŠããŸãã
ã¯ã©ã€ã¢ã³ããµãŒããŒéçºãã©ãã€ã
1C:Enterprise ã§äœæãããæ¥åã¢ããªã±ãŒã·ã§ã³ã¯ XNUMX ã€ã®ã¬ãã«ã§åäœããŸã
ã¢ããªã±ãŒã·ã§ã³ ã³ãŒãã§ã¯ãããã·ãŒãžã£ãšé¢æ°ã®ããããŒã¯ã&AtClient / &AtServer ãã£ã¬ã¯ãã£ã (è±èªçã§ã¯ &AtClient / &AtServer) ã䜿çšããŠãã³ãŒããå®è¡ãããå Žæãæ瀺çã«ç€ºãå¿
èŠããããŸãã 1C éçºè
ã¯ããã£ã¬ã¯ãã£ãã¯å®éã«ã¯æ¬¡ã®ãšããã§ãããšèšã£ãŠç§ãèšæ£ããã§ãããã
ã¯ã©ã€ã¢ã³ã ã³ãŒããããµãŒã㌠ã³ãŒããåŒã³åºãããšã¯ã§ããŸããããµãŒã㌠ã³ãŒãããã¯ã©ã€ã¢ã³ã ã³ãŒããåŒã³åºãããšã¯ã§ããŸããã ããã¯ãããŸããŸãªçç±ããç§ãã¡ãèšããåºæ¬çãªå¶éã§ãã ç¹ã«ããµãŒã㌠ã³ãŒãã¯ãã¯ã©ã€ã¢ã³ããŸãã¯ãµãŒããŒã®ã©ãããåŒã³åºãããŠãåãæ¹æ³ã§å®è¡ãããããã«èšè¿°ããå¿ èŠãããããã§ãã ãŸããå¥ã®ãµãŒã㌠ã³ãŒããããµãŒã㌠ã³ãŒããåŒã³åºãå Žåãã¯ã©ã€ã¢ã³ãèªäœã¯ååšããŸããã ãŸãããµãŒã㌠ã³ãŒãã®å®è¡äžã«ããã®ã³ãŒããåŒã³åºããã¯ã©ã€ã¢ã³ããéããŠã¢ããªã±ãŒã·ã§ã³ãçµäºããå¯èœæ§ãããããµãŒããŒã«ã¯åŒã³åºãå ãååšããªããªããŸãã
ãã¿ã³ã®ã¯ãªãã¯ãåŠçããã³ãŒã: ã¯ã©ã€ã¢ã³ãããã®ãµãŒã㌠ããã·ãŒãžã£ã®åŒã³åºãã¯æ©èœããŸããããµãŒããŒããã®ã¯ã©ã€ã¢ã³ã ããã·ãŒãžã£ã®åŒã³åºãã¯æ©èœããŸããã
ããã¯ããµãŒããŒããã¯ã©ã€ã¢ã³ã ã¢ããªã±ãŒã·ã§ã³ã«äœããã®ã¡ãã»ãŒãžãéä¿¡ãããå Žåãããšãã°ããé·æéå®è¡ããããã¬ããŒãã®çæãå®äºããã¬ããŒãã衚瀺ã§ããããã«ãããå Žåããã®ãããªã¡ãœããããªãããšãæå³ããŸãã ããšãã°ãã¯ã©ã€ã¢ã³ã ã³ãŒããããµãŒããŒãå®æçã«ããŒãªã³ã°ãããªã©ã®ããªãã¯ã䜿çšããå¿ èŠããããŸãã ãã ãããã®ã¢ãããŒãã§ã¯ã·ã¹ãã ã«äžèŠãªåŒã³åºããããŒãããããããäžè¬ã«ããŸãæŽç·Žããããã®ãšã¯èšããŸããã
ãŸããé»è©±ãããã£ãŠãããšããªã©ã«ãããŒãºããããŸãã
å¶äœèªäœã
ã¡ãã»ãŒãžã³ã°ã¡ã«ããºã ãäœæããŸãã é«éãã€ä¿¡é Œæ§ãé«ããé ä¿¡ãä¿èšŒãããŠãããã¡ãã»ãŒãžãæè»ã«æ€çŽ¢ã§ããŸãã ãã®ã¡ã«ããºã ã«åºã¥ããŠã1C ã¢ããªã±ãŒã·ã§ã³å ã§å®è¡ãããã¡ãã»ã³ãžã£ãŒ (ã¡ãã»ãŒãžããããªé話) ãå®è£ ããŸãã
æ°Žå¹³æ¹åã«æ¡åŒµã§ããããã«ã·ã¹ãã ãèšèšããŸãã å¢å ããè² è·ã¯ããŒãæ°ãå¢ããããšã§ã«ããŒããå¿ èŠããããŸãã
å ·çŸå
ç§ãã¡ã¯ãSV ã®ãµãŒããŒéšåã 1C:Enterprise ãã©ãããã©ãŒã ã«çŽæ¥çµ±åããã®ã§ã¯ãªããå¥ã®è£œåãšããŠå®è£ ãããã® API ã 1C ã¢ããªã±ãŒã·ã§ã³ ãœãªã¥ãŒã·ã§ã³ã®ã³ãŒãããåŒã³åºãããšãã§ããããã«ããããšã«ããŸããã ããã«ã¯ããŸããŸãªçç±ããããŸããããäž»ãªçç±ã¯ãç°ãªã 1C ã¢ããªã±ãŒã·ã§ã³é (ããšãã°ãTrade Management ãš Accounting ã®é) ã§ã¡ãã»ãŒãžã亀æã§ããããã«ããããšããããšã§ããã ç°ãªã 1C ã¢ããªã±ãŒã·ã§ã³ã¯ãç°ãªãããŒãžã§ã³ã® 1C:Enterprise ãã©ãããã©ãŒã ã§å®è¡ããããç°ãªããµãŒããŒã«é 眮ãããã§ããŸãã ãã®ãããªç¶æ³ã§ã¯ãSV ã 1C èšåã®ãåŽãã«é 眮ãããå¥åã®è£œåãšããŠå®è£ ããããšãæé©ãªãœãªã¥ãŒã·ã§ã³ã§ãã
ããã§SVãå¥è£œåãšããŠäœãããšã«ããŸããã å°èŠæš¡äŒæ¥ã«ã¯ããµãŒããŒã®ããŒã«ã« ã€ã³ã¹ããŒã«ãšæ§æã«é¢é£ããè«žçµè²»ãåé¿ããããã«ãã¯ã©ãŠã (wss://1cdialog.com) ã«ã€ã³ã¹ããŒã«ãã CB ãµãŒããŒã䜿çšããããšããå§ãããŸãã 倧èŠæš¡ãªã¯ã©ã€ã¢ã³ãã¯ãèªç€Ÿã®æœèšã«ç¬èªã® CB ãµãŒããŒãèšçœ®ããããšããå§ãããŸãã åœç€Ÿã®ã¯ã©ãŠã SaaS 補åã§ãåæ§ã®ã¢ãããŒãã䜿çšããŸãã
ã¢ããªã±ãŒã·ã§ã³
è² è·ãšãã©ãŒã«ã ãã¬ã©ã³ã¹ãåæ£ããããã«ãXNUMX ã€ã® Java ã¢ããªã±ãŒã·ã§ã³ã§ã¯ãªããè€æ°ã® Java ã¢ããªã±ãŒã·ã§ã³ããããã€ãããã®åã«ããŒã ãã©ã³ãµãŒã眮ããŸãã ããŒãããããŒããžã¡ãã»ãŒãžã転éããå¿ èŠãããå Žåã¯ãHazelcast ã§ãããªãã·ã¥/ãµãã¹ã¯ã©ã€ãã䜿çšããŸãã
ã¯ã©ã€ã¢ã³ããšãµãŒããŒéã®é信㯠WebSocket çµç±ã§è¡ãããŸãã ãªã¢ã«ã¿ã€ã ã·ã¹ãã ã«æé©ã§ãã
åæ£ãã£ãã·ã¥
RedisãHazelcastãEhcache ã®äžããéžæããŸããã 2015幎ã§ãã Redis ã¯æ°ããã¯ã©ã¹ã¿ãŒããªãªãŒã¹ããã°ããã§ãã (æ°ããããŠæã)ãå€ãã®å¶éã®ãã Sentinel ããããŸãã Ehcache ã¯ã¯ã©ã¹ã¿ãŒã«çµã¿ç«ãŠãæ¹æ³ãç¥ããŸãã (ãã®æ©èœã¯åŸã§ç»å ŽããŸãã)ã Hazelcast 3.4 ã§è©ŠããŠã¿ãããšã«ããŸããã
Hazelcast ã¯ãç®±ããåºããŠããã«ã¯ã©ã¹ã¿ãŒã«çµã¿ç«ãŠãããŸãã ã·ã³ã°ã« ããŒã ã¢ãŒãã§ã¯ãããŸã圹ã«ç«ããããã£ãã·ã¥ãšããŠã®ã¿äœ¿çšã§ããŸããããŒã¿ããã£ã¹ã¯ã«ãã³ãããæ¹æ³ãããããªããããå¯äžã®ããŒãã倱ããšããŒã¿ã倱ãããŸãã è€æ°ã® Hazelcast ããããã€ãããã®éã§éèŠãªããŒã¿ãããã¯ã¢ããããŸãã ãã£ãã·ã¥ã¯ããã¯ã¢ããããŸãããæ°ã«ããŸããã
ç§ãã¡ã«ãšã£ãŠãHazelcast ã¯æ¬¡ã®ãšããã§ãã
- ãŠãŒã¶ãŒã»ãã·ã§ã³ã®ã¹ãã¬ãŒãžã æ¯åã»ãã·ã§ã³ã®ããã«ããŒã¿ããŒã¹ã«ã¢ã¯ã»ã¹ãããšæéããããããããã¹ãŠã®ã»ãã·ã§ã³ã Hazelcast ã«å ¥ããŸãã
- ãã£ãã·ã¥ã ãŠãŒã¶ãŒ ãããã¡ã€ã«ãæ¢ããŠããå Žåã¯ããã£ãã·ã¥ã確èªããŠãã ããã æ°ããã¡ãã»ãŒãžãäœæããŸãã - ãã£ãã·ã¥ã«å ¥ããŸããã
- ã¢ããªã±ãŒã·ã§ã³ ã€ã³ã¹ã¿ã³ã¹éã®éä¿¡ã«é¢ãããããã¯ã ããŒãã¯ã€ãã³ããçæããHazelcast ãããã¯ã«é 眮ããŸãã ãã®ãããã¯ã«ãµãã¹ã¯ã©ã€ãããŠããä»ã®ã¢ããªã±ãŒã·ã§ã³ ããŒãã¯ãã€ãã³ããåä¿¡ããŠââåŠçããŸãã
- ã¯ã©ã¹ã¿ãŒããã¯ã ããšãã°ãäžæã®ããŒã䜿çšããŠãã£ã¹ã«ãã·ã§ã³ãäœæããŸã (1C ããŒã¿ããŒã¹å ã®ã·ã³ã°ã«ãã³ ãã£ã¹ã«ãã·ã§ã³)ã
conversationKeyChecker.check("ÐÐÐÐÐÐÐÐÐÐÐÐ");
doInClusterLock("ÐÐÐÐÐÐÐÐÐÐÐÐ", () -> {
conversationKeyChecker.check("ÐÐÐÐÐÐÐÐÐÐÐÐ");
createChannel("ÐÐÐÐÐÐÐÐÐÐÐÐ");
});
ãã£ã³ãã«ããªãããšã確èªããŸããã ç§ãã¡ã¯ããã¯ãååŸããå床確èªããŠãäœæããŸããã ããã¯ãååŸããåŸã«ããã¯ããã§ãã¯ããªããšããã®æç¹ã§å¥ã®ã¹ã¬ããããã§ãã¯ãããåããã£ã¹ã«ãã·ã§ã³ãäœæããããšããå¯èœæ§ããããŸããããã®ãã£ã¹ã«ãã·ã§ã³ã¯ãã§ã«ååšããŸãã åæãŸãã¯éåžžã® Java ããã¯ã䜿çšããŠããã¯ããããšã¯ã§ããŸããã ããŒã¿ããŒã¹çµç± - é ãã®ã§ããŒã¿ããŒã¹ã«ãšã£ãŠã¯æ®å¿µã§ãããHazelcast çµç± - ãããå¿ èŠã§ãã
DBMS ã®éžæ
ç§ãã¡ã¯ãPostgreSQL ã䜿çšãããã® DBMS ã®éçºè ãšååããŠæåããåºç¯ãªçµéšãæã£ãŠããŸãã
PostgreSQL ã¯ã©ã¹ã¿ãŒã䜿çšããã®ã¯ç°¡åã§ã¯ãããŸããã
ãªã¬ãŒã·ã§ãã« ããŒã¿ããŒã¹ãæ¡åŒµããå¿
èŠãããå Žåãããã¯æ¬¡ã®ããšãæå³ããŸãã
ã·ã£ãŒãã£ã³ã°ã®æåã®ããŒãžã§ã³ã§ã¯ãã¢ããªã±ãŒã·ã§ã³ã®åããŒãã«ãããŸããŸãªãµãŒããŒã«ããŸããŸãªå²åã§åæ£ã§ããããšãæ³å®ãããŠããŸããã ãµãŒã㌠A ã«ã¯å€§éã®ã¡ãã»ãŒãžããããŸãããé¡ãããŸãããã®ããŒãã«ã®äžéšããµãŒã㌠B ã«ç§»åããŸãããããã®æ±ºå®ã¯åã«ææå°æ©ãªæé©åãæžå¿µãããã®ã§ãã£ãããããã«ãããã³ãã®ã¢ãããŒãã«éå®ããããšã«ããŸããã
ããšãã°ãWeb ãµã€ãã§ãã«ãããã³ãã«ã€ããŠèªãããšãã§ããŸãã
SV ã«ã¯ã¢ããªã±ãŒã·ã§ã³ãšãµãã¹ã¯ã©ã€ãã®æŠå¿µããããŸãã ã¢ããªã±ãŒã·ã§ã³ã¯ãERP ãäŒèšãªã©ã®ããžãã¹ ã¢ããªã±ãŒã·ã§ã³ãšãã®ãŠãŒã¶ãŒããã³ããžãã¹ ããŒã¿ã®ç¹å®ã®ã€ã³ã¹ããŒã«ã§ãã ãµãã¹ã¯ã©ã€ãã¯ããã®ä»£çãšããŠã¢ããªã±ãŒã·ã§ã³ã SV ãµãŒããŒã«ç»é²ãããçµç¹ãŸãã¯å人ã§ãã ãµãã¹ã¯ã©ã€ãã¯è€æ°ã®ã¢ããªã±ãŒã·ã§ã³ãç»é²ã§ãããããã®ã¢ããªã±ãŒã·ã§ã³ã¯çžäºã«ã¡ãã»ãŒãžã亀æã§ããŸãã å å ¥è ã¯ã·ã¹ãã ã®ããã³ãã«ãªããŸããã è€æ°ã®å å ¥è ããã®ã¡ãã»ãŒãžã XNUMX ã€ã®ç©çããŒã¿ããŒã¹ã«é 眮ã§ããŸãã ãµãã¹ã¯ã©ã€ãã倧éã®ãã©ãã£ãã¯ãçæãå§ããŠããããšãããã£ãå Žåããããå¥ã®ç©çããŒã¿ããŒã¹ (ãŸãã¯å¥ã®ããŒã¿ããŒã¹ ãµãŒããŒ) ã«ç§»åããŸãã
ãã¹ãŠã®å å ¥è ããŒã¿ããŒã¹ã®å Žæã«é¢ããæ å ±ãå«ãã«ãŒãã£ã³ã° ããŒãã«ãä¿åãããŠããã¡ã€ã³ ããŒã¿ããŒã¹ããããŸãã
ã¡ã€ã³ ããŒã¿ããŒã¹ãããã«ããã¯ã«ãªãã®ãé²ãããã«ãã«ãŒãã£ã³ã° ããŒãã« (ããã³ãã®ä»ã®é »ç¹ã«å¿
èŠãªããŒã¿) ããã£ãã·ã¥ã«ä¿æããŸãã
ãµãã¹ã¯ã©ã€ãã®ããŒã¿ããŒã¹ã®é床ãäœäžãå§ããå ŽåãããŒã¿ããŒã¹ãå
éšã®ããŒãã£ã·ã§ã³ã«åå²ããŸãã ç§ãã¡ã䜿çšããä»ã®ãããžã§ã¯ãã§ã¯
ãŠãŒã¶ãŒ ã¡ãã»ãŒãžã倱ãããšã¯å¥œãŸãããªããããããŒã¿ããŒã¹ã¯ã¬ããªã«ã§ç¶æãããŠããŸãã åæã¬ããªã«ãšéåæã¬ããªã«ãçµã¿åãããããšã§ãã¡ã€ã³ ããŒã¿ããŒã¹ã倱ãããå Žåã«åããããšãã§ããŸãã ã¡ãã»ãŒãžæ倱ã¯ããã©ã€ã㪠ããŒã¿ããŒã¹ãšãã®åæã¬ããªã«ã«åæã«é害ãçºçããå Žåã«ã®ã¿çºçããŸãã
åæã¬ããªã«ã倱ããããšãéåæã¬ããªã«ãåæã«ãªããŸãã
ã¡ã€ã³ ããŒã¿ããŒã¹ã倱ããããšãåæã¬ããªã«ãã¡ã€ã³ ããŒã¿ããŒã¹ã«ãªããéåæã¬ããªã«ãåæã¬ããªã«ã«ãªããŸãã
æ€çŽ¢çšã® Elasticsearch
ãšããããSV ã¯ã¡ãã»ã³ãžã£ãŒã§ããããããäžæ£ç¢ºãªäžèŽã䜿çšããŠã圢æ
ãèæ
®ãããé«éã§äŸ¿å©ãã€æè»ãªæ€çŽ¢ãå¿
èŠã§ãã ç§ãã¡ã¯è»èŒªã®åçºæã¯è¡ãããã©ã€ãã©ãªã«åºã¥ããŠäœæãããç¡æã®æ€çŽ¢ãšã³ãžã³ Elasticsearch ã䜿çšããããšã«ããŸããã
github ã§èŠã€ããŸãã
ãããŠãããã¹ãããšããèšèã®èªæºãä¿åãããŸãã ãã®æ¹æ³ã§ã¯ãåèªã®å é ãäžéãæ«å°Ÿãæ€çŽ¢ã§ããŸãã
倧å±
èšäºã®åé ã®å³ãç¹°ãè¿ããŸããã説æãä»ããŠããŸãã
- ã€ã³ã¿ãŒãããäžã«å ¬éããããã©ã³ãµãŒã nginx ããããŸãããã©ãã§ãæ§ããŸããã
- Java ã¢ããªã±ãŒã·ã§ã³ ã€ã³ã¹ã¿ã³ã¹ã¯ãHazelcast ãä»ããŠçžäºã«éä¿¡ããŸãã
- 䜿çšãã Web ãœã±ãããæäœããã«ã¯
ãããã£ãŒ . - Java ã¢ããªã±ãŒã·ã§ã³ã¯ Java 8 ã§æžãããŠããããã³ãã«ã§æ§æãããŠããŸãã
OSGi ã èšç»ã«ã¯ãJava 10 ãžã®ç§»è¡ãšã¢ãžã¥ãŒã«ãžã®ç§»è¡ãå«ãŸããŸãã
éçºãšãã¹ã
SV ã®éçºãšãã¹ãã®éçšã§ãç§ãã¡ã¯äœ¿çšããŠãã補åã®å€ãã®èå³æ·±ãæ©èœã«æ°ã¥ããŸããã
è² è·ãã¹ããšã¡ã¢ãªãªãŒã¯
å SV ãªãªãŒã¹ã®ãªãªãŒã¹ã«ã¯è² è·ãã¹ããå«ãŸããŸãã 次ã®å Žåã«æåããŸãã
- ãã¹ãã¯æ°æ¥éæ©èœãããµãŒãã¹é害ã¯çºçããŸããã§ãã
- ããŒæäœã®å¿çæéã¯å¿«é©ãªãããå€ãè¶ ããŸããã§ãã
- åããŒãžã§ã³ãšæ¯èŒããããã©ãŒãã³ã¹ã®äœäžã¯ 10% æªæº
ãã¹ã ããŒã¿ããŒã¹ã«ããŒã¿ãå ¥åããŸãããããè¡ãããã«ãéçšãµãŒããŒããæãã¢ã¯ãã£ããªãµãã¹ã¯ã©ã€ããŒã«é¢ããæ å ±ãåãåãããã®æ°å€ã 5 (ã¡ãã»ãŒãžããã£ã¹ã«ãã·ã§ã³ããŠãŒã¶ãŒã®æ°) ã§ä¹ç®ãããã®æ¹æ³ã§ãã¹ãããŸãã
ã€ã³ã¿ã©ã¯ã·ã§ã³ ã·ã¹ãã ã®è² è·ãã¹ãã¯ã次㮠XNUMX ã€ã®æ§æã§å®è¡ããŸãã
- ã¹ãã¬ã¹ãã¹ã
- æ¥ç¶ã®ã¿
- 賌èªè ç»é²
ã¹ãã¬ã¹ ãã¹ãäžãæ°çŸã®ã¹ã¬ãããèµ·åãããã¡ãã»ãŒãžã®æžã蟌ã¿ããã£ã¹ã«ãã·ã§ã³ã®äœæãã¡ãã»ãŒãžã®ãªã¹ãã®åä¿¡ãªã©ãåæ¢ããããšãªãã·ã¹ãã ãããŒããããŸãã éåžžã®ãŠãŒã¶ãŒã®ã¢ã¯ã·ã§ã³ (æªèªã¡ãã»ãŒãžã®ãªã¹ããååŸããã誰ãã«æžã蟌ã) ãšãœãããŠã§ã¢ ãœãªã¥ãŒã·ã§ã³ (ç°ãªãæ§æã®ããã±ãŒãžãéä¿¡ãããã¢ã©ãŒããåŠçãã) ãã·ãã¥ã¬ãŒãããŸãã
ããšãã°ãã¹ãã¬ã¹ ãã¹ãã®äžéšã¯æ¬¡ã®ããã«ãªããŸãã
- ãŠãŒã¶ãŒã®ãã°ã€ã³
- æªèªã®ãã£ã¹ã«ãã·ã§ã³ããªã¯ãšã¹ãããŸã
- 50% ã®ç¢ºçã§ã¡ãã»ãŒãžãèªã
- 50% ã®ç¢ºçã§ããã¹ãã¡ãã»ãŒãžãéä¿¡ãã
- 次ã®ãŠãŒã¶ãŒ:
- 20% ã®ç¢ºçã§æ°ãããã£ã¹ã«ãã·ã§ã³ãäœæããã
- ãã£ã¹ã«ãã·ã§ã³ã®ãããããã©ã³ãã ã«éžæããŸã
- äžã«å ¥ããŸã
- ãªã¯ãšã¹ãã¡ãã»ãŒãžããŠãŒã¶ãŒãããã¡ã€ã«
- ãã®ãã£ã¹ã«ãã·ã§ã³ããã©ã³ãã ãªãŠãŒã¶ãŒã«å®ãŠã XNUMX ã€ã®ã¡ãã»ãŒãžãäœæããŸã
- ãã£ã¹ã«ãã·ã§ã³ãçµäºããŸã
- 20åç¹°ãè¿ããŸã
- ãã°ã¢ãŠãããã¹ã¯ãªããã®å é ã«æ»ããŸã
- ãã£ããããããã·ã¹ãã ã«äŸµå
¥ããŸã (ã¢ããªã±ãŒã·ã§ã³ ã³ãŒãããã¡ãã»ãŒãžã³ã°ããšãã¥ã¬ãŒãããŸã)
- 50% ã®ç¢ºçã§ããŒã¿äº€æçšã®æ°ãããã£ãã«ãäœæãã (ç¹å¥ãªè°è«)
- 50% ã®ç¢ºçã§æ¢åã®ãã£ãã«ã®ããããã«ã¡ãã»ãŒãžãæžã蟌ã
ãæ¥ç¶ã®ã¿ãã·ããªãªãç»å Žããã®ã«ã¯çç±ããããŸãã ãŠãŒã¶ãŒãã·ã¹ãã ã«æ¥ç¶ããŠãããããŸã åå ããŠããªããšããç¶æ³ããããŸãã åãŠãŒã¶ãŒã¯æ 09 æã«ã³ã³ãã¥ãŒã¿ãŒã®é»æºãå ¥ãããµãŒããŒãžã®æ¥ç¶ã確ç«ããæ²é»ãããŸãŸã«ãªããŸãã ããã€ãã¯å±éºã§ãããããããŸãã圌ããæã£ãŠããããã±ãŒãžã¯ PING/PONG ã ãã§ããããµãŒããŒãžã®æ¥ç¶ãç¶æããŸã (æ¥ç¶ãç¶æããããšã¯ã§ããŸãããæ°ããã¡ãã»ãŒãžããã£ããã©ãããŸãã)ã ãã®ãã¹ãã§ã¯ãå€æ°ã®ãã®ãããªãŠãŒã¶ãŒã 00 å以å ã«ã·ã¹ãã ã«ãã°ã€ã³ããããšããç¶æ³ãåçŸããŸãã ããã¯ã¹ãã¬ã¹ãã¹ãã«äŒŒãŠããŸããããã®çŠç¹ã¯ãŸãã«ãã®æåã®å ¥åã«ãããŸãããã®ããã倱æã¯ãããŸããïŒäººã¯ã·ã¹ãã ã䜿çšããŠãããããã§ã«èœã¡ãŠããŸããããããæªãããšãèããã®ã¯å°é£ã§ãïŒã
ãµãã¹ã¯ã©ã€ãç»é²ã¹ã¯ãªããã¯ãæåã®èµ·åããéå§ãããŸãã ã¹ãã¬ã¹ãã¹ããå®æœããéä¿¡äžã«ã·ã¹ãã ã®é床ãäœäžããªãããšã確èªããŸããã ãããããŠãŒã¶ãŒããã£ãŠæ¥ãŠãã¿ã€ã ã¢ãŠãã®ããã«ç»é²ã倱æãå§ããŸããã ç»é²æã«äœ¿çšããã®ã¯ã
ããŒããžã§ãã¬ãŒã¿ãšããŠäœ¿çšããŸã
ããããå§ããããšã«ããŸããã
æ¬æ Œçãªãã¹ããéå§ããçŽåŸã«ãJMeter ãã¡ã¢ãª ãªãŒã¯ãéå§ããããšãããããŸããã
ãã®ãã©ã°ã€ã³ã¯å¥ã®å€§ããªè©±ã§ãã¹ã¿ãŒã 176 åãããgithub ã«ã¯ 132 åã®ãã©ãŒã¯ããããŸãã äœè
èªèº«ã¯ 2015 幎以éãã®åé¡ã«ã³ãããããŠããŸãã (2015 幎ã«å®è¡ããŸãããããã®æã¯çæã¯çããŸããã§ãã)ãã¡ã¢ãª ãªãŒã¯ã«é¢ããããã€ãã® github ã®åé¡ã7 件ã®æªå®äºã®ãã« ãªã¯ãšã¹ãããããŸãã
ãã®ãã©ã°ã€ã³ã䜿çšããŠè² è·ãã¹ããå®è¡ããå Žåã¯ã次ã®è°è«ã«æ³šæããŠãã ããã
- ãã«ãã¹ã¬ããç°å¢ã§ã¯ãéåžžã® LinkedList ã䜿çšãããçµæã¯æ¬¡ã®ããã«ãªããŸããã
NPE å®è¡æã ããã¯ãConcurrentLinkedDeque ã«åãæ¿ããããåæããããããã¯ã«ãã£ãŠè§£æ±ºã§ããŸãã ç§ãã¡ã¯æåã®ãªãã·ã§ã³ãèªåãã¡ã§éžæããŸãã (https://github.com/maciejzaleski/JMeter-WebSocketSampler/issues/43 ). - ã¡ã¢ãªãªãŒã¯; åææã«æ¥ç¶æ
å ±ãåé€ãããªã (
https://github.com/maciejzaleski/JMeter-WebSocketSampler/issues/44 ). - ã¹ããªãŒãã³ã° ã¢ãŒã (WebSocket ããµã³ãã«ã®æåŸã«éãããããèšç»ã®åŸåã§äœ¿çšãããå Žå) ã§ã¯ãå¿çãã¿ãŒã³ã¯æ©èœããŸãã (
https://github.com/maciejzaleski/JMeter-WebSocketSampler/issues/19 ).
ãã㯠github ã«ãããã®ã® XNUMX ã€ã§ãã æã ã®ããããšïŒ
- åã£ã
ãã©ãŒã¯ãšãªã©ã³ã»ã³ãŒã¬ã³ (@elyrank) â åé¡ 1 ãš 3 ãä¿®æ£ããŸã - 解決ãããåé¡ 2
- æ¡æ©ã 9.2.14 ãã 9.3.12 ã«æŽæ°ããŸãã
- SimpleDateFormat ã ThreadLocal ã«ã©ããããŸããã SimpleDateFormat ã¯ã¹ã¬ããã»ãŒãã§ã¯ãªããããå®è¡æã« NPE ãçºçããŸã
- å¥ã®ã¡ã¢ãª ãªãŒã¯ãä¿®æ£ããŸãã (åææã«æ¥ç¶ãæ£ããéããããŸããã§ãã)
ããã§ããããã¯æµããŸãïŒ
èšæ¶åã¯XNUMXæ¥ã§ã¯ãªãXNUMXæ¥ã§ãªããªãå§ããã æéããŸã£ããæ®ã£ãŠããªãã£ããããã¹ã¬ããã®æ°ãæžããããšãŒãžã§ã³ãã XNUMX ã€ç«ã¡äžããããšã«ããŸããã å°ãªããšãäžé±éã¯ããã§ååã ããã
XNUMXæ¥ãçµã¡ãŸããâŠ
çŸåšãHazelcast ã®ã¡ã¢ãªãäžè¶³ããŠããŸãã ãã°ã«ãããšãæ°æ¥éã®ãã¹ãã®åŸãHazelcast ãã¡ã¢ãªäžè¶³ã«ã€ããŠäžå¹³ãèšãå§ãããã°ãããããšã¯ã©ã¹ã¿ãŒã厩å£ããããŒãã XNUMX ã€ãã€åæ¢ãç¶ããŸããã JVisualVM ã hazelcast ã«æ¥ç¶ãããšããã©ã€ãžã³ã° ãœãŒãã衚瀺ãããŸãããããã¯å®æçã« GC ãåŒã³åºããŸããããã¡ã¢ãªãã¯ãªã¢ã§ããŸããã§ããã
hazelcast 3.4 ã§ã¯ãããã/multiMap (map.destroy()) ãåé€ãããšãã«ãã¡ã¢ãªãå®å
šã«è§£æŸãããªãããšãå€æããŸããã
ãã®ãã°ã¯çŸåš 3.5 ã§ä¿®æ£ãããŠããŸãããåœæã¯åé¡ã§ããã åçãªååãæã€æ°ãã multiMap ãäœæããããžãã¯ã«åŸã£ãŠåé€ããŸããã ã³ãŒãã¯æ¬¡ã®ããã«ãªããŸããã
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 ã¯ãµãã¹ã¯ãªãã·ã§ã³ããšã«äœæãããäžèŠã«ãªã£ãå Žåã¯åé€ãããŸããã Mapãå§ããããšã«ããŸãããããŒã¯ãµãã¹ã¯ãªãã·ã§ã³ã®ååãå€ã¯ã»ãã·ã§ã³èå¥åã«ãªããŸã (å¿ èŠã«å¿ããŠããããããŠãŒã¶ãŒèå¥åãååŸã§ããŸã)ã
public void join(Authentication auth, String sub) {
addValueToMap(sub, auth.getSessionId());
}
public void leave(Authentication auth, String sub) {
removeValueFromMap(sub, auth.getSessionId());
}
ãã£ãŒããæ¹åãããŸããã
è² è·ãã¹ãã«ã€ããŠä»ã«äœãåŠãã ã§ãããã?
- JSR223 㯠Groovy ã§èšè¿°ããã³ã³ãã€ã« ãã£ãã·ã¥ãå«ããå¿
èŠããããŸããããã¯ã¯ããã«é«éã§ãã
ãªã³ã¯ . - Jmeter-Plugins ã®ã°ã©ãã¯æšæºã®ãã®ãããç解ããããã§ãã
ãªã³ã¯ .
Hazelcast ã®çµéšã«ã€ããŠ
Hazelcast ã¯ç§ãã¡ã«ãšã£ãŠæ°ãã補åã§ãããŒãžã§ã³ 3.4.1 ãã䜿ãå§ããŸããããçŸåšãæ¬çªãµãŒããŒã¯ããŒãžã§ã³ 3.9.2 ãå®è¡ããŠããŸã (ãã®èšäºã®å·çæç¹ã§ã® Hazelcast ã®ææ°ããŒãžã§ã³ã¯ 3.10)ã
IDã®çæ
ç§ãã¡ã¯æŽæ°ã®èå¥åããå§ããŸããã æ°ãããšã³ãã£ãã£ã«å¥ã® Long ãå¿ èŠã ãšæ³åããŠã¿ãŸãããã ããŒã¿ããŒã¹å ã®é åºãé©åã§ã¯ãããŸãããããŒãã«ãã·ã£ãŒãã£ã³ã°ã«é¢äžããŠããŸããDB1 ã«ã¯ã¡ãã»ãŒãž ID=1 ããããDB1 ã«ã¯ã¡ãã»ãŒãž ID=2 ãããããšãããããŸãããã® ID ã Elasticsearch ã«ã Hazelcast ã«ãå ¥ããããšã¯ã§ããŸããããã ããææªã®å Žåã¯ã1 ã€ã®ããŒã¿ããŒã¹ã®ããŒã¿ã 10 ã€ã«çµåããå Žåã§ã (ããšãã°ããããã®ãµãã¹ã¯ã©ã€ããŒã«ã¯ 000 ã€ã®ããŒã¿ããŒã¹ã§ååã§ãããšå€æããå Žå)ã ããã€ãã® AtomicLong ã Hazelcast ã«è¿œå ããããã«ã«ãŠã³ã¿ãŒãä¿æãããšãæ°ãã ID ãååŸããããã©ãŒãã³ã¹ã¯ãincrementAndGet ã« Hazelcast ãžã®ãªã¯ãšã¹ãã®æéãå ãããã®ã«ãªããŸãã ããããHazelcast ã«ã¯ãââãæé©ãªãã®ãFlakeIdGenerator ããããŸãã åã¯ã©ã€ã¢ã³ãã«é£çµ¡ãããšããæåã®ã¯ã©ã€ã¢ã³ãã«ã¯ 10 ïœ 001ã20 çªç®ã«ã¯ 000 ïœ XNUMX ãªã©ã® ID ç¯å²ãäžããããŸãã ããã§ãã¯ã©ã€ã¢ã³ãã¯ãçºè¡ãããç¯å²ãçµäºãããŸã§ãç¬èªã«æ°ããèå¥åãçºè¡ã§ããããã«ãªããŸãã åäœã¯é«éã§ãããã¢ããªã±ãŒã·ã§ã³ (ããã³ Hazelcast ã¯ã©ã€ã¢ã³ã) ãåèµ·åãããšãæ°ããã·ãŒã±ã³ã¹ãéå§ããããããã¹ããããªã©ãçºçããŸãã ããã«ãéçºè ã¯ãID ãæŽæ°ã§ããã«ãããããããéåžžã«äžè²«æ§ããªãçç±ãå®éã«ã¯ç解ããŠããŸããã ãã¹ãŠãæ¯èŒæ€èšããUUID ã«åãæ¿ããŸããã
ã¡ãªã¿ã«ãTwitter ã®ããã«ãªããã人ã®ããã«ãSnowcast ã©ã€ãã©ãªããããŸãããã㯠Hazelcast ã®äžã« Snowflake ãå®è£ ãããã®ã§ãã ããã§èŠãããšãã§ããŸã:
ããããç§ãã¡ã¯ããããã«ã¯æãä»ããŠããŸããã
TransactionalMap.replace
ãã XNUMX ã€ã®é©ã: 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 ã«èšé²ããããšã«ããŸããã ããšãã°ãApplication ã¯ã©ã¹ãããã®ã§ããããä¿åããŠèªã¿åããããšããŸãã ä¿åïŒ
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 ãåãåãå§ããŸããã Hazelcast ã¯ã€ã³ããã¯ã¹ã«è¿œå ããããšããŸããããç§ãã¡ã®ã¯ã©ã¹ã«ã€ããŠäœãç¥ããªãã£ãã®ã§ããã®ã¯ã©ã¹ã® JAR ãæäŸãããããšãæãã§ããŸããã ããã ãã§ãã¹ãŠããŸããããŸããããã¯ã©ã¹ã¿ãŒãå®å šã«åæ¢ããã« JAR ãæŽæ°ããã«ã¯ã©ãããã°ããããšããæ°ããªåé¡ãçºçããŸããã Hazelcast ã¯ãããŒãããšã®æŽæ°äžã«æ°ãã JAR ãååŸããŸããã ãã®æç¹ã§ãã€ã³ããã¯ã¹æ€çŽ¢ãªãã§ãçããŠããããšå€æããŸããã çµå±ã®ãšãããHazelcast ã Key-Value ã¹ãã¢ãšããŠäœ¿çšããã°ããã¹ãŠãæ©èœããã®ã§ãããã? ããŸãã ããã§ããIMap ãš TransactionalMap ã®åäœã¯ç°ãªããŸãã IMap ãæ°ã«ããªãå ŽåãTransactionalMap ã¯ãšã©ãŒãã¹ããŒããŸãã
Iãããã 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 ã§ã¯ããŠãŒã¶ãŒ ã¯ã©ã¹ ãããã€ã¡ã³ã ã¡ã«ããºã ãç»å ŽããŸããã XNUMX ã€ã®ãã¹ã¿ãŒ ããŒããæå®ãããã®ããŒãäžã§ JAR ãã¡ã€ã«ãæŽæ°ã§ããŸãã
çŸåšãç§ãã¡ã¯ã¢ãããŒããå®å šã«å€æŽããŸãããç§ãã¡ã¯ãããèªåãã¡ã§ JSON ã«ã·ãªã¢ã«åããHazelcast ã«ä¿åããŸãã Hazelcast ã¯ã¯ã©ã¹ã®æ§é ãç¥ãå¿ èŠããªããããããŠã³ã¿ã€ã ãªãã§æŽæ°ã§ããŸãã ãã¡ã€ã³ ãªããžã§ã¯ãã®ããŒãžã§ã³ç®¡çã¯ã¢ããªã±ãŒã·ã§ã³ã«ãã£ãŠå¶åŸ¡ãããŸãã ç°ãªãããŒãžã§ã³ã®ã¢ããªã±ãŒã·ã§ã³ãåæã«å®è¡ãããå¯èœæ§ããããæ°ããã¢ããªã±ãŒã·ã§ã³ãæ°ãããã£ãŒã«ããæã€ãªããžã§ã¯ããæžã蟌ãããå€ãã¢ããªã±ãŒã·ã§ã³ããããã®ãã£ãŒã«ãããŸã èªèããŠããªããšããç¶æ³ãçºçããå¯èœæ§ããããŸãã åæã«ãæ°ããã¢ããªã±ãŒã·ã§ã³ã¯ãå€ãã¢ããªã±ãŒã·ã§ã³ã«ãã£ãŠæžã蟌ãŸãããæ°ãããã£ãŒã«ããæããªããªããžã§ã¯ããèªã¿åããŸãã ãã®ãããªç¶æ³ã¯ã¢ããªã±ãŒã·ã§ã³å ã§åŠçããŸãããç°¡åã«ããããã«ãã£ãŒã«ãã®å€æŽãåé€ã¯è¡ãããæ°ãããã£ãŒã«ããè¿œå ããŠã¯ã©ã¹ãæ¡åŒµããã ãã§ãã
é«ãããã©ãŒãã³ã¹ãä¿èšŒããæ¹æ³
Hazelcast ãžã® XNUMX åã®æ è¡ - è¯ããããŒã¿ããŒã¹ãžã® XNUMX åã®æ è¡ - æªã
ããŒã¿ããã£ãã·ã¥ã«ä¿åããæ¹ããããŒã¿ããŒã¹ã«ä¿åãããããåžžã«åªããŠããŸãããæªäœ¿çšã®ã¬ã³ãŒããä¿åããããšãæãŸãããããŸããã äœããã£ãã·ã¥ãããã«ã€ããŠã®æ±ºå®ã¯ãéçºã®æçµæ®µéãŸã§æ®ãããŸãã æ°ããæ©èœãã³ãŒãã£ã³ã°ããããšãPostgreSQL ã®ãã¹ãŠã®ã¯ãšãªã®ãã°èšé²ããªã³ã«ãªã (log_min_duration_statement ã 0 ã«)ãè² è·ãã¹ãã 20 åéå®è¡ãããŸããåéããããã°ã䜿çšããŠãpgFouine ã pgBadger ãªã©ã®ãŠãŒãã£ãªãã£ã§åæã¬ããŒããäœæã§ããŸãã ã¬ããŒãã§ã¯ãäž»ã«äœéã§é »ç¹ãªã¯ãšãªãæ¢ããŸãã é ãã¯ãšãªã®å Žåã¯ãå®è¡èšç» (EXPLAIN) ãæ§ç¯ãããã®ãããªã¯ãšãªãé«éåã§ãããã©ãããè©äŸ¡ããŸãã åãå ¥åããŒã¿ã«å¯Ÿããé »ç¹ãªãªã¯ãšã¹ãã¯ãã£ãã·ã¥ã«ããŸãåãŸããŸãã ã¯ãšãªãããã©ãããã«ä¿ã¡ãã¯ãšãªããšã« XNUMX ã€ã®ããŒãã«ãä¿æããããã«åªããŸãã
æŸå
ãªã³ã©ã€ã³ãµãŒãã¹ãšããŠã®SVã¯2017幎æ¥ã«çšŒåããåäœè£œåãšããŠã¯2017幎XNUMXæã«SVããªãªãŒã¹ãããŸããïŒåœæã¯ããŒã¿çã®ç¶æ ïŒã
XNUMX 幎以äžã®éçšã«ãããŠãCB ãªã³ã©ã€ã³ ãµãŒãã¹ã®éçšã«é倧ãªåé¡ã¯çºçããŠããŸããã ãªã³ã©ã€ã³ ãµãŒãã¹ãç£èŠããã«ã¯ã
SV ãµãŒããŒã®ãã£ã¹ããªãã¥ãŒã·ã§ã³ã¯ããã€ãã£ã ããã±ãŒãž (RPMãDEBãMSI) ã®åœ¢åŒã§æäŸãããŸãã ããã«ãWindows ã®å Žåã¯ããµãŒããŒãHazelcastãããã³ Elasticsearch ã XNUMX å°ã®ãã·ã³ã«ã€ã³ã¹ããŒã«ãã XNUMX ã€ã®ã€ã³ã¹ããŒã©ãŒã XNUMX ã€ã® EXE 圢åŒã§æäŸããŸãã åœåããã®ããŒãžã§ã³ã®ã€ã³ã¹ããŒã«ãããã¢ãããŒãžã§ã³ãšåŒãã§ããŸãããããããæãäžè¬çãªå°å
¥ãªãã·ã§ã³ã§ããããšãæããã«ãªããŸããã
åºæïŒ habr.com