You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

JMeterTesting.asciidoc 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. ---
  2. title: JMeter Testing
  3. order: 20
  4. layout: page
  5. ---
  6. [[how-to-test-vaadin-web-application-performance-with-jmeter]]
  7. = How to test Vaadin web application performance with JMeter
  8. This article describes how to make load testing of your Vaadin web
  9. application with http://jakarta.apache.org/jmeter/[JMeter].
  10. [[get-the-latest-jmeter]]
  11. Get the latest JMeter
  12. ~~~~~~~~~~~~~~~~~~~~~
  13. Download JMeter from http://jmeter.apache.org/download_jmeter.cgi
  14. [[configure-jmeter]]
  15. Configure JMeter
  16. ~~~~~~~~~~~~~~~~
  17. Unzip the apache-jmeter-x.x.x.zip file.
  18. Edit `JMETERHOME/bin/jmeter.bat` (or `jmeter.sh`) and check that the JVM
  19. memory parameters are ok (e.g. `set HEAP=-Xms512m -Xmx1500m -Xss128k`).
  20. The maximum heap size (`-Xmx`) should be at least 1024m. I would also
  21. recommend that the thread stack size is set to 512k or below if a large
  22. number of threads is used in testing.
  23. You should read this to ensure you follow best-practices:
  24. * http://jmeter.apache.org/usermanual/best-practices.html +
  25. * http://www.ubik-ingenierie.com/blog/jmeter_performance_tuning_tips/
  26. [[start-jmeter]]
  27. Start JMeter
  28. ~~~~~~~~~~~~
  29. E.g. double clicking jmeter.bat
  30. [[configure-your-test-plan-and-workbench]]
  31. Configure your Test Plan and WorkBench
  32. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  33. Right click the WorkBench icon and select 'Add' -> 'Non-Test Elements'
  34. -> 'HTTP(S) Test Script Recorder'. Edit the Recorder parameters and set
  35. Port: to e.g. 9999 (you could leave it to 8080 if your web application
  36. servers do not use the port 8080). Typically requests related to loading
  37. static web content like css files and images are excluded from the load
  38. test. You can use 'Url Patterns to Exclude' section of the recorder to
  39. define what content is excluded. For instance to exclude css files add
  40. following pattern: `.*\.css`
  41. image:img/jm1B.png[JMeter patterns to exclude]
  42. Right click the Recorder icon and select 'Add' -> 'Timer' -> 'Uniform
  43. random timer'. Configure timer by setting the *Constant Delays Offset
  44. into $\{T}*. This setting means that JMeter records also the delays
  45. between the http requests. You could also test without the timer but
  46. with the timer your test is more realistic.
  47. image:img/jm3B.png[JMeter uniform random timer]
  48. Optionally you could also add 'View Result Tree' listener under the
  49. Recorder. With 'View Result Tree' listener it is possible to inspect
  50. every recorded request and response.
  51. *Note since JMeter you can do this in one step using menu item
  52. "Templates..." and selecting "Recording" template.*
  53. image:img/jm2B.png[JMeter View Results Tree]
  54. Next, configure the Test Plan.
  55. Add a 'Thread Group' to it and then add a 'Config Element' -> 'HTTP
  56. Cookie Manager' to the thread group. Set Cookie policy of the cookie
  57. manager to be 'compatibility'. *Remember also to set the "Clear cookies
  58. each iteration" setting to 'checked'*. Add also a 'Config Element' ->
  59. 'HTTP Request Defaults' into Thread group.
  60. You could also add a 'Config Element' -> 'User Defined Variables' and a
  61. 'Logic Controller' -> 'Recording Controller' into Thread Group.
  62. Your JMeter should now looks something like the screenshot below:
  63. image:img/jm4.png[JMeter User Defined Variables]
  64. [[configure-your-vaadin-application]]
  65. Configure your Vaadin application
  66. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  67. [[disable-the-xsrf-protection]]
  68. Disable the xsrf-protection
  69. ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  70. In Vaadin you have to disable the xsrf-protection of your application or
  71. otherwise the JMeter test may fail. The way how xsrf protection is
  72. disabled differs in Vaadin 6 and Vaadin 7.
  73. *In Vaadin 7*
  74. If you use web.xml in your Vaadin 7 project, add the following
  75. context-parameter in the web.xml or optionally add it as an init
  76. parameter just like in the Vaadin 6 project below.
  77. [source,xml]
  78. ....
  79. <context-param>
  80. <param-name>disable-xsrf-protection</param-name>
  81. <param-value>true</param-value>
  82. </context-param>
  83. ....
  84. If you use annotation based (Servlet 3.0) Vaadin servlet configuration,
  85. you can currently (in Vaadin 7.1.11) either fall back to Servlet 2.4
  86. web.xml configuration or set the parameter value for
  87. 'disable-xsrf-protection' as a `java.lang.System property` before the
  88. Vaadin's `DefaultDeploymentConfiguration` is loaded. This can be done for
  89. example by extending `VaadinServlet` class. At the end of this Wiki
  90. article there is an example servlet (`JMeterServlet`) that implements this
  91. functionality. See the example code below for how to replace the default
  92. `VaadinServlet` with your custom `VaadinServlet` in the UI class.
  93. [source,java]
  94. ....
  95. public class YourUI extends UI {
  96. @WebServlet(value = "/*", asyncSupported = true)
  97. @VaadinServletConfiguration(productionMode = false, ui = YourUI.class)
  98. public static class Servlet extends JMeterServlet {
  99. }
  100. @Override
  101. protected void init(VaadinRequest request) {
  102. //...
  103. }
  104. ....
  105. *In Vaadin 6*
  106. See the example below for how to disable the protection from the web.xml
  107. file:
  108. [source,xml]
  109. ....
  110. <servlet>
  111. <servlet-name>FeatureBrowser</servlet-name>
  112. <servlet-class>com.vaadin.terminal.gwt.server.ApplicationServlet</servlet-class>
  113. <init-param>
  114. <param-name>application</param-name>
  115. <param-value>com.vaadin.demo.featurebrowser.FeatureBrowser</param-value>
  116. </init-param>
  117. <init-param>
  118. <param-name>disable-xsrf-protection</param-name>
  119. <param-value>true</param-value>
  120. </init-param>
  121. </servlet>
  122. ....
  123. *Important! Remember to enable the protection after the testing is
  124. done!*
  125. [[disabling-syncid-happens-with-similar-parameter]]
  126. Disabling syncId happens with similar parameter
  127. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  128. [source,xml]
  129. ....
  130. <context-param>
  131. <param-name>syncId</param-name>
  132. <param-value>false</param-value>
  133. </context-param>
  134. ....
  135. If you want to do the above with Java Servlet 3.0 annotations, use the
  136. following:
  137. [source,java]
  138. ....
  139. initParams = {
  140. @WebInitParam(name = "disable-xsrf-protection", value = "true"),
  141. @WebInitParam(name = "syncIdCheck", value = "false")}
  142. ....
  143. [[use-debug-ids-within-your-vaadin-application]]
  144. Use debug id:s within your Vaadin application
  145. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  146. Normally a Vaadin application sets a sequential id for each user
  147. interface component of the application. These ids are used in the
  148. ajax-requests when the component state is synchronized between the
  149. server and the client side. The aforementioned id sequence is likely the
  150. same between different runs of the application, but this is not
  151. guaranteed. *In Vaadin 6* these ids can be manually set by calling
  152. http://vaadin.com/api/com/vaadin/ui/AbstractComponent.html#setDebugId%28java.lang.String%29[`setDebugId()`]
  153. method.
  154. *In Vaadin 7* there no more exists a `setDebugId()` method; instead there
  155. is
  156. https://vaadin.com/api/com/vaadin/ui/Component.html#setId(java.lang.String)[`setId()`]
  157. method. Unfortunately this method won't set component ids used in the
  158. ajax-request. Therefore, by default, JMeter tests of a Vaadin 7
  159. application are not stable to UI changes. To overcome this problem you
  160. can use our `JMeterServlet` (see the end of this article) instead of the
  161. default `VaadinServlet`. When using the `JMeterServlet` component ids are
  162. again used in the ajax requests. See example above for how to replace
  163. default `VaadinServlet` with JMeterServlet. For additional information,
  164. see the Vaadin ticket http://dev.vaadin.com/ticket/13396[#13396].
  165. [[use-named-windows-in-your-application]]
  166. Use named windows in your application
  167. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  168. Setting the name for the Windows *in the Vaadin (< 6.4.X)* application
  169. is important since otherwise these names are randomly generated. Window
  170. name could be set using the `setName()`{empty}-method.
  171. [[configure-your-browser]]
  172. Configure your browser
  173. ~~~~~~~~~~~~~~~~~~~~~~
  174. Since JMeter is used as a proxy server, you have to configure the proxy
  175. settings of your browser. You can find the proxy settings of Firefox
  176. from Tools -> Options -> Connections -> Settings: 'Manual proxy
  177. configuration'. Set the correct IP of your computer (or 'localhost'
  178. string) and the same port that you set into proxy server settings above.
  179. [[start-recording]]
  180. Start recording
  181. ~~~~~~~~~~~~~~~
  182. Start your web application server. Start the proxy server from the
  183. JMeter. Open the URL of your web application into the browser configured
  184. above. You should append `?restartApplication` to the URL used when
  185. recording the tests to make sure that the UI gets initialized properly.
  186. Thus the URL becomes something like
  187. (http://localhost:8080/test/TestApplication/?restartApplication). If
  188. everything is ok your web application opens normally and you can see how
  189. the different HTTP requests appear into JMeter's thread group (see
  190. screenshot below). When you have done the recording, stop the proxy
  191. server.
  192. image:img/jm5.png[JMeter Thread Groups]
  193. [[performance-testing]]
  194. Performance testing
  195. ~~~~~~~~~~~~~~~~~~~
  196. [[clean-up-the-recorded-request]]
  197. Clean up the recorded request
  198. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  199. Before you start the test, you may have to delete the first timer object
  200. which is located below the first HTTP request in the thread group since
  201. its time delay may be unrealistically big (see the screenshot above).
  202. *It is also very much recommended to check the recorded data and delete
  203. all unessential requests.*
  204. [[detecting-out-of-sync-errors]]
  205. Detecting Out of Sync errors
  206. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  207. If your test results in the application being in an Out of Sync error
  208. state it is not by default detected by JMeter (because the response code
  209. is still HTTP/1.1 200 OK). To make an assertion for detecting this kind
  210. of error you should add a Response Assertion to your test plan.
  211. Right-click on the thread group and select Add -> Assertions -> Response
  212. Assertion. Configure the assertion to assert that the Text Response does
  213. NOT contain a pattern "Out of sync".
  214. [[optional-parameterization-of-the-request]]
  215. Optional parameterization of the request
  216. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  217. Sometimes, it is useful to parameterize the recorded requests.
  218. Parameterization of a request is easily done in JMeter:
  219. 1. add a "User Defined Variables"-element into the first place of your Test Plan.
  220. 2. Copy paste the whole parameter value of wanted UIDL-request into the
  221. newly made variable (e.g. `PARAM1`).
  222. 3. Replace the value of the UIDL-request with the parameter reference (e.g. `${PARAM1}`).
  223. [[start-testing]]
  224. Start testing
  225. ^^^^^^^^^^^^^
  226. Now, it is time to do the actual testing. Configure the thread group
  227. with proper 'Number of Threads' (e.g. 100) and set also the 'Ramp-Up
  228. Period' to some realistic value (e.g. 120). Then, add e.g. 'Listener' ->
  229. 'Graph Results' to monitor how your application is performing. Finally,
  230. start the test from the Run -> Start.
  231. [[stop-on-error]]
  232. Stop on Error
  233. ^^^^^^^^^^^^^
  234. When you are pushing your Vaadin application to the limits, you might
  235. get into a situation where some of the UIDL requests fail. Because of
  236. the server-driven nature of Vaadin, it's likely that subsequent requests
  237. will cause errors like "_Warning: Ignoring variable change for
  238. non-existent component_", as the state stored on the server-side is no
  239. longer in sync with the JMeter test script. In these cases, it's often
  240. best to configure your JMeter thread group to stop the thread on sampler
  241. error. However, if you have configured your test to loop, you might want
  242. to still continue (and ignore the errors), if the next iteration will
  243. start all over again with fresh state.
  244. [[continuous-integration]]
  245. Continuous Integration
  246. ^^^^^^^^^^^^^^^^^^^^^^
  247. If you want to integrate load testing in your CI, you can use this
  248. http://jmeter.lazerycode.com/[plugin].
  249. You can read this for full integration with Jenkins : 
  250. * https://blog.codecentric.de/en/2014/01/automating-jmeter-tests-maven-jenkins/
  251. [[jmeterservlet]]
  252. JMeterServlet
  253. ^^^^^^^^^^^^^
  254. In Vaadin 7 we recommend using the following or similar customized
  255. `VaadinServlet`.
  256. [source,java]
  257. ....
  258. package com.example.vaadin7jmeterservlet;
  259. import com.vaadin.server.ClientConnector;
  260. import com.vaadin.server.DeploymentConfiguration;
  261. import com.vaadin.server.ServiceException;
  262. import com.vaadin.server.VaadinRequest;
  263. import com.vaadin.server.VaadinService;
  264. import com.vaadin.server.VaadinServlet;
  265. import com.vaadin.server.VaadinServletService;
  266. import com.vaadin.server.VaadinSession;
  267. import com.vaadin.ui.Component;
  268. /**
  269. * @author Marcus Hellberg (marcus@vaadin.com)
  270. * Further modified by Johannes Tuikkala (johannes@vaadin.com)
  271. */
  272. public class JMeterServlet extends VaadinServlet {
  273. private static final long serialVersionUID = 898354532369443197L;
  274. public JMeterServlet() {
  275. System.setProperty(getPackageName() + "." + "disable-xsrf-protection",
  276. "true");
  277. }
  278. @Override
  279. protected VaadinServletService createServletService(
  280. DeploymentConfiguration deploymentConfiguration)
  281. throws ServiceException {
  282. JMeterService service = new JMeterService(this, deploymentConfiguration);
  283. service.init();
  284. return service;
  285. }
  286. private String getPackageName() {
  287. String pkgName;
  288. final Package pkg = this.getClass().getPackage();
  289. if (pkg != null) {
  290. pkgName = pkg.getName();
  291. } else {
  292. final String className = this.getClass().getName();
  293. pkgName = new String(className.toCharArray(), 0,
  294. className.lastIndexOf('.'));
  295. }
  296. return pkgName;
  297. }
  298. public static class JMeterService extends VaadinServletService {
  299. private static final long serialVersionUID = -5874716650679865909L;
  300. public JMeterService(VaadinServlet servlet,
  301. DeploymentConfiguration deploymentConfiguration)
  302. throws ServiceException {
  303. super(servlet, deploymentConfiguration);
  304. }
  305. @Override
  306. protected VaadinSession createVaadinSession(VaadinRequest request)
  307. throws ServiceException {
  308. return new JMeterSession(this);
  309. }
  310. }
  311. public static class JMeterSession extends VaadinSession {
  312. private static final long serialVersionUID = 4596901275146146127L;
  313. public JMeterSession(VaadinService service) {
  314. super(service);
  315. }
  316. @Override
  317. public String createConnectorId(ClientConnector connector) {
  318. if (connector instanceof Component) {
  319. Component component = (Component) connector;
  320. return component.getId() == null ? super
  321. .createConnectorId(connector) : component.getId();
  322. }
  323. return super.createConnectorId(connector);
  324. }
  325. }
  326. }
  327. ....