Tag: java11

  • Introducing Jetty Load Generator

    The Jetty Project just released the Jetty Load Generator, a Java 11+ library to load-test any HTTP server, that supports both HTTP/1.1 and HTTP/2.
    The project was born in 2016, with specific requirements. At the time, very few load-test tools had support for HTTP/2, but Jetty’s HttpClient did. Furthermore, few tools supported web-page like resources, which were important to model in order to compare the multiplexed HTTP/2 behavior (up to ~100 concurrent HTTP/2 streams on a single connection) against the HTTP/1.1 behavior (6-8 connections). Lastly, we were more interested in measuring quality of service, rather than throughput.
    The Jetty Load Generator generates requests asynchronously, at a specified rate, independently from the responses. This is the Jetty Load Generator core design principle: we wanted the request generation to be constant, and measure response times independently from the request generation. In this way, the Jetty Load Generator can impose a specific load on the server, independently of the network round-trip and independently of the server-side processing time. Adding more load generators (on the same machine if it has spare capacity, or using additional machines) will allow the load against the server to increase linearly.
    Using this core principle, you can setup the load testing by having N load generator loaders that impose the load on the server, and 1 load generator probe that imposes a very light load and measures response times.
    For example, you can have 4 loaders that impose 20 requests/s each, for a total of 80 requests/s seen by the server. With this load on the server, what would be the experience, in terms of response times, of additional users that make requests to the server? This is exactly what the probe measures.
    If the load on the server is increased to 160 requests/s, what would the probe experience? The same response times? Worse? And what are the probe response times if the load on the server is increased to 240 requests/s?
    Rather than trying to measure some form of throughput (“what is the max number of requests/s the server can sustain?”), the Jetty Load Generator measures the quality of service seen by the probe, as the load on the server increases. This is, in practice, what matters most for HTTP servers: knowing that, when your server has a load of 1024 requests/s, an additional user can still see response times that are acceptable. And knowing how the quality of service changes as the load increases.
    The Jetty Load Generator builds on top of Jetty’s HttpClient features, and offers:

    • A builder-style Java API, to embed the load generator into your own code and to have full access to all events emitted by the load generator
    • A command-line tool, similar to Apache’s ab or wrk2, with histogram reporting, for ease of use, scripting, and integration with CI servers.

    Download the latest command-line tool uber-jar from: https://repo1.maven.org/maven2/org/mortbay/jetty/loadgenerator/jetty-load-generator-starter/

    $ cd /tmp
    $ curl -O https://repo1.maven.org/maven2/org/mortbay/jetty/loadgenerator/jetty-load-generator-starter/1.0.2/jetty-load-generator-starter-1.0.2-uber.jar
    

    Use the --help option to display the available command line options:

    $ java -jar jetty-load-generator-starter-1.0.2-uber.jar --help
    

    Then run it, for example:

    $ java -jar jetty-load-generator-starter-1.0.2-uber.jar --scheme https --host your_server --port 443 --resource-rate 1 --iterations 60 --display-stats
    

    You will obtain an output similar to the following:

    ----------------------------------------------------
    -------------  Load Generator Report  --------------
    ----------------------------------------------------
    https://your_server:443 over http/1.1
    resource tree     : 1 resource(s)
    begin date time   : 2021-02-02 15:38:39 CET
    complete date time: 2021-02-02 15:39:39 CET
    recording time    : 59.657 s
    average cpu load  : 3.034/1200
    histogram:
    @                     _  37 ms (0, 0.00%)
    @                     _  75 ms (0, 0.00%)
    @                     _  113 ms (0, 0.00%)
    @                     _  150 ms (0, 0.00%)
    @                     _  188 ms (0, 0.00%)
    @                     _  226 ms (0, 0.00%)
    @                     _  263 ms (0, 0.00%)
    @                     _  301 ms (0, 0.00%)
                       @  _  339 ms (46, 76.67%) ^50%
       @                  _  376 ms (7, 11.67%) ^85%
      @                   _  414 ms (5, 8.33%) ^95%
    @                     _  452 ms (1, 1.67%)
    @                     _  489 ms (0, 0.00%)
    @                     _  527 ms (0, 0.00%)
    @                     _  565 ms (0, 0.00%)
    @                     _  602 ms (0, 0.00%)
    @                     _  640 ms (0, 0.00%)
    @                     _  678 ms (0, 0.00%)
    @                     _  715 ms (0, 0.00%)
    @                     _  753 ms (1, 1.67%) ^99% ^99.9%
    response times: 60 samples | min/avg/50th%/99th%/max = 303/335/318/753/753 ms
    request rate (requests/s)  : 1.011
    send rate (bytes/s)        : 189.916
    response rate (responses/s): 1.006
    receive rate (bytes/s)     : 41245.797
    failures          : 0
    response 1xx group: 0
    response 2xx group: 60
    response 3xx group: 0
    response 4xx group: 0
    response 5xx group: 0
    ----------------------------------------------------
    

    Use the Jetty Load Generator for your load testing, and report comments and issues at https://github.com/jetty-project/jetty-load-generator. Enjoy!

  • CometD 5.0.3, 6.0.0 and 7.0.0

    Following the releases of Eclipse Jetty 10.0.0 and 11.0.0, the CometD project has released versions 5.0.3, 6.0.0 and 7.0.0.

    CometD 5.0.x Series

    CometD 5.0.x, of which the latest is the newly released 5.0.3, require at least Java 8 and it is based on Jetty 9.4.x.
    This version will be maintained as long as Jetty 9.4.x is maintained, likely many more years, to allow migration away from Java 8.

    CometD 6.0.x Series

    CometD 6.0.x, with the newly released 6.0.0, requires at least Java 11 and it is based on Jetty 10.0.x.
    In turn, Jetty 10.0.x is based on Java EE 8 / Jakarta EE 8, which provide Servlet and WebSocket APIs under the javax.* packages.
    This version of CometD provides a smooth transition from CometD 5 (or earlier) to Java 11 and Jetty 10.
    In this way, you can leverage new Java 11 language features in your application source code, as well as the few new APIs made available in the Servlet 4.0 Specification without having to change much of your code, since you will still be using javax.* Servlet and WebSocket APIs (see the next section on CometD 7.0.x for the migration to the jakarta.* APIs).
    However, server-side CometD applications should not depend much on Servlet or WebSocket APIs, so the migration from CometD 5 (or earlier) should be pretty straightforward.
    CometD 6.0.x, as Jetty 10.0.x, are transition releases to the new Jakarta EE 9 APIs in the jakarta.* packages.
    CometD 6.0.x will be maintained as long as Jetty 10.0.x is maintained.
    Since CometD applications do not depend much on Servlet or WebSocket APIs, consider moving directly to CometD 7.0.x if you don’t depend on other libraries (for example, Spring) that require javax.* classes.

    CometD 7.0.x Series

    CometD 7.0.x, with the newly released 7.0.0, requires at least Java 11 and it is based on Jetty 11.0.x.
    In turn, Jetty 11.0.x is based on Jakarta EE 9, which provide Servlet and WebSocket APIs under the jakarta.* packages.
    Migrating from CometD 6.0.x (or earlier) to CometD 7.0.x should be very easy if your applications depend mostly on the CometD APIs (few or no changes there) and depend very little on the Servlet or WebSocket APIs.
    Dependencies on the javax.* APIs should be migrated to the jakarta.* APIs.
    If your applications depend on third-party libraries, you need to make sure to update the third-party library to a version that supports — if necessary — jakarta.* APIs.
    Migrating to CometD 7.0.x allows you to leverage Java 11 language features and the benefit that you can base your applications on the new Jakarta EE Specifications, therefore abandoning the now-dead Java EE Specifications.
    This migration keeps your applications up-to-date with the current state-of-the-art of EE Specifications, reducing the technical debt to a minimum.
    CometD 7.0.x will be maintained as long as Jetty 11.0.x is maintained.
    The evolution of the Jakarta EE Specifications will be implemented by future Jetty versions, and future CometD versions will keep the pace.

    Which CometD Series Do I Use?

    If your applications depend on third-party libraries that use or depend on Jetty 9.4.x (such as Spring / Spring Boot), use CometD 5.0.x and Jetty 9.4.x until the third party libraries update to newer Jetty versions.
    If your applications depend on third-party libraries that depend on javax.* APIs and that have not been updated to Jakarta EE 9 yet (and therefore to jakarta.* APIs), use CometD 6.0.x and Jetty 10.0.x until the third party libraries update to Jakarta EE 9.
    If your applications depend on third-party libraries that have already been updated to use Jakarta EE 9 APIs, for example, Jakarta Restful Web Services (previously known as JAX-RS) using Eclipse Jersey 3.0, use CometD 7.0.x and Jetty 11.0.x.
    If you are migrating from earlier CometD versions, skip entirely CometD 6.0.x: for example move from CometD 5.0.x and Jetty 9.4.x directly to CometD 7.0.x and Jetty 11.0.x.

  • OpenJDK 11 and TLS 1.3 issues

    At the Jetty Project we have been getting reports from the community as well as seeing random failures of load tests and benchmarks that were using TLS, and the failures were only happening with Java 11 (any version up to 11.0.2).

    Jetty users also saw TLS failures in their environments and opened issues about these failure, most notably issue #2939. Following that Jetty issue, OpenJDK issue JDK-8213202 was reported by @rraptorr (kudos for that!).

    The bad news is that JDK-8213202 is not fixed in Java 11.0.2, but it has been fixed in Java 12 (since jdk-12+21), and it has been backported to the OpenJDK 11 repository (and therefore will eventually be part of a future OpenJDK 11.0.x release – hopefully 11.0.3).

    The good news is that the issue can be worked around, while waiting for a Java 11 release that fixes it.

    It may be possible that you have been running Java 11 with TLS 1.3 without any problem for months, as JDK-8213202 is difficult to reproduce and we have only seen it trigger under moderate load and even in that case not all the times.

    Upgrade to Java 12 Solution

    If you can upgrade to Java 12 (at the time of this writing Java 12 is in Release Candidate status), that will solve JDK-8213202. The upgrade to Java 12 should be a drop-in from Java 11, but we recommend you test the upgrade thoroughly.

    Stay on Java 11 Solution

    If you must/want to stay on Java 11 – it is a long-term supported release – then you can work around JDK-8213202 by disabling TLS 1.3, which is used by default in Java 11 or greater, and use TLS 1.2.

    If you are using Jetty embedded you can use this code:

    SslContextFactory sslContextFactory = new SslContextFactory();
    sslContextFactory.setExcludeProtocols("TLSv1.3");

    If you are using Jetty standalone, you can create file $JETTY_BASE/etc/disable-tls13.xml as follows:

    
    <!DOCTYPE Configure PUBLIC "-" "http://www.eclipse.org/jetty/configure_9_3.dtd">
    <Configure id="sslContextFactory" class="org.eclipse.jetty.util.ssl.SslContextFactory">
      <Call name="addExcludeProtocols">
        <Arg>
         <Array type="java.lang.String">
           <Item>TLSv1.3
         </Array>
        </Arg>
      </Call>
    </Configure>

    Then you can start the Jetty standalone server in this way (from directory $JETTY_BASE):

    $ java -jar ../start.jar etc/disable-tls13.xml

    Alternatively, you can add the XML file to $JETTY_BASE/start.ini:

    ... # The existing content of your start.ini
    etc/disable-tls13.xml

    Java 11 Remarks

    Java 11.0.3 will hopefully contain the fix for JDK-8213202. It is unclear if Oracle will build a binary of OpenJDK 11.0.3 since OpenJDK 12 is due soon.

    If you have a support contract with an OpenJDK vendor, you will be able to obtain OpenJDK 11.0.3 through your vendor.

    If you don’t have a support contract with an OpenJDK vendor, you will still be able to obtain OpenJDK 11.0.3, for example through the AdoptOpenJDK Project.

    We will keep you up-to-date about the progress of this issue on this blog and on the @JettyProject Twitter account.

     

  • Running Jetty on the JPMS module-path

    Jetty and the Java Module System.

    Java 9 introduced the arguably biggest change in the Java platform since its inception, the Java Module System (a.k.a. Project Jigsaw, or Java Platform Module System – JPMS).
    The Java Module System primarily targets the modularization of the JDK itself, but can also be used to write modularized applications.
    Historically, Jetty has been often used to write applications that needed to embed an HTTP server without having too many dependencies. The fact that Jetty itself is a highly modular set of components allows you to use only the Jetty components that you need, reducing the dependencies and keeping your single application jar small.
    For example, you may need to embed Jetty as an HTTP server only, without the need for JSPs, without support for WebSocket, without HTTP/2: Jetty allows you to do that.
    You will be able to mix and match Jetty features by simply adding dependencies on the Jetty modules you need.
    Since Jetty is already modularized into Jetty modules, it would be great if a JPMS application could reference Jetty modules as JPMS modules.
    This is now possible since Jetty 9.4.14.

    JPMS modules for Jetty 9.4.x and Jetty 10.0.x

    To make Jetty modules available as JPMS modules we have taken a two-steps approach.
    First, the Jetty 9.4.x series now include the entryAutomatic-Module-Name in the fileMANIFEST.MF of each jar representing a Jetty module.
    This allowed us to lock down the definition of the Jetty JPMS module names, in the form of org.eclipse.jetty.* names.
    For example, the jetty-util Jetty module has a JPMS module name of org.eclipse.jetty.util, and so forth for other Jetty modules.
    Second, the Jetty 10.0.x series will include a proper module-info.java JPMS module file for each Jetty module. This will allow us to take advantage of the JPMS module system and hiding implementation classes that we don’t want to expose.
    With stable Jetty JPMS module names, JPMS applications that use proper module-info.java JPMS module files can reliably reference JPMS Jetty modules by name, and little will change when they will update their Jetty version from 9.4.x to 10.0.x (where Jetty will also use proper module-info.java JPMS module files).

    Running Jetty standalone on the module-path

    But Jetty is also a great standalone server!
    It is now possible to run Jetty as a standalone server on the module-path rather than on the class-path as it has always been.
    To run Jetty as a standalone server on the module-path, you just need to add an additional command line option, namely --jpms:

    # Create a new JETTY_BASE directory.
    $ mkdir jetty-base
    $ cd jetty-base
    # Configure the HTTP module.
    $ java -jar $JETTY_HOME/start.jar --add-to-start=http
    # Start Jetty on the module-path.
    $ java -jar $JETTY_HOME/start.jar --jpms
    

    That is all!
    Note that this will run the Jetty server on the module path.
    Web applications deployed to Jetty will not take advantage of the JPMS module system (yet).
    Making Web application take advantage of the JPMS module system is a matter for the Eclipse EE4J effort, but we may anticipate that effort in Jetty 10.0.x with some experiments on our own (if you are interested, follow this Jetty enhancement issue).
    We recommend using Java 11 to run Jetty on the module-path.
    Follow the Jetty JPMS documentation if you want to know more details about how to customize Jetty modules so that they are JPMS friendly, and let us know what you think!