Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

LoadTestingWithGatling.asciidoc 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. ---
  2. title: Load Testing With Gatling
  3. order: 51
  4. layout: page
  5. ---
  6. [[loading-testing-with-gatling]]
  7. Load testing with Gatling
  8. -------------------------
  9. http://gatling.io[Gatling] is a powerful tool for load testing. Compared
  10. to WebDriver/Selenium/TestBench, it doesn't render the actual content,
  11. but just simulates messages clients send to the server. The server
  12. doesn't know if the test tool actually does something with the
  13. responses, so it gives you perfectly valid numbers for your applications
  14. performance - on the server side. It scales very well, so you don' t
  15. need huge army of nodes to bombard your application under test. It can
  16. be used with Vaadin as such, but with these tips you hopefully get
  17. started easier.
  18. [[vaadin-tips-to-make-tests-more-stable-and-easier-to-create]]
  19. Vaadin tips to make tests more stable and easier to create
  20. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  21. Gatling works with Vaadin "out of the box", but there are some obstacles
  22. you might face if you don't understand a bit how Vaadin communication
  23. works. E.g. plain recordings from standard Vaadin apps will not work
  24. properly.
  25. The communication that Vaadin's "thin client" in browser does with the
  26. server side has couple of checks that it does to improve robustness and
  27. security. One can simulate these with Gatling as well, by e.g.
  28. https://github.com/mstahv/v-quiz/blob/master/src/test/scala/loadtest/WebSocketVaadinSimulation.scala#L84[reading the XSRF prevention key into a variable] and passing the value
  29. https://github.com/mstahv/v-quiz/blob/master/src/test/scala/loadtest/WebSocketVaadinSimulation.scala#L95[in
  30. each response]. However, these setting can be disabled during load
  31. testing to make it easier to write and maintain your application. The
  32. effect for the scalability, when disabling or configuring these, should
  33. be negligible. Feel free to do these, but also remember to remove these
  34. "hacks" when building your production war file. Consider e.g. using
  35. separate maven profile and inject different parameters with it.
  36. [[disabling-xsrf-presentation-key]]
  37. Disabling XSRF presentation key
  38. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  39. The XSRF prevention can be disabled with following servlet parameter
  40. (or similar servlet 3 style parameter). NOTE, do not leave this for
  41. public apps in production.
  42. [source,xml]
  43. ....
  44. <context-param>
  45. <param-name>disable-xsrf-protection</param-name>
  46. <param-value>true</param-value>
  47. </context-param>
  48. ....
  49. [[disabling-syncid-happens-with-similar-parameter]]
  50. Disabling syncId happens with similar parameter
  51. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  52. [source,xml]
  53. ....
  54. <context-param>
  55. <param-name>syncIdCheck</param-name>
  56. <param-value>false</param-value>
  57. </context-param>
  58. ....
  59. If you want to do the above with Java Servlet 3.0 annotations, use the
  60. following:
  61. [source,java]
  62. ....
  63. initParams = {
  64. @WebInitParam(name = "disable-xsrf-protection", value = "true"),
  65. @WebInitParam(name = "syncIdCheck", value = "false")}
  66. ....
  67. [[using-debug-ids-in-communication]]
  68. Using debug ids in communication
  69. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  70. If you want to minimize the effort needed for maintaining your
  71. scalability tests, you probably want to do a small hack to the Vaadin
  72. communication mechanism. Normally Vaadin uses a incrementing session
  73. wide identifier to connect components to their "client side
  74. counterparts". Thus, if you add a one single component to your login
  75. screen, the whole load test simulation might be broken.
  76. You can set "id" for each component, but in recent Vaadin versions this
  77. id is no more used in the communication, but only assigned to
  78. client dom. This can still be enforced with a specially crafted
  79. extension to VaadinServlet. An implementation for the "competing tool" JMeter can be
  80. found at <<jmeter-vaadin-servlet-extension>>. This implementation works for Gatling users
  81. as well. Note that, it is suggested to do this only for load testing, and NOT
  82. for the production.
  83. [[ignoring-obsolete-static-file-requests]]
  84. Ignoring "obsolete" static file requests
  85. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  86. One of the most simplest and cheapest method to improve your apps
  87. scalability is to serve static files form a separate server or from a
  88. CDN provider. Thus it might make sense to leave loading those files away
  89. from your test script. If you do the script manually, just don't add
  90. requests for static files (js/css/images/...). If you recorded you test
  91. case, just remove these form the script. Check out the example project
  92. that only uses the required files.
  93. [[testing-with-websockets]]
  94. Testing with WebSockets
  95. ~~~~~~~~~~~~~~~~~~~~~~~
  96. If your want to load test your application with the most advanced
  97. communication channel, WebSockets, you can do that with Gatling as well.
  98. Using the recorder in this case doesn't work, but handcrafting the test
  99. case isn't that hard once you get started. The example app has a branch
  100. with WebSocket test case. With WebSocket communication it might also be
  101. handy to disable xsrf prevention and the so called "syncid".
  102. First two request are just normal http requests. The first gets the
  103. "host page" and also the initial state request is done with normal XHR.
  104. The difference to normal Vaadin communication is that it is to be sent
  105. to "/PUSH" address.
  106. After the initial state request you start to use the special WebSocket
  107. API in Gatling. There are lot of things to keep in mind with this
  108. fundamentally totally different kind of communication mechanism. Check
  109. out Gatling's generic websocket help for basic info.
  110. When you start handcrafting the WebSocket simulation, the easiest tool
  111. is probably Chrome's dev tools. With that you can open normal browser
  112. session and "sniff" the traffic that is sent to the server and also the
  113. messages that are received. An easy option is just to copy paste the
  114. payloads and possibly add some verification to ensure proper answers are
  115. received. The websocket example is built with special variable to work
  116. without disabling xsrf verification.
  117. If you are using random input in your load tests, something that is
  118. highly suggested for realistic numbers, you might end up in small
  119. problems. The message format, by Atmosphere, has a weird number and "|"
  120. in front of each message. That number tells the message length and it
  121. must really match the real message length. Create a simple helper
  122. function to calculate that if your input data length varies.
  123. [source,javascript]
  124. ....
  125. import io.gatling.core.session._
  126. import io.gatling.core.session.el._
  127. def atmoMessage(message: Expression[String]) = message.map(m => m.length + '|' + m)
  128. .sendText(atmoMessage("SomeMessage"))
  129. ....
  130. If (and when) you probably want to close the websocket connection
  131. cleanly, you need to notify the server with an extra xhr with a
  132. identifier given by the atmosphere framework. The key is the first
  133. message that the server sends when you connect to it. 
  134. Check out this script for
  135. https://github.com/mstahv/v-quiz/blob/master/src/test/scala/loadtest/WebSocketVaadinSimulation.scala[an
  136. example using WebSocket] communication. It also saves XSRF prevention
  137. key to variable, so it don't need it to be disabled from the server.
  138. [[configuring-gatling-to-the-web-app-build]]
  139. Configuring Gatling to the Web app build
  140. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  141. It is a good habit to keep your tests in the same projects as your
  142. actual application. Then you can easily verify your application still
  143. scales, after you have for example written a cryptic SQL query.
  144. Even better if you can make a Gatling script to be executed during
  145. builds to make. Gatling has http://gatling.io/docs/current/extensions/maven_plugin/[a
  146. maven plugin] that can do exactly this thing.
  147. https://github.com/mstahv/gatling-vaadin-example[The example project
  148. setup] executes a test during basic "mvn install". With similar setup in
  149. a real project, your CI server most likely saves results stored under
  150. target directory. This way it is easy to check it out afterwards how the
  151. performance of your application has evolved during its development.
  152. [[jmeter-vaadin-servlet-extension]]
  153. JMeter Vaadin Servlet extension
  154. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  155. The implementation referred to in <<using-debug-ids-in-communication>>
  156. [source,java]
  157. ....
  158. package com.example.vaadin7jmeterservlet;
  159. import com.vaadin.server.ClientConnector;
  160. import com.vaadin.server.DeploymentConfiguration;
  161. import com.vaadin.server.ServiceException;
  162. import com.vaadin.server.VaadinRequest;
  163. import com.vaadin.server.VaadinService;
  164. import com.vaadin.server.VaadinServlet;
  165. import com.vaadin.server.VaadinServletService;
  166. import com.vaadin.server.VaadinSession;
  167. import com.vaadin.ui.Component;
  168. /**
  169. * @author Marcus Hellberg (marcus@vaadin.com)
  170. * Further modified by Johannes Tuikkala (johannes@vaadin.com)
  171. */
  172. public class JMeterServlet extends VaadinServlet {
  173. private static final long serialVersionUID = 898354532369443197L;
  174. public JMeterServlet() {
  175. System.setProperty(getPackageName() + "." + "disable-xsrf-protection",
  176. "true");
  177. }
  178. @Override
  179. protected VaadinServletService createServletService(
  180. DeploymentConfiguration deploymentConfiguration)
  181. throws ServiceException {
  182. JMeterService service = new JMeterService(this, deploymentConfiguration);
  183. service.init();
  184. return service;
  185. }
  186. private String getPackageName() {
  187. String pkgName;
  188. final Package pkg = this.getClass().getPackage();
  189. if (pkg != null) {
  190. pkgName = pkg.getName();
  191. } else {
  192. final String className = this.getClass().getName();
  193. pkgName = new String(className.toCharArray(), 0,
  194. className.lastIndexOf('.'));
  195. }
  196. return pkgName;
  197. }
  198. public static class JMeterService extends VaadinServletService {
  199. private static final long serialVersionUID = -5874716650679865909L;
  200. public JMeterService(VaadinServlet servlet,
  201. DeploymentConfiguration deploymentConfiguration)
  202. throws ServiceException {
  203. super(servlet, deploymentConfiguration);
  204. }
  205. @Override
  206. protected VaadinSession createVaadinSession(VaadinRequest request)
  207. throws ServiceException {
  208. return new JMeterSession(this);
  209. }
  210. }
  211. public static class JMeterSession extends VaadinSession {
  212. private static final long serialVersionUID = 4596901275146146127L;
  213. public JMeterSession(VaadinService service) {
  214. super(service);
  215. }
  216. @Override
  217. public String createConnectorId(ClientConnector connector) {
  218. if (connector instanceof Component) {
  219. Component component = (Component) connector;
  220. return component.getId() == null ? super
  221. .createConnectorId(connector) : component.getId();
  222. }
  223. return super.createConnectorId(connector);
  224. }
  225. }
  226. }
  227. ....