ç§ã®äŒç€Ÿã«ã¯åæã«è€æ°ã®ã¹ã¿ãžãªãããããããã®åã¹ã¿ãžãªã®åã²ãŒã ãããžã§ã¯ãã®å質ãç¶æããããã«ãäºãã«ç¬ç«ããŠã¹ãã¬ã¹ãã¹ããå®è¡ããå¿ èŠããããŸããããã«ããããã®ããžãã¹ãæ倧éã«èªååããæåã«ããåå ãæå°éã«æããå¿ èŠãçããŸããã
ç§ã®é ã®äžã®ã¹ãã¬ã¹ãã¹ãã®ããã»ã¹ã¯ãããã€ãã®æ®µéã«åãããŠããŸãã

æåã®3ã€ã®ã¹ãããã¯ãåã«ã·ã¹ãã åæãšã¹ã¯ãªããéçºã§ãã 次ã«ãæãéå±ã§é·ãå埩段éãå§ãŸããŸããã€ãŸããããèªäœããã¹ãããçµæãåæããŸãããã®çµæãçµæã«å¿ããŠãæãèå³æ·±ãéšåã§ãããã¥ãŒãã³ã°ã«é²ã¿ãŸãã
ãã ãããã¥ãŒãã³ã°ãã§ãŒãºã«ã¯æ°åããããŸãããçµæãæ°æéåŸ æ©ããŸãã 次ã«ãçµæãåéããŠåæããå¿ èŠããããŸãããæè¿ã§ã¯å€ãã®æäœæ¥ãå¿ èŠã«ãªããŸããããå®éã«ã¯ãããã»ã¹å šäœãããèå³æ·±ããã®ã«æžããããã«ãã¹ã¯ãªããéçºãšãã¥ãŒãã³ã°ãåãé€ãå¿ èŠããããŸããã
ãœãŒã¹ããŒã¿
è² è·ãã¹ãã®ããŒã«ãšããŠãïŒåœç¶ïŒ Apache Jmeterã䜿çšããŸãã
Innogamesãããžã§ã¯ãã¯ãhttpãwebsocketãprotobufãprotobuf + STOMPãããã«ã¯udpãªã©ããã®è£œåã䜿çšããŠïŒãã¡ãããå€ãã®å Žåãç¬èªã®è¿œå ãã©ã°ã€ã³ã䜿çšããŠïŒç°¡åã«ãšãã¥ã¬ãŒãã§ããããŸããŸãªãããã³ã«ã䜿çšããŸãã ãŸããåªããè² è·åæ£ã·ã¹ãã ã®ãããã§ãå¿ èŠãªæ°ã®VUïŒä»®æ³ãŠãŒã¶ãŒïŒãšãã©ãã£ãã¯ãç°¡åã«ãšãã¥ã¬ãŒãã§ããŸãã ããšãã°ããããããžã§ã¯ãã§ã¯ã65k VUãäžããŠ3000ãªã¯ãšã¹ã/ç§ãçæããå¿ èŠããããŸããã
åœç¶ããã¹ãŠã®ãã¡ãã·ã§ã³ãªãã£ã¹ãšåæ§ã«ãJenkins CIã䜿çšããŠãã¹ããå®è¡ãå§ããŸããã ããããçµæã®åæã«é¢ããåé¡ããããŠæãéèŠãªããšã«ã¯ãçµæãšä»¥åã®ãã¹ãã®çµæãšã®æ¯èŒã¯éåžžã«é¢é£æ§ããããŸããã ãªã³ã©ã€ã³ç£èŠã®åé¡ãšåæ§ã«ããã¹ãã¯ãã¡ããã³ã³ãœãŒã«ã¢ãŒãã§å®è¡ãããjmeterããã®ã³ã³ãœãŒã«åºåãããããŸããããã°ã©ããå¿ èŠã§ãã
æåã¯ããœãªã¥ãŒã·ã§ã³ãã©ã®ããã«ããŸãæ©èœãããJenkinsã®ããã©ãŒãã³ã¹ãã©ã°ã€ã³ ã ããããåãããžã§ã¯ãã®ãã¹ãæ°ã®å¢å ãšåæçšã®éåžžã«å€§ããªãã¡ã€ã«ã®åºçŸã«ããïŒ3000ãªã¯ãšã¹ã/ç§ã®3æéãã¹ãã§ã¯4Gb + CSVãã¡ã€ã«ãçæãããŸãïŒããã®ãã©ã°ã€ã³ã¯æ°æéåäœãå§ããjenkinsã§OOMã«èœã¡ãŸããã
ãããžã§ã¯ããããŒã¿ãå©å®³é¢ä¿è ã®æ°ãå¢ããäœããããå¿ èŠããããŸããã
åæ決å®
æ¢è£œã®ãœãªã¥ãŒã·ã§ã³
ããã«ãã®ã¹ã¯ãªãããžã®ãªã³ã¯ããããŸãããããèŠãŠã¯ãããŸããã
ãã°ããã®éãããã§åé¡ã¯è§£æ±ºããŸããã ããããããã¯éåžžã«æªã決å®ã§ãããããŒã«ã«CSVãã¡ã€ã«ãèªã¿åããã¿ãã¬ãããäœæããå€æ°ã®ããŒããããç»åãšJavaã¹ã¯ãªããããããŸããã
ããæç¹ã§ãã¬ããŒãã¯é·æéïŒæ°åïŒèªã¿èŸŒãŸãå§ããã¿ããªãæ¿æãããæåãªSaaSã®1ã€ã§ããè² è·ãã¹ããããã€ããŒãšã®ã³ã©ãã¬ãŒã·ã§ã³ãæ€èšããããšãææ¡ããŸãã-ãã®ãµãŒãã¹ã¯ç¡æã®Jmeterã䜿çšããè² è·çæã«åºã¥ããŠããŸããã圌ãã¯ãã®ããžãã¹ãå€é¡ã®ãéã§å£²ãããã¹ããå®è¡ããŠçµæãåæããããã®äŸ¿å©ãªç°å¢ãæäŸããŸãã ç§ã¯ãããã®ãµãŒãã¹ã¯ããŸã奜ãã§ã¯ãããŸããããåãJmeterïŒããšãã°ãBlazeMeterïŒã«å¯ŸããŠã¯å€ãã®ããšãããŸãã
éæšæºãããã³ã«ããšãã¥ã¬ãŒãããŠå€æ°ã®VUãçºçãããæ¹æ³ãç解ã§ããªãã£ããšèšããªããã°ãªããŸããããããããã¹ãŠã®ã°ã©ããšã¬ããŒãã䜿çšããè² è·ãã¹ãã®äŸ¿å©ãªç°å¢ã®ã¢ã€ãã¢ãš ãå€ãã®äººãåæã«äœ¿çšã§ãããšããäºå®ã奜ãã§ããã
ãã³ãã念é ã«çœ®ããŠãç§ã¯èªåã®ãœãªã¥ãŒã·ã§ã³ãè©ŠããŠã¿ãããšã«ããŸããã
解決ç
æåŸã«ãã¡ã€ã³ãããã¯ã«é²ã¿ãŸãã ããªãã®è©Šè¡é¯èª€ã®äžã§ãDjangoãHTMLãjavaã¹ã¯ãªãããªã©ã®ç 究ãéã㊠ã次ã®ãœãªã¥ãŒã·ã§ã³ãçãŸããŸããããããInnogames Load Testing Center ïŒä»¥äžã LTC ïŒãšåŒã³ãŸãã
äŒç€Ÿã®å ¬åŒGitããã§ããJmeter Load Testing Centerããããããžã§ã¯ãã®éçºã«ããŠã³ããŒãããŠåå ã§ããŸãïŒããã«ã¯å€ãã®è¯ãããšããããŸãïŒã
ããã¯Django Webã¢ããªã±ãŒã·ã§ã³ã§ãããPostgresã䜿çšããŠããŒã¿ãä¿åããŸãã pandasã¢ãžã¥ãŒã«ã¯ãããŒã¿ãã¡ã€ã«ã®åæã«äœ¿çšãããŸãã
次ã®äž»èŠã³ã³ããŒãã³ãã§æ§æãããŸãïŒDjangoèšèª-ã¢ããªã±ãŒã·ã§ã³ïŒã
- ããã·ã¥ããŒãã¯ãææ°ã®å®è¡äžã®ãã¹ãã«é¢ããäžè¬æ å ±ãèšèŒãããããã³ãããŒãžã§ãã
- ã¢ãã©ã€ã¶ãŒ -ããã§ã¬ããŒããäœæãããã¹ãçµæãåæããŸã
- ãªã³ã©ã€ã³ -ãã¹ãããªã³ã©ã€ã³ã§èŠãããšãã§ããŸã
- ã³ã³ãããŒã©ãŒ -ããã§ããã¹ããæ§æããã³å®è¡ã§ããŸãïŒéçºäžïŒ
- 管çè -ããŸããŸãªãã©ã¡ãŒã¿ãŒ/å€æ°ãæ§æããŸãã
çŸæç¹ã§ã¯ãJenkinsã¯ã©ãã«ãè¡ã£ãŠããŸãããControllerã¢ããªã±ãŒã·ã§ã³ã¯ãŸã éçºäžã§ãã ããããããã«ãžã§ã³ãã³ã¹ã亀æãããå¯èœæ§ããããŸãã
ãããã£ãŠãHansãšããååã®ãŠãŒã¶ãŒããã¹ããå®è¡ããå ŽåãJenkinsããããžã§ã¯ããéžæããŠéããéå§ãæŒããŸãã

ãã®åŸãJenkinsã¯ã¡ã€ã³ãµãŒããŒäžã§ã¡ã€ã³ã®Jmeterã€ã³ã¹ã¿ã³ã¹ãèµ·åãïŒJenkinsãšLTCèªäœãé 眮ãããŠããadmin.loadtestãšåŒã³ãŸãïŒãå¿ èŠãªéã®1ã€ä»¥äžã®ãªã¢ãŒãä»®æ³ãã·ã³äžã®JmeterãµãŒããŒïŒããã«ã€ããŠã¯åŸã§èª¬æããŸãïŒãå®éã«èµ·åããŸããã¹ãããã»ã¹ã
ãã¹ãäžã«ãJMeterã®çµæãå«ãCSVãã¡ã€ã«ãäœæããããããžã§ã¯ãã®$ WORKSPACEãã©ã«ããŒå ã®ããŒã¿ãšããªã¢ãŒããã¹ãã®ç£èŠããŒã¿ãå«ãå¥ã®CSVãã¡ã€ã«ã§æŽæ°ãããŸãã
ãã®åŸãHansã¯LTCãéãããã¹ããã¹ããªã³ã©ã€ã³ã§èŠãããšãã§ããŸãã ïŒãã®æç¹ã§ãã¢ããªã±ãŒã·ã§ã³ã¯åè¿°ã®CSVãã¡ã€ã«ã解æããããããOnlineãã°ã©ããæãããŒã¿ããŒã¹å ã®äžæããŒãã«ã«é 眮ããŸãã

ãŸãã¯ãåãHansã¯ãã¹ãã®çµäºãŸã§åŸ æ©ã§ããŸãããã¹ãã®çµäºæã«ãç¹å¥ãªã¹ã¯ãªãããããŒã¿ããŒã¹å ã®ãã¹ãŠã®ããŒã¿ãåéããåæããã³ä»ã®çµæãšã®æ¯èŒã«ã¢ãã©ã€ã¶ãŒã§äœ¿çšã§ããŸãã

æåŸã®åé¡ã¯æ®ã£ãŠããŸãïŒããã€ãã®ãããžã§ã¯ããããããããžã§ã¯ãã¯è² è·ãéã¶ããã«ç°ãªã容éãå¿ èŠãšããŸãïŒèªã¿åããç°ãªãæ°ã®VUããšãã¥ã¬ãŒãããŸãïŒããŠãŒã¶ãŒã¯ããããåæã«å®è¡ã§ããŸãããããªããããããŸããã ãã¹ãŠã®å©çšå¯èœãª10ã®ä»®æ³ãã·ã³ãžã§ãã¬ãŒã¿ãŒãé åžããæ¹æ³ã åãããžã§ã¯ããç¹å®ã®ãžã§ãã¬ãŒã¿ãŒïŒåœåïŒã«å²ãåœãŠãããã¹ã±ãžã¥ãŒã«ãèšå®ããããJenkinsã®ããããã³ã°ãã©ã°ã€ã³ã䜿çšããããäœãé¢çœãããšããããã§ããŸãã 以äžã«ã€ããŠã
äžè¬çãªããã€ã¹
ç§ãèšã£ãããã«ãããã¯ãšã³ãã¯Djangoãã¬ãŒã ã¯ãŒã¯ã§æžãããŠããŸãã ããã³ããšã³ãã®éçºã§ã¯ããã¹ãŠã®æšæºã©ã€ãã©ãªjqueryãšbootstrapã䜿çšããŸããã ã°ã©ããšããŠãåãåã£ãããŒã¿ãJSON圢åŒã§ç°¡åã«æç»ãããœãªã¥ãŒã·ã§ã³ãå¿ èŠã§ããã C3.jsã¯ãããããŸãåŠçããŸãã
ããŒã¿ããŒã¹ã®ããŒãã«ã«ã¯ãéåžžãããŒãã¢ãšJSONFieldïŒïŒããŒã¿åã®1ã€ã®ãã£ãŒã«ãããããŸãã JSONFieldã䜿çšãããã®ã¯ããã®åŸãæ§é ãå€æŽããã«ãã®ããŒãã«ã«æ°ããã¡ããªãã¯ãç°¡åã«è¿œå ã§ããããã§ãã
ãããã£ãŠã1ã€ã®ãã¹ãäžã«å¿çæéããšã©ãŒã®æ°ãªã©ã®ããŒã¿ãä¿åããå žåçãªã¢ãã«ã¯éåžžã«åçŽã«èŠããŸãã
class TestData(models.Model): test = models.ForeignKey(Test) data = JSONField() class Meta: db_table = 'test_data'
ããŒã¿ãã£ãŒã«ãã®ããŒã¿èªäœã¯ããããã1åéã«éçŽãããæ å ±ãä¿åããJSONã§ãã

ãã®ããŒãã«ããããŒã¿ãæœåºããããã«ãurls.pyãã¡ã€ã«ã«ã¯ããã®ããŒã¿ãåŠçããèªã¿ãããJSONãè¿ãé¢æ°ãåŒã³åºããšã³ããã€ã³ãã1ã€ãããŸãã
ãšã³ããã€ã³ãïŒ
url(r'^test/(?P<test_id>\d+)/rtot/$', views.test_rtot),
æ©èœïŒ
def test_rtot(request, test_id): # timestamp min_timestamp = TestData.objects. \ filter(test_id=test_id). \ values("test_id").\ aggregate(min_timestamp=Min( RawSQL("((data->>%s)::timestamp)", ('timestamp',))))['min_timestamp'] # , min_timestamp, , timestamp, JSON . d = TestData.objects. \ filter(test_id=test_id). \ annotate(timestamp=(RawSQL("((data->>%s)::timestamp)", ('timestamp',)) - min_timestamp)). \ annotate(average=RawSQL("((data->>%s)::numeric)", ('avg',))). \ annotate(median=RawSQL("((data->>%s)::numeric)", ('median',))). \ annotate(rps=(RawSQL("((data->>%s)::numeric)", ('count',))) / 60). \ values('timestamp', "average", "median", "rps"). \ order_by('timestamp') data = json.loads( json.dumps(list(d), indent=4, sort_keys=True, default=str)) return JsonResponse(data, safe=False)
ããã³ããšã³ãã«ã¯ããã®ãšã³ããã€ã³ããåç §ããc3.jsãã£ãŒãããããŸãã
var test_rtot_graph = c3.generate({ data: { url: '/analyzer/test/' + test_id_1 + '/rtot/', mimeType: 'json', type: 'line', keys: { x: 'timestamp', value: ['average', 'median', 'rps'], }, xFormat: '%H:%M:%S', axes: { rps: 'y2' }, }, zoom: { enabled: true }, axis: { x: { type: 'timeseries', tick: { format: '%H:%M:%S' } }, y: { padding: { top: 0, bottom: 0 }, label: 'response times (ms)', }, y2: { min: 0, show: true, padding: { top: 0, bottom: 0 }, label: 'Requests/s', } }, bindto: '#test_rtot_graph' });
ãã®çµæã次ã®ããã«ãªããŸãã

å®éãã¢ããªã±ãŒã·ã§ã³å šäœã¯ãããã¯ãšã³ãã®å¯Ÿå¿ãããšã³ããã€ã³ãããããŒã¿ãæç»ããã°ã©ãã§æ§æãããŠããŸãã
ãã¹ããåæããããã®ã·ã¹ãã å šäœããœãŒã¹ã³ãŒãããã©ã®ããã«æ©èœãããã確èªã§ããŸãã次ã«ãInnogamesã§è² è·ãã¹ããå®è¡ããããã»ã¹ã説æããŸãïŒãã®éšåã¯ããããŸã§ã®ãšããåœç€Ÿã«ã®ã¿é¢é£ããŠããŸãïŒã
ãã¡ã€ã¢ãŒïŒ
è² è·ãã¹ãç°å¢
åè¿°ããããã«ãè² è·ãã¹ãç°å¢å šäœã¯ã1ã€ã®ã¡ã€ã³ãµãŒããŒadmin.loadtestãšè€æ°ã®generatorN.loadtestãµãŒããŒã§æ§æãããŠããŸãã
admin.loadtest -Debian Linux 9 ä»®æ³ãã·ã³ ã16ã³ã¢/ 16ã®ã°ãJenkinsãLTCããã³ãã®ä»ã®éèŠã§ãªããœãããŠã§ã¢ãå®è¡ããŸãã
generatorN.loadtest -Java 8ãã€ã³ã¹ããŒã«ããã裞ã®Debian Linux 8ä»®æ³ãã·ã³ãã¯ãŒã¯ç°ãªããŸããã32ã³ã¢/ 32ã®ã°ãšããŸãããã
admin.loadtestã§ã¯ã / var / lib / apache-jmeterãã©ã«ããŒã«ã€ã³ã¹ããŒã«ãããJmeterïŒæãåºæ¬çãªãã©ã°ã€ã³ãåããææ°ããŒãžã§ã³ïŒã¯ãäºåã«çµã¿ç«ãŠãããdebãã£ã¹ããªãã¥ãŒã·ã§ã³ãšããŠã€ã³ã¹ããŒã«ãããŸãã
Git
åãããžã§ã¯ãã®ãã¹ãèšç»ã¯ãInnoGameså ã®GitLabã®åå¥ã®ãããžã§ã¯ãã«ãããããåããŒã ã®éçºè ãŸãã¯QAã¯ç¬èªã®ä¿®æ£ãè¡ãããšãã§ããŸãã ãããŠãåãããžã§ã¯ãã¯Gitã§åäœããããã«æ§æãããŠããŸãã

åãããžã§ã¯ãã®æ§æã¯æ¬¡ã®ãšããã§ãã
./jmeter_ext_libs/src/
./test-plan.jmx
./prepareAccouts.sh
- jmeter_ext_libs-Gradleã䜿çšããŠãã«ããããåãã¹ãã®åã«/ var / lib / apache-jmeter / lib / extã«é 眮ãããè¿œå ãã©ã°ã€ã³ã®ãœãŒã¹ãã©ã«ããŒã
- test-plan.jmx-ãã¹ãèšç»
- * .sh-ãŠãŒã¶ãŒã¢ã«ãŠã³ããªã©ãæºåããããã®è¿œå ã¹ã¯ãªããã
ãã¹ãèšç»
åãã¹ãèšç»ã¯ã ã¹ã¬ããã°ã«ãŒããšããŠ3ã€ã®å€æ°ãæã€ã¹ã¬ããã¹ã¬ããã®ã¹ãããã䜿çšããŸãïŒthread_countãramp_upãdurationïŒ

ãããã®å€æ°ã®å€ã¯ããã¹ãã®éå§æã«JenkinsããååŸãããŸãããæåã«ãä»ã®ãã¹ãŠã®ãã©ã¡ãŒã¿ãŒåãããå€æ°ãšåæ§ã«ããŠãŒã¶ãŒå®çŸ©å€æ°ã®ãã¹ãèšç»ã®ã¡ã€ã³èŠçŽ ã§é©åã«å®£èšããå¿ èŠããããŸãã éèŠãªãã®ã®1ã€ãããŒã«ãšåŒã³ãŸããã-䜿çšäžã®ããŒã¿ããŒã«ïŒãŠãŒã¶ãŒãã°ã€ã³ãªã©ïŒãåŸã§åºå¥ããããã«ãå®è¡äžã®JmeterãµãŒããŒããšã«ã·ãªã¢ã«çªå·ãéä¿¡ãããŸãã

ããã§$ {__ PïŒTHREAD_COUNTã1ïŒ}ïŒTHREAD_COUNTã¯JenkinsããååŸãããå€æ°ã®ååã§ãããããã§ãªãå Žåã¯1ãããã©ã«ãå€ã§ãã
ãŸããåãã¹ãèšç»ã«ã¯ããµã³ãã©ãŒã®çµæãCSVãã¡ã€ã«ã«æžã蟌ãSimpleDataWriterããããŸãã 次ã®ãªãã·ã§ã³ãæå¹ã«ãªã£ãŠããŸãã
<time>true</time> <latency>true</latency> <timestamp>true</timestamp> <success>true</success> <label>true</label> <code>true</code> <fieldNames>true</fieldNames> <bytes>true</bytes> <threadCounts> true</threadCounts>
ãžã§ã³ãã³ã¹
ãã¹ããéå§ããåã«ãåãŠãŒã¶ãŒã¯ãJmeterãã¹ãèšç»ã®äžèšã®å€æ°ã«æž¡ãããããã€ãã®ãã©ã¡ãŒã¿ãŒãèšå®ã§ããŸãã

è©Šé転
ããã§ã¯ãã¹ã¯ãªããã«ç§»ããŸãããã ãŸãããã«ãåã¹ã¯ãªããã§ãJmeterãã£ã¹ããªãã¥ãŒã·ã§ã³ãæºåããŸãã
- / tmp / jmeter-xvgenq /ãšãã圢åŒã®äžæãã©ã«ããŒãäœæããŸã
- / var / lib / apache-jmeter /ããã¡ã€ã³ãã£ã¹ããªãã¥ãŒã·ã§ã³ãã³ããŒããŸã/
- jmeter_ext_libsãã©ã«ããŒïŒååšããå ŽåïŒããè¿œå ã®ãã©ã°ã€ã³ãåéããŸãã
- åéãã* .jarã/ tmp / jmeter-xvgenq /ã«ã³ããŒããŸã
- å®æããäžæé åžãããJmeterãããŒããžã§ãã¬ãŒã¿ãŒã«æ¡åŒµããŸãã
#!/bin/bash export PATH=$PATH:/opt/gradle/gradle-4.2.1/bin echo "JMeter home: $JMETER_HOME" JMETER_INDEX=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 8 | head -n 1) # JMETER_DIR="/tmp/jmeter-$JMETER_INDEX" echo "JMeter directory: $JMETER_DIR" echo $JMETER_DIR > "/tmp/jmeter_dir$JOB_NAME" mkdir $JMETER_DIR cp -rp $JMETER_HOME* $JMETER_DIR if [ -d "$WORKSPACE/jmeter_ext_libs" ]; then echo "Building additional JMeter lib" cd "$WORKSPACE/jmeter_ext_libs" gradle jar cp ./build/libs/* $JMETER_DIR/lib/ext/ ls $JMETER_DIR/lib/ext/ fi cd $WORKSPACE
次ã«ãæåŸã®ã¿ã¹ã¯ã«æ»ããŸãïŒè² è·ãçæããããã«èšèšããã10å°ã®ä»®æ³ãã·ã³ãããïŒä»ã®ãããžã§ã¯ãã®ãã¹ããå®è¡ãããŠãããã©ãããããããŸããïŒãTHREAD_COUNTã®ãšãã¥ã¬ãŒããããã¹ã¬ããã®å¿ èŠç·æ°ã«åºã¥ããŠããããã®ä»®æ³ãã·ã³ã§å€æ°ã®JmeterãµãŒããŒãå®è¡ããå¿ èŠããããŸãïŒç°ãªãïŒå¿ èŠãªè² è·ããšãã¥ã¬ãŒãããã®ã«ååã§ãã
ã¹ã¯ãªããã§ã¯ãããã¯Jenkins bashã¹ã¯ãªããã®3è¡ã®å©ããåããŠè¡ãããŸãããã¡ãããLTCèªäœã®ã¹ã¯ãªããã®ããæ·±å»ãªãã®ã«ã€ãªãããŸãã
REMOTE_HOSTS_DATA=`python /var/lib/jltc/manage.py shell -c "import controller.views as views; print(views.prepare_load_generators('"$JOB_NAME"','"$WORKSPACE"','"$JMETER_DIR"', '$THREAD_COUNT', '$duration'));"` THREADS_PER_HOST=`python -c 'import json,sys;data=dict('"$REMOTE_HOSTS_DATA"');print data["threads_per_host"]'` REMOTE_HOSTS_STRING=`python -c 'import json,sys;data=dict('"$REMOTE_HOSTS_DATA"');print data["remote_hosts_string"]'`
ãããã£ãŠãæåã®è¡ã§ïŒ
prepare_load_generatorsé¢æ°ãåŒã³åºãããããžã§ã¯ãåããããžã§ã¯ãã¯ãŒã¯ã¹ããŒã¹ãã£ã¬ã¯ããªãžã®ãã¹ãäžèšã§äœæããäžæJmeterãã£ã¹ããªãã¥ãŒã·ã§ã³ãžã®ãã¹ïŒ/ tmp / jmeter-xvgenq /ïŒããã¹ãæéããããŠæãéèŠãªãšãã¥ã¬ãŒãã¹ã¬ããã®åèšæ°$ THREAD_COUNTãæž¡ããŸãã
äžè¬ã«æ¬¡ã®å Žåããªããžããªã§æ¬¡ã«äœã衚瀺ãããŸããïŒ
- æå®ãããthread_countã«åºã¥ããŠãå¿ èŠãªJmeterãµãŒããŒã®æ°Xããç§ãèæ¡ããåŒã«åŸã£ãŠèšç®ãããŸãã
- ããã«ããã·ã³generatorN.loadtestã®çŸåšã®è² è·ãšäœ¿çšå¯èœãªã¡ã¢ãªã«åºã¥ããŠããããã®ãã·ã³ã®ããããã§ãåèšæ°ãXã«ãªããŸã§nçªç®ã®JmeterãµãŒããŒãèµ·åãããŸãã
- éžæããgeneratorN.loadtestã®ããããã§ãrsyncã¯ãã®äžæçãªJmeterãã£ã¹ããªãã¥ãŒã·ã§ã³ãããŒãããŸãã
- åãžã§ãã¬ãŒã¿ãŒã§ãnçªç®ã®æ°ã®JmeterãµãŒããŒïŒåã®æé ã§ååŸïŒãèµ·åãããã·ãªã¢ã«çªå·ããŒã«ãå®è¡äžã®åããã»ã¹ã«æž¡ããŠããŒã¿ããŒã«ãé åžããŸãïŒåã«æžããããã«ïŒã
- Jmeterã€ã³ã¹ã¿ã³ã¹ã®å®è¡ã«é¢ãããã¹ãŠã®ããŒã¿ã¯ããŒã¿ããŒã¹ã«ä¿åããããã¹ãåŸããã¹ãŠã®ã€ã³ã¹ã¿ã³ã¹ã¯ãã®ããŒã¿ã«åºã¥ããŠç Žæ£ãããŸãã
- æåŸã«ãé¢æ°ã¯æ¬¡ã®åœ¢åŒã®JSONãè¿ããŸãã
{ âremote_hosts_stringâ: âgenerator1.loadtest:10000,generator2.loadtest:10000, generator2.loadtest:10001â, "threads_per_host": 100 }
å®éã®ãšããããã¹ãŠã®JmeterãµãŒããŒã¯å®è¡äžã§ãããããããæ¥ç¶ãããã®ãåŸ ã£ãŠããããã¹ãèªäœãéå§ãããŸãã ãããã£ãŠã2è¡ç®ãš3è¡ç®ã§ã¯ããã®JSONããå€ãååŸããŠã¡ã€ã³Jmeterã€ã³ã¹ã¿ã³ã¹ã«æž¡ããŸããåæå€THREAD_COUNTã¯ãªã¢ãŒãjmeterãµãŒããŒéã§åå²ãããåãµãŒããŒã«ã¯threads_per_hostããããŸãïŒäžèšã§ååŸããthread_per_hostå€ãTHREAD_COUNTãšããŠæž¡ããŸãïŒ ïŒ
java -jar -server $JAVA_ARGS $JMETER_DIR/bin/ApacheJmeter.jar -n -t $WORKSPACE/test-plan.jmx -R $REMOTE_HOSTS_STRING -GTHREAD_COUNT=$threads_per_host -GDURATION=$DURATION -GRAMPUP=$RAMPUP
ããã§ã$ JMETER_DIRã¯ãäžæçãªJmeterãã£ã¹ããªãã¥ãŒã·ã§ã³ïŒ/ tmp / jmeter-xvgenq /ïŒããããã©ã«ããŒã§ãã
ãªã¢ãŒãJmeterãµãŒããŒãå®è¡ããã«ã¯ãç¬èªã®ã¢ãã«ããããŸãã ã©ã®ãã¹ããå®è¡ãããŠããããã©ã®ä»®æ³ãã·ã³ãããŒãããã®ããã»ã¹ã®IDãªã©ã«é¢ããããŒã¿ãä¿åããŸãã ããããã¹ãŠã¯ããããã®åãjmeter-serverãç Žæ£ããå¿ èŠãããå Žåã«ããã¹ããããã«åæ¢ããããã«å¿ èŠã§ãã
class JmeterInstance(models.Model): test_running = models.ForeignKey(TestRunning, on_delete=models.CASCADE) load_generator = models.ForeignKey(LoadGenerator) pid = models.IntegerField(default=0) port = models.IntegerField(default=0) jmeter_dir = models.CharField(max_length=300, default="") project = models.ForeignKey(Project, on_delete=models.CASCADE) threads_number = models.IntegerField(default=0) class Meta: db_table = 'jmeter_instance'
ãŸããããã³ãããŒãžã«ã¯ãå®è¡äžã®ãã¹ããšè² è·ãžã§ãã¬ãŒã¿ãŒã®ã¹ããŒã¿ã¹ã«é¢ããæ å ±ãèšèŒãããç¹å¥ãªçŸãããã¬ãŒãããããŸãã

ãã¹ãåæ¢
ãã¹ãåŸãå®è¡äžã®ãã¹ãŠã®JmeterãµãŒããŒãç Žæ£ããäžæçãªJmeterãã£ã¹ããªãã¥ãŒã·ã§ã³ãåé€ããŠãçµæãåéããå¿ èŠããããŸãã
ãã«ãåŸã¹ã¯ãªããã§æ¬¡ãè¿œå ããŸãã
JMETER_DIR=$(cat /tmp/jmeter_dir$JOB_NAME) echo "Removing Jmeter dir from admin: $JMETER_DIR" rm -rf $JMETER_DIR python /var/lib/jltc/manage.py shell -c "import controller.views as views; print(views.stop_test_for_project('"$JOB_NAME"'))"
ãŸããã¡ã€ã³ãµãŒããŒããäžæçãªdistãåé€ããŠããã stop_test_for_projecté¢æ°ãåŒã³åºããŠãããžã§ã¯ãåãæž¡ããŸãã ãã®é¢æ°ã¯ãå®è¡äžã®Jmeterã€ã³ã¹ã¿ã³ã¹ã«é¢ããæ å ±ãä¿åããããããåæ¢ããããŒã¿ããŒã¹å ã®ç¹å¥ãªããŒãã«ãééããŸãã
æåŸã®ã¹ãããã§ããçµæã®åéã¯ã2ã€ã®æ¹æ³ã§å®è¡ã§ããã¹ã¯ãªãããå®è¡ããŸãã
python /var/lib/jltc/datagenerator_linux.py
ãŸãã¯ãWebãµãŒãã¹ãããŒã«ã«ã§åŒã³åºããŸãã
curl --data "results_dir=$JENKINS_HOME/jobs/$JOB_NAME/builds/$BUILD_NUMBER/" http://localhost:8888/controller/parse_results
çŸæç¹ã§ã¯ãã¹ã¯ãªããã䜿çšããŠãJancisãã©ã«ããŒå ã®ãã¹ãŠã®ãžã§ããå®è¡ããããŒã¿ããŒã¹å ã®ãžã§ããšæ¯èŒããŠãäžè²«æ§ãä¿æããŠããŸãã
ãªãã·ã§ãã«
LTCã§ã¯ãããã€ãã®kronosãæ§ç¯ããŸãããããšãã°ãjmeterãµãŒããŒããã»ã¹ã®S0UãS1UãEUãããã³OUãåéããã¡ããªãã¯ããŒã¿ã®åèšãã¹ã¬ããæ°ã§é€ç®ãããªã©ãNåããšã«ä»®æ³ãã·ã³ãšjmeterã€ã³ã¹ã¿ã³ã¹ã®javaããã»ã¹ã®å®è¡ã«é¢ããæ å ±ãåéãããžã£ããäœæããŸããå®è¡äž-1ã€ã®ã¹ã¬ãããæ¶è²»ããã¡ã¢ãªã®å¹³åãµã€ãºãååŸããŸãã ã¡ããªãã¯ã¯ããªãå¥åŠã§ããããŸãã¯æããããããŸããããç¹å®ã®æ°ã®ã¹ã¬ããããšãã¥ã¬ãŒãããããã«å¿ èŠãªãJavaããã»ã¹ã«å¿ èŠãªã¡ã¢ãªãµã€ãºã倧ãŸãã«èšç®ããã®ã«åœ¹ç«ã¡ãŸãã
ãããã«
ãã¡ãããå€ãã®äººããã«ãã€ã³ã®Jmeterã¬ããŒãã·ã¹ãã ã䜿çšããŠããŸããããããéæ¢ããŠããããåžžã«é²åããŠããŸãã ããŒã¿ãä¿åããç°ãªããã¹ãéã§çµæãæ¯èŒããå¿ èŠãããå ŽåãBlazeMeterãªã©ã®ãµãŒãã¹ã䜿çšã§ããŸãã
ç§ã®çŸå®ã§ã¯ããããã®ãµãŒãã¹ã¯éåžžã«é«äŸ¡ã§ãããè² è·ãçæããã®ã«ååãªå®¹éãããããããã€ã³ãµã€ããŒããœãªã¥ãŒã·ã§ã³ãäœæããããšããŸããã
ãã§ã«å€ãã®ããšãç¥ã£ãŠããŸãããå®ç§ã«ã¯ã»ã©é ããå®ç§ã«ã¯ã»ã©é ãã§ãã ã ããä»ãç§ã¯åæ§ã®åé¡ãæ±ããŠãã人ã ããŸã ããããšãæãã§ããŸãã
ã¿ãªãããããããšãããããŸããã