ã¢ããªã¹ã§ã¯ãã¡ãœããåŒã³åºãã¯åãã¢ããªã±ãŒã·ã§ã³å
ã§è¡ãããŸãã-çŸåšããã€ã¯ããµãŒãã¹ã¢ãŒããã¯ãã£ã§ã¯ããã¹ãŠã®çžäºäœçšã¯ãããã¯ãŒã¯ãä»ããŠå®è¡ãããŸãã ãããã£ãŠãã¢ããªã±ãŒã·ã§ã³éã®æ
å ±äº€æã¬ãŒãã¯ã䜿çšããã亀æãããã³ã«ã«é¢ä¿ãªãäœäžããŸãã
ãã®èšäºã§ã¯ã JMeterãGatling ïŒ ããŒã2 ïŒãªã©ã®ããŒã«ã䜿çšããäŸãšããŠã Apache Thriftã䜿çšããéHTTPãããã³ã«ã®è² è·ãã¹ãã®ããã®ã³ãŒãã®äœææ¹æ³ã瀺ããŸãã 50K RPSã«å¯Ÿå¿ãããã€ã¯ããµãŒãã¹ããã¹ãããŸãã 1å°ã®ããŒããã·ã³ã§ããã®ãã€ãŒãã«èšèŒãããŠããããã©ãŒãã³ã¹ãéæããããšããŸãã
Thriftãåºæ¬ãšããŠããŸãããããã¯ç¹å¥ãªåœ¹å²ãæãããŠãããã gRPC ã Avro ãããã³ãã®ä»ã®ãããã³ã«ããã¹ãã§ããå°ããªèª¿æŽããããŸãã ãã®èšäºã®ã¢ãããŒãã¯äžè¬çãªãã®ã§ãããã¯ã©ã€ã¢ã³ãã眮ãæããå¿
èŠãããã ãã§ãã
æ確åæ£åŒã«ã¯ã説æãããŠãããããã³ã«ã¯RPCãã¬ãŒã ã¯ãŒã¯ããã³/ãŸãã¯ããŒã¿ã·ãªã¢ã«åã·ã¹ãã ã§ãããéçºè
èªèº«ããããã³ã«ãšããèšèã䜿çšããŠã ãŸã ã
JMeterãšGatlingãéžã¶çç±
1ã€ã®çç±ã¯ããªãŒãã³ãœãŒã¹ã®èµ·æºã§ãã ã³ãŒãã調ã¹ãŠãããŒã«ã«äœãã©ã®ããã«å®è£
ãããŠããããç解ããŠãã ããã ãããŠãæ¯æãå¿
èŠã¯ãããŸããã
GitHubã®ãªãŒãã³ã¹ããŒã¹ã«ã¯ãç¹å®ã®ãããã³ã«çšã«åŒ·åãããããŒã«ããããŸãã ããšãã°ãThriftã®å ŽåãTwitteréçºè
ã®IagoãPinterestã®ç·æ§ã®ãã³ããŒã§ãã ãããããã®ãããªãã¬ãŒã ã¯ãŒã¯ã䜿çšãããšããšã³ããªã®ãããå€ãšãã¹ä¿æ°ãåçã«å¢å ããŸãã 察ç
§çã«ãã¬ããªã³ã°ãšç¹ã«JMeterã¯åºãæ®åããŠããã倧ããªã³ãã¥ããã£ãããããã€ã§ãã¢ããã€ã¹ãæ±ããããåé¡ã®èª¬æãèŠã€ããããšãã§ããŸãã
ãŸããç§ãã¡ã«ãšã£ãŠãç解ã§ããªãç¶æ³ã§ã³ãŒããæžããã¡ã³ãšããŠãäž¡æ¹ã®ããŒã«ã¯çŽ æŽãããã§ãã
次ã®è³ªåïŒ2ã€ã®ããŒã«ã®ãããããéžæããŠã¿ãŸãããïŒ äžèŠãããšããããããã®éã«ã¯åçæ§ãããããã¹ãŠã詳现ã«ç解ããå¿
èŠããããŸãã ããã«ãã¢ãããŒã-Threads vs Actorsãæ¯èŒããããšã¯èå³æ·±ãã§ãã
Jmeter
JMeterã¯GUIæåã®ããŒãæ段ã§ããããã®ããã®ã³ãŒããæžãããšãã§ããŸãã ãã®ã¢ãããŒãã«ãããå¯èªæ§ãåäžããããŒã¿ãVCSã«é©åãªåœ¢åŒã§ä¿åããç®ãçããããšãªãã³ãŒãã¬ãã¥ãŒãå®æœã§ããŸãã ããã«ãä»»æã®ãããã³ã«ã®ã¯ã©ã€ã¢ã³ããäœæããã«ã¯ãã³ãŒããååã§ããã ãã§ãªããå¿
èŠãªæ¡ä»¶ããããŸãã æåŸã«ããã®ã³ãŒãã䜿çšãããšãç¹å®ã®ããŒã«ã«ã€ããŠèª¬æããããšãªããéçºãæ¯æŽããããšã容æã«ãªããããã«ãã£ãŠåã³ãã¹ãã¡ã¯ã¿ãŒãäœäžããŸãã
ã«ã¹ã¿ã ãããã³ã«ãããŒãããããã«JMeterãæäŸãããã®ãèŠãŠã¿ãŸãããã
- éHTTPãã©ã°ã€ã³ã ãã®ãªãã·ã§ã³ã¯ãã¡ããåªããŠããŸããããããã³ã«ã«å®è£
ãããŠãããããããã«å€æŽå¯èœã§ãã
- JMeterå
ã§ã³ãŒããèšè¿°ããŸãã ã¢ã€ãã¢ã¯ãŸããŸãã§ã-äŸåé¢ä¿ãæ±ãã®ã¯é£ãããããã©ãŒãã³ã¹ã®åé¡ããããããããŸããã BeanShellã®èšäºã«ãããšã Samplerã¯éåžžã«é
ããããã·ã§ã«ã«æžã蟌ãå¿
èŠããããŸããããã«ããããããŸãããã JSR223ãµã³ãã©ãŒã¯äžèŠããŠãŸãšããªããã©ãŒãã³ã¹ã瀺ããŠããŸããä»åŸã®ãã¹ãã®ããã«ãã®ãŸãŸã«ããŠãããŸãã
- IDEã§ã®ã³ãŒãã®èšè¿°ã¯ãåžžã«ãã䟿å©ã§äŸ¿å©ã§ãã JMeterã¯ããã®ããã«JavaãšJunitã®2ã€ã®ãµã³ãã©ãŒãæäŸããŠããŸãã
ãµã³ãã©ãŒã®æ§èœæ¯èŒ
ã©ã®ãµã³ãã©ãŒã䜿çšããããç解ããããã«ãæ¯èŒåæãå®æœããŸãã ãã¹ãã®ããã«ãã«ãŒãå
ã®è¡ãé£çµããVALUEãsmallïŒ10ïŒããã³largeïŒ100ïŒã«èšå®ããç°¡åãªã¹ã¯ãªãããäœæããŸãã
import java.security.SecureRandom; for (int i = 0; i < VALUE; i++) { new StringBuilder().append( new SecureRandom().nextInt()); }
ãã¹ãŠã®ãã¹ãã¯JMeter 3.3ã§å®æœãããŸããã

JSR223ã®æ¹ãé
ãããšãããããŸããã€ãŸããã¯ã©ãã·ã¥ããŸãã JavaãšJunitã®ããã©ãŒãã³ã¹ã¯äŒŒãŠããŸãããã©ã¡ãããã䟿å©ããç解ããã«ã¯ãäž¡æ¹ãå解ããå¿
èŠããããŸãã
Javaãªã¯ãšã¹ããµã³ãã©ãŒ

Java Samplerã«ã¯ãè² è·ã®ãã¹ãã®éžæãšãã¹ãã«æž¡ãããã®ãã©ã¡ãŒã¿ãŒã®2ã€ã®èšå®ãããããŸããã ã³ãŒãã§äžé£ã®ããã©ã«ããã©ã¡ãŒã¿ãæå®ã§ããŸãããããã¯JMeter GUIã«è¡šç€ºãããŸãã ãã ããGUIããæ°ãããã©ã¡ãŒã¿ãŒãçŽæ¥è¿œå ãããã¹ãèšç»ãä¿åãããšãè¿œå ãããã©ã¡ãŒã¿ãŒããªã»ãããããããšã«æ³šæããŠãã ããã
Java Samplerãã¹ãã¯ãJMeterã©ã€ãã©ãªã®æšæºçãªAbstractJavaSamplerClientãæ¡åŒµããŸãïŒGradleãªã©ã®äŸ¿å©ãªãã«ãããŒã«ãšæ¥ç¶ããŸãïŒã å®éããã¹ãã¯ã©ã¹ã¯ããã¹ãèªäœãäºåæ¡ä»¶ãšäºåŸæ¡ä»¶ãããã³ããã©ã«ããã©ã¡ãŒã¿ã§æ§æã§ããŸãã
public class ThriftJavaSampler extends AbstractJavaSamplerClient { @Override public SampleResult runTest(JavaSamplerContext javaSamplerContext) { SampleResult sampleResult = new SampleResult(); sampleResult.sampleStart(); boolean result = Utility.getScenario(); sampleResult.sampleEnd(); sampleResult.setSuccessful(result); return sampleResult; } }
ãã¹ãã¡ãœããã¯ããã©ã¡ãŒã¿ãŒãååŸããJMeterã³ã³ããã¹ããååŸããSampleResultãè¿ããŸããSampleResultã«ã¯ããã¹ãå®è¡ã®æ§æãšçµæã®è©äŸ¡ã«åœ¹ç«ã€äžé£ã®ã¡ãœãããå«ãŸããŠããŸãã ç§ãã¡ã®ç®çã«ãšã£ãŠãæå®ããã3ã€ã®ã¡ãœããã¯éèŠã§ãããªã¯ãšã¹ãã®éå§æéãšçµäºæéãããã³çµæã§ãã
Junitãªã¯ãšã¹ããµã³ãã©ãŒ

Junit Samplerã«ã¯ããŒãçšã®ãã¹ãéžæããããããã§1ã€ã®ã¯ã©ã¹ã«è€æ°ã®ã¡ãœãããèšè¿°ã§ããŸãã ããã©ã«ãã®ãã©ã¡ãŒã¿ãŒã¯ããŠãŒã¶ãŒå®çŸ©å€æ°èŠçŽ ãä»ããŠã³ãŒãã«ã¹ããŒãããŸãã ä»ã®ãã¹ãŠã®èšå®ã¯èª¬æããæããã§ããäºåæ¡ä»¶ãšäºåŸæ¡ä»¶ãåŒã³åºãããåºåã«ã¢ãµãŒããšã©ãŒãšã©ã³ã¿ã€ã ãšã©ãŒãè¿œå ããŸãã ããã©ãŒãã³ã¹ã倧å¹
ã«äœäžããããããæ°ãããªã¯ãšã¹ãããšã«ãã¹ãã€ã³ã¹ã¿ã³ã¹ãäœæããããšã¯å«ããªãã§ãã ããã
Junit Request Samplerã¯ãéåžžã®Junitãã¹ãã«äŒŒãŠããŸãããåäœãå°ãç°ãªããŸãã JMeterã¯@BeforeClassãš@AfterClassãåŒã³åºãããšã¯ãããŸããããã®ãããåå¥ã®ãã¹ãã䜿çšããŠã°ããŒãã«åææ¡ä»¶ãæ§æããå¿
èŠããããŸãã ãŸãã Beforeããã³Afterã®ã³ãŒãã¯ããã¹ãã©ã³ã¿ã€ã ã§ã¯èæ
®ãããªãããšã«æ³šæããŠãã ããã
@BeforeClass public static void setUpClass() {assert false;} @Before public void setUp() {} @Test public void test() {} @After public void cleanUp() {} @AfterClass public static void cleanUpTest() {assert false;}
JMeteréçºè
èªèº«ã¯ãGUIã¢ãŒãã¯ãããã°ã«ã®ã¿äœ¿çšãã¹ãã ãšèšã£ãŠããŸãã ããããããã§ã¯éçãšã·ã³ã°ã«ãã³ã«æ³šæããå¿
èŠããããŸãã ããšãã°ããã¹ããåèµ·åããåŸãã·ã³ã°ã«ãã³å
ã§å®£èšãããŠãããã®ã¯ãã¹ãŠåæåãããŸããã åæã«ãã·ã³ã°ã«ãã³ã䜿çšããã«ãåãã¹ãã®åã«ãã¹ãŠã®ãªããžã§ã¯ããååæåãããããã©ãŒãã³ã¹ã«æªåœ±é¿ãåãŒããŸãã éçå€æ°ã¯ããã¹ãã®å®è¡åŸã«ãã®å€ãæ°žä¹
ã«èšæ¶ããGUIããåå®çŸ©ãããŠãå€æŽãããŸããã
äž¡æ¹ã®ãµã³ãã©ãŒãæ¯èŒããŠãæçµçã«ã¯ç°¡åã§ä¿®æ£ããããJunit Request Samplerã«æ±ºããŸããã
Thriftã¯ã©ã€ã¢ã³ãã®äœæ
ã¯ã©ã€ã¢ã³ããäœæãããšãã¯ãThriftãããã³ã«ã®ããŸããŸãªèšå®ãèæ
®ããå¿
èŠããããŸãã äž»ãªã«ãŒã«ïŒã¯ã©ã€ã¢ã³ããšãµãŒããŒã¯åããã©ã³ã¹ããŒããšãããã³ã«ã§åäœããã¢ãŒãã£ãã¡ã¯ãã®ããŒãžã§ã³ã1ã€å¿
èŠã§ãã

åãã¹ãã§ã¯ã©ã€ã¢ã³ããäœæããæéãç¡é§ã«ãããè² è·ãçæãããã·ã³ã®ããŒãã䜿ãæãããªãããã«ãããã«ã¯ã©ã€ã¢ã³ãããŒã«ãæžã蟌ã¿ãŸãã ããŒã«ã«ã€ããŠã¯ãã¯ã©ã€ã¢ã³ãã®æ°ãæå®ã§ããŸããããã¯ãå¿
èŠãªæ°ã®æ¥ç¶ãç¶æããŸãã䜿çšåã«ããŒã«ããã¯ã©ã€ã¢ã³ããåãåºãã䜿çšåŸã«æ»ãã ãã§ãã
asyncClientPool = new ThriftClientPool<>(() -> new PaymentsCreate.AsyncClient( (TProtocolFactory) tTransport -> new TMultiplexedProtocol(new TBinaryProtocol(tTransport), SERVICE), new TAsyncClientManager(), new TNonblockingSocket(host, port, TIMEOUT)), PoolConfig.get());
ããããããŒã«ãšã¯ã©ã€ã¢ã³ãã®äœææ¹æ³ã§ãã äž»ãªããšã¯ããã®äŸã§ã¯ãããŒã«ã¯å®è£
ã«ã€ããŠäœãç¥ãããäœææã«æ§æãããŸãã ããã¯ãGenericObjectPoolã§èšè¿°ãããæãåºæ¬çãªããŒã«ã§ããããã«åºã¥ããŠãéçºè
ã¯ãã®ã³ã°ãšåäžã®ãããã³ã«/ãã©ã³ã¹ããŒãã§èªå·±èª¿æŽããŒã«ãäœæããŸããã
ã³ãŒããèšè¿°ããjarãã¡ã€ã«ã«å
¥ããŠãJMeterã®æšªã«çœ®ããŸãã
$JMETER_DIR/lib/junit $JMETER_DIR/lib/ext $JMETER_DIR/lib
ãµãŒãããŒãã£ã©ã€ãã©ãªãšãã®äžææ§ãå¿ããªãã§ãã ããã ãããããªããšããã¹ãã¯äœ¿çšå¯èœãªãã®ã®ãªã¹ãã«è¡šç€ºãããªãããããŒãã®éå§æã«ããŒãžã§ã³ã®ç«¶åãçºçããªãå ŽåããããŸãã
jmxã®ãªãJMeter
JMeterã®ã³ãŒãã®èšè¿°ã«é¢ããèšäºã¯ãjmxãã¡ã€ã«ã®äœçŸãã®XMLè¡ã®é¢åãªãã¹ãèšç»ãåãé€ãæ¹æ³ãè°è«ããªãéããäžå®å
šã§ãã
JMeterã©ã€ãã©ãªã䜿çšããŠã¢ããªã±ãŒã·ã§ã³ãèšè¿°ããäž»èŠãªãã€ã³ããé çªã«èª¬æããŸãã
ã¢ããªã±ãŒã·ã§ã³ãéå§ããåã«ãJMeterã®èšå®ãååšããå Žæãæå®ããå¿
èŠããããŸãã åæã«ãJMeterã®ããŒã«ã«ã€ã³ã¹ããŒã«ã¯ãªãã·ã§ã³ã§ãã
final String JMETER_HOME = Utility.getJMeterHome(); JMeterUtils.loadJMeterProperties(JMETER_HOME + "jmeter.properties"); JMeterUtils.initLogging(); JMeterUtils.setLocale(Locale.ENGLISH); JMeterUtils.setJMeterHome(JMETER_HOME);
ãã¹ãèšç»ã«ååãä»ããŠããããã³ã«ã瀺ããŸãããã
TestPlan testPlan = new TestPlan("Thrift test"); TestElement sampler = Utility.getSampler();
LoopControllerãšThreadGroupã¯ãããŒããžã§ãã¬ãŒã¿ãŒïŒããŒãããæ¹æ³ãšéïŒãæ
åœããŸãã ããã§ã¯ãã¹ãŠãæšæºã§ãã
LoopController controller = new LoopController(); controller.setLoops(10); controller.setContinueForever(false); ThreadGroup threadGroup = new ThreadGroup(); threadGroup.setNumThreads(10); threadGroup.setRampUp(0); threadGroup.setDuration(30); threadGroup.setSamplerController(controller);
ããŒãäžã«çµæãå§çž®åœ¢åŒã§è¡šç€ºãïŒãµãã©ã€ã¶ãŒã®ãããïŒãããã«åŠçããããã«çµæãä¿åã§ããŸãïŒresultCollectorããããæ
åœããŸãïŒã
Summariser summariser = new Summariser(); SampleSaveConfiguration saveConfiguration = new SampleSaveConfiguration(true); ResultCollector resultCollector = new ResultCollector(summariser); resultCollector.setFilename(JMETER_HOME + "report.jtl"); resultCollector.setSuccessOnlyLogging(true); resultCollector.setSaveConfig(saveConfiguration);
ãã¹ãŠã®èŠçŽ ã¯ãç¹å¥ãªJMeterããªãŒã§çµåãããŸãã GUI modã§ãããè¡ãæ¹æ³ã®ããã«èŠããŸãïŒ
HashTree config = new HashTree(); config.add(testPlan) .add(threadGroup) .add(sampler) .add(resultCollector);
ããŒããæ§æããŠå®è¡ããŸãã
StandardJMeterEngine jMeterEngine = new StandardJMeterEngine(); jMeterEngine.configure(config); jMeterEngine.runTest();
XMLã«ã€ããŠå¿ããããšãã§ãããã¹ãŠã ãã£ãïŒ
究極ã®è² è·
çºé»æ©ã1å°ã®è² è·æ©æ¢°ããã©ãã ãçç£ã§ããããèŠãŠã¿ãŸãããã åœç¶ãè² è·ãã¹ãçšã®ãã¹ãŠã®ã·ã¹ãã èšå®ãè¡ãããŸããããããã¯ãŒã¯èšå®ãæ¢ã«èæ
®ãããªãŒãã³èšè¿°åã®å¶éãå¢ãããŸããã å®è¡åŸãçŽ30K RPSãå®è¡ã§ããããŒãã¹ã±ãžã¥ãŒã«ã¯ããŸãåäžã§ã¯ãããŸããã


åé¡ã¯åœç¶çºçããŸãããããã¯ã¯ã©ã€ã¢ã³ãåŽãŸãã¯ãµãŒããŒåŽã®å¶éã§ããïŒ å¥ã®JMeterãã¯ã©ã¹ã¿ãŒã«äžç·ã«é
眮ãããµãŒãã¹ãã¿ãŒã²ãã5äžRPSãçºè¡ã§ããããšã確èªããŸããã
PS
次ã®ããŒãã§ã¯ãã¬ããªã³ã°ã䜿çšããŠéHTTPè² è·ãåæããããã©ãŒãã³ã¹ã10åã«é«ããæ¹æ³ã説æããŸãã