TailSampler - parallel sending GET requests to Apache.JMeter


     

    1. Purpose of the HTTP Request Tail plugin


    The plugin simplifies the loading of embedded resources, allows you to execute specified GET requests in parallel . Making the test as close as possible to the browser in terms of the composition of the downloaded resources and the method of loading these resources.

    TailSampler helps out if necessary:

    • execute a group of GET requests in parallel;
    • 1000 GET-run queries, without creating 1000 components of the HTTP the Request ;
    • test a site that actively uses AJAX , Adobe Flash , Adobe AIR , SilverLigth , ...

    2. Instructions for use


    HTTP Request Tail converts the list of links into an HTML document, loading the built-in resources of which will create a GET request for each of the specified links. Figure 1. Data preparation process for the TailSampler plugin and its use

    The data preparation process for the <b> TailSampler </b> plugin and its use


    1. Launch Fiddler .
    2. Open a page in a web browser, the loading of which must be imitated in detail in the test - this can be a page with Adobe Flash , with Adobe AIR , with Microsoft SilverLigth , with ActiveX components.
    3. Perform the necessary actions on the page.
    4. Copy from Fiddler links to GET requests that need to be executed in the test in parallel, as if they were executed by the browser.
    5. Insert links into TailSampler , parameterize if necessary.
    6. Get parallel execution of the specified requests in the test, the degree of parallelism is configured.



    3. The work of standard html-parsers JMeter


    The standard way to get an HTML document via HTTP in JMeter is to use an HTTP Request sampler. The HTTP Request is a simple way to request a page embedded resources - tick [v] the Retrieve Embedded the Resource s. The standard parser that forms links to page resources is LagartoBasedHtmlParser . Parser can be changed in setting htmlparser.classname file jmeter.properties .

    A study of Apache.JMeter parsers for five popular sites is given in the article “Choosing an HTML parser for Apache.JMeter”:


    When using parsers, almost all the necessary resources are loaded. But for different sites, the completeness of the download is different. So if the website is implemented on Microsoft Silverlight , then the performance of the Apache.JMeter parser will be about 0%. Whereas, using TailSampler , it will be possible to apply a load similar to how the browser works in a simple way.

    3.1. An example of working with the complex atlas.mos.ru site



    Figure 2. Site atlas.mos.ru in the browser - 85queries to the main domain

    Figure 3. Site atlas.mos.ru in JMeter - 2request to the main domain

    Figure 4. Trace of query execution can be seen in webpagetest.org

    Figure 5. The browser performs 85queries to the main domain, and JMeter only 2- performance 2,35%, see the logs in google docs

    When you open the atlas.mos.ru site that actively uses AJAX , the difference is visible:

    • 2GET request, if LagartoBasedHtmlParser , HTTP Request , JMeter 3.0 are running ;
    • 85GET requests if the Chrome browser is running .

    Thus, when using the HTTP Request with the [v] Retrieve Embedded Resources setting for the atlas.mos.ru address , the83 GET request will not be sent.


    Little will be
    "Last year's snow fell"

    To simulate sending a 83GET request, you will need to add 83the HTTP Request component to the JMeter script :

    • JMeter script will become cumbersome.

    Added 83HTTP Request will be processed sequentially one after another - the browser sends requests for embedded resources in parallel :

    • the total duration of loading page resources will be longer than in the browser, sequential loading takes longer than parallel on an unloaded server;
    • the number of simultaneously open connections to the server will be less than when the browser is running; the number of connections to the server indirectly affects performance.



    Figure 6. Report on loading the pflb.ru site in Firefox - http://www.webpagetest.org/result/160319_RQ_Q3W/1/details/ - parallel load groups are visible on 6requests.

    Thus, using only HTTP Request you will not be able to completely repeat the download built-in resources so as to accurately measure the loading time of the html page with all the subqueries. Figure 7. HTTP Request does not allow you to see the whole picture, HTTP Request Tail will help to implement the tail of sub- requests




    4. History of creation


    The HTTP Request Tail plugin for JMeter was created as an alternative to the Tile Server service in python , see the description below.

    The first acquaintance with the Tile Server service occurred when colleagues Zhenya Borodenkov and Maxim Konyshev talked about load testing a web project that loads large images in slices, tiles. Then we solved the task of stress testing one of the versions of this web project that uses SilverLight on the client and streaming content from the server using the SOAP / MSBin1 protocol . Send from JMeter requests by protocol SOAP / MSBin1and at first we didn’t know how to process the answers to them, we discussed the options.

    The story was something like this:
    - If Vova was here, he would say use an intermediate service to form the necessary requests.

    - Intermediate service, it's too complicated (answered them). Let's write a plugin for JMeter . The plugin is simple and reliable.

    - That's when the previous testing was, Andrei Pishchulin wrote the Tile Server service in python , we still use this service, the service for working with tiles:
    • JMeter sends Tile Server a list of links using the POST method via HTTP Request ;
    • Tile Server implements a web server, receives a list of links, generates an html document from the links with a list of iframes that point to the links, and returns a JMeter html document ;
    • JMeter parses the html document and executes the necessary GET requests, like subqueries.
    Let's do the same.

    - Well, let's do an intermediate service to implement work with SOAP / MSBin1 .


    Figure 8. Tile Server

    Looking ahead, I’ll say we did the same as once. We made a .NET proxy service that generated requests via SOAP / MSBin1 - JMeter sent commands to this service via SOAP / XML , and the service sent requests to the loaded host via SOAP / MSBin1 and returned responses to JMeter .

    And with a high load, the proxy service became a bottleneck, it could not generate requests and process responses so that the loaded servers were dull and snug. The tested servers received the load, but if they answered the proxy service in 10seconds, the proxy service answered JMeter in 110seconds. According to statistics from the logsJMeter turned out that the loaded service was depressed, and yes, the load was good, but the loaded service responded vigorously, more vigorously than the JMeter logs indicated . The prompt addition of detailed logging to the proxy service corrected the situation, but when the proxy service crashed, the logging on it was delayed - it was necessary to scale the intermediate service or rewrite it completely, one instance did not pull the role of Tsar Cannon. Figure 9. Tsar Cannon The proxy service has become a point of failure. Then we returned to the idea of ​​a plug-in for JMeter , and made a machine gun for working on the SOAP / MSBin1 protocol from JSR223 , JNA libraries, and a proxy client on .NET




    It turned out great. The plugin no longer has to process multiple incoming streams. RAM overhead, of course, more, but it works faster.

    Then the idea came to write sampler JMeter in java, to replace Tile Server , and suddenly it is a point of failure under load. Even the name of the future sampler appeared - “HTTP Request Tail” or “Tail Sampler”. Due to poor knowledge of the English language, I heard the word “Tile” as “Tail”, I did not understand a bit, moreover, here are the “tiles” and the word that translates as “tail”. Deaf phones, tail so tail, the image of a mermaid complemented the picture. The idea has taken hold, the idea is clear, there is a name. The only thing left was to do it. Then Sasha Perevozchikova Sanchez92 , an expert on plug-in development, helped .

    I have no complaints against Tile Server , my colleagues say - this is a fast and reliable tool. The plugin was created out of curiosity and interest in the new JMeter tool for me , and Sasha had to take something, otherwise the girl was bored.

    All the names in this story are fictitious, explicitly or indirectly, the HTTP Request Tail plugin did:

    • Sasha Perevozchikova;
    • Andrey Pishchulin;
    • Vova Lavrentiev;
    • Maxim Konyshev;
    • Zhenya Borodenkov;
    • and I was there, drinking something.


    5. Description


    5.1. Default settings



    Figure 10. Default settings

    The default settings are:

    • [v] Retrieve All Embedded Resources - the checkbox is checked by default, it can be unchecked, but then the subqueries will not be executed, and the HTTP Request Tail will become useless;
    • [v] Use concurent pool - the checkbox is checked by default, on a large number of built-in resources, multithreaded download increases the download speed;
    • Use concerent pool Size :4- the default value is 4, this value is used by JMeter as the base:
      • HttpClient4, when configured, Use concerent pool Size : 4will send up to 4 requests at a time, each thread will use 1 permanent connection to each domain:
        • a group of threads starts, the group size is determined by the Use concerent pool Size setting ;
        • when setting [v] Use keepalive, each thread for each unique domain will create one persistent-connection;
      • Mozilla Firefox 44.0 browser by default sends up to 6simultaneous requests to each domain (see about:config):
        • 256- network.http.max-connections - the maximum number of connections;
        • 6- network.http.max-persistent-connections-per-server - the maximum number of permanent connections to the server (keepalive);
        • 32- network.http.max-persistent-connections-per-proxy - the maximum number of persistent connections to the proxy server (keepalive);
      • If you focus on the settings of Mozilla Firefox 44.0 , and the fact that links to embedded resources in load testing projects usually belong to the same domain, then in Use concerent pool Size you can set a value 6instead of a standard value 4.

    Unused settings - settings for POST requests, the values ​​are not used in any way by either the main request or subqueries:

    • [] Use multipart / form-data for POST ;
    • [] Browser-compatible headers .

    The main request is generated, but not sent, the settings for POST requests do not affect it. Subqueries use the GET method; the settings for POST requests are also not valid for them.

    Other settings affect subqueries.

    HTTP Request Tail is the successor to HTTP Request , a description of the settings can be found in the documentation for HTTP Request :



    5.2. Configured HTTP Request Tail



    Figure 11. Configured HTTP Request Tail
    Links to embedded resources are indicated in the Embedded resources text box . You can specify relative and absolute links.

    5.2.1. Absolute links

    See the RFC for a description of the format for absolute links: https://tools.ietf.org/html/rfc3986 .

    Absolute links begin with the protocol:
    • file://
    • http://
    • https://

    Other protocols are not processed by HTTP Request Tail . Examples of absolute links:



    5.2.2. Relative links

    Relative links are supplemented by field values:
    • Path - a directory for those links that are relative to the page, and not relative to the host, here you can specify the protocol and the host and port.
    • Web Server - host and port:
      • Server Name or IP ;
      • Number The Port ;
    • Protocol [http] - protocol if Path Unknown protocol value is taken into account, allowed valuesfile,http,https.

    An example of relative links:

    • image1.png
    • /images/image1.png
    • /ResourceGenerator.aspx?id=0121
    • subFolder/style.css
    • subFolder/1/2/3/test.php


    5.2.3. Parameterization using variables and functions

    You can use JMeter variables and functions to parameterize GET requests . Example:
    • ${variable_URL}
    • /search.php?q=${variable_Query_String}
    • /search.php?q=${variable_Query_String}&client=Mozilla
    • /search.php?q=${__urlencode(${variable_Query_String})}&client=Mozilla


    5.2.4. Features of processing Unicode and html entities

    When forming an html page from links, html escaping is used. Therefore, when writing links, you can use:

    • Cyrillic domains
    • special characters, such as <, >, &and others;
    • any unicode characters.

    The structure of the html page will not be violated, the links will be processed correctly and in full.
    See the full list of html entities for html4 here:


    If some entity from the specification is not escaped, then issue a note for the plugin.

    No need to pre-escap special characters. So if there is a need to specify a URL of the form:

    • /search.php?q=Testing&client=Mozilla - right.

    That’s the way to write - just do not need &to screen in advance &:

    • /search.php?q=Testing&amp;client=Mozilla- wrong .


    5.2.5. Unicode for java

    It is noticed that if the address has a unicode character, for example, ®, Ω, π, ≈:

    • /search.php?q=Microsoft®

    And in the Implementation setting there is a value Java, then in the subquery the unicode character will be replaced by a square:

    • /search.php?q=Microsoft□

    When starting JMeter from Windows using a bat-file, the coding for java is assigned windows-1251, I assume this is the reason for replacing the unicode-character with a small square. To specify the encoding, you need to specify the argument for java : in the bat-file -Dfile.encoding=UTF-8. When used HttpClient4, HttpClient3.1such an undesirable transformation does not occur.

    5.3. Generated response



    Figure 12. Response to the main request - generated response The

    response to the main request is generated. There is no request, only the response body.

    The response body is an html document, text encoded in UTF-8, where a tag is generated for each link to an embedded resource iframe.

    Document example:

    Embedded resources


    Figure 13. Execution statistics of generated request

    5.3.1. Change plans

    When writing an article about JMeter parsers, the developer JMeter Philippe M. philmdot appeared in the comments and asked to post the defect at the expense of recursive processing:


    I plan to post a defect, and even fix it. Making it so that to respond to requests from tags img, a recursive search for links to resources is not performed. That in JMeter parsing worked the same way as the browser does. Now if iframe, then you need to perform parsing, but if it's simple img, then a single request is executed.

    And then it will be necessary to change the TailSampler plugin so that tags are used imginstead of tags during generation iframe.

    Philippe wrote today that he would like to see this code in the JMeter core , that this will be a good way to work with AJAX . I'll try to catch this year, it will be an interesting experience.


    5.4. Known effects



    5.4.1. +1 request in the log

    Although the root request is not sent, it gets to the log:

    • weak, but overestimates the value of the Hits per second indicator - hits per second;
    • Indirectly, it affects the general statistics on the JMeter log;
    • To reduce the impact of this single query on statistics - the number of real subqueries should be large, dozens of links in the Embedded resources field .


    5.4.2. Visual hoax for answer 302

    If the Follow Redirect setting is selected , then for each embedded resource with the response code 302(Found):

    • it will redirect to the page specified in the Location value of the response header;
    • redirects are displayed in JMeter as subqueries - visually looks like a cascade of requests.


    5.4.3. Recursion

    A rare but possible effect is loading inline resources for an inline resource:

    • with content type (see htmlParser.Types and wmlParser.Types settings in jmeter.properties ):

      • text / html;
      • application / xhtml + xml;
      • application / xml;
      • text / xml;
      • text / vnd.wap.wml;
    • performed:

      • loading embedded resources for the current embedded resource — there may be more subqueries than the links in the Embedded resources field .


    There are plans to limit the recursion depth to a parameter configured in the plug-in interface in 3 levels by default. When loading a picture ( img tag ), the browser does not load embedded resources for it. Immediately, all resources are wrapped in an iframe tag , and Apache.JMeter does not currently distinguish for which tag the request was made - it always parses the response for the subject of subqueries if the Content Type of the response is suitable. Figure 14. The first test_server.ru request is visible, which did not actually run (the “+1 request” effect). A cascade of redirects is visible (the “Visual cheating for 302 response” effect) and subqueries for subqueries (the “Recursion” effect).




    5.5. Time characteristics


    If you uncheck [] Retrieve All Embedded Resources or do not specify any links in Embedded resources , then the logs will say that the request was sent instantly, and the answer came instantly.

    Description of time characteristics:

    • Load Time - total duration of loading embedded resources;
    • Connect time always 0;
    • Latency always 0.


    6. Project on Github




    7. Project structure


    Source code in the directory:

    / src / ru / pflb / jmeter
    • protocol / http / config / gui :
      • TailUrlConfigGui.java — элемент управления с большим полем ввода для ссылок на встроенные ресурсы;
    • samplers:
      • wrapper — обёртки, чтобы использовать указанный на форме Implementation:
        • WrapperHTTPFileImpl.java — обёртка, чтобы использовать обработчик протокола file:// для подзапросов;
        • WrapperHTTPHC3Impl.java — обёртка, чтобы использовать HttpClient3.1 из настройки Implementation для подзапросов;
        • WrapperHTTPHC4Impl.java — обёртка, чтобы использовать HttpClient4 из настройки Implementation для подзапросов;
        • WrapperHTTPJavaImpl.java — обёртка, чтобы использовать Java из настройки Implementation для подзапросов;
        • WrapperHTTPSamplerFactory.java — фабрика, для создания обёрток, возвращает обработчик по значениям протокола и настройке Implementation;
      • EscapeUtils.java — реализация html-экранирования, позволяет работать с русскими доменами, юникодом и специальными символами в ссылках;
      • ITailHTTPImpl.java — базовый интерфейс для всех обработчиков;
      • TailHTTPHC4Impl.java — модифицированный HttpClient4, который использует указанное тело ответа не отправляя запрос;
      • TailHTTPSamplerProxy.java — прокси-класс в котором реализована вся логика работы TailSampler:
        • for the first request, it takes a list of links from the Embedded resources field and passes it to TailHTTPHC4Impl - emulation of receiving a page with a list of iframes in the content;
        • for requests for built-in resources, a standard handler is created and called, specified in the Implementation setting - the actual sending of requests;
      • TailHttpSamplerGui.java - visual representation of TailSampler .

    Other auxiliary directories are used for convenient debugging of the project.

    7.1. The form


    The TailUrlConfigGui form is a modification of the main HTTP Request form from Apache.JMeter 2.13, from which the fields for editing the request body and specifying the list of parameters are removed, but one large field for entering the list of links is added.
    And the look of TailHttpSamplerGui is also a copy of the HTTP Request , which now uses the new TailUrlConfigGui main control .

    It was not without copy-paste. I went to this step so that the HTTP Request Tail almost did not differ from the HTTP Request .

    But in JMeter 3.0 the look of the HTTP Requesthas been changed, controls are rearranged. Now the HTTP Request Tail is different than the HTTP Request for JMeter 3.0. But this does not affect the work.

    7.2. Wrappers


    I wanted to make the most of the existing code, but I did not want to do copy paste. Therefore, Wrapper classes were created, thanks to which the methods sample , notifyFirstSampleAfterLoopRestart and threadFinished became available.

    7.3. Shielding utility


    The code for the escaping class is taken from ibm.com: www.ibm.com/developerworks/en/library/se-prevent/index.html The
    table of html entities has been expanded due to the RFC with the description of HTML4.


    8. Installation


    1. Download plugin ru.pflb.jmeter.samplers.TailSampler.jar :
    2. Copy the plugin to the lib / ext directory for JMeter .
    3. Restart JMeter .


    Figure 15. Now the HTTP Request Tail plugin is available in JMeter

    Example directory:

    D: \ TOOLS \ apache-jmeter-2.13 \ lib \ ext \
    D: \ TOOLS \ apache-jmeter-2.13 \ lib \ ext \ ru.pflb.jmeter.samplers.TailSampler.jar
    D: \ TOOLS \ apache-jmeter-3.0 \ lib \ ext \
    D: \ TOOLS \ apache-jmeter-3.0 \ lib \ ext \ ru.pflb.jmeter.samplers.TailSampler.jar


    9. System requirements



    9.1. To work with Apache.JMeter 2.13



    Apache.JMeter 2.13 is compiled using Java 6. And if you build the TailSampler plugin using, for example, OpenJDK 1.7.0_09-icedtea, and run Apache.JMeter 2.13 + the compiled plug-in on a computer where there is only Java 6, then Apache.JMeter 2.13 will start, but the plugin will not. As a result, their bundle will not work. The issue of building projects and libraries for different versions of Java and their compatibility deserves a separate instruction.

    9.2. To work with Apache.JMeter 3.0



    Apache.JMeter 3.0 is built using Java 7. The TailSampler plugin must be built using Java 7 or the version of Java that will be used to run JMeter and the plugin.


    Also popular now: