I am working on a web application with dynamic content generated by a servlet running in a JBoss container and static content/load balancing being handled by Apache + mod_jk.
The client end uses jQuery to making AJAX requests to the servlet which processes them and in turn generates large JSON responses.
One thing I noticed is that the original author chose to manually compress the output stream in the servlet using something like below.
gzout = new GZIPOutputStream(response.getOutputStream());
Could this have been handled using mod_deflate on the Apache end? If you can do this, is it considered better practice, can you explain why or why not?
I believe it makes more sense to apply HTTP compression within Apache in your case.
If a server is properly configured to compress responses of this type (application/json, if the server-side code is setting the correct content-type), then it's being wastefully re-compressed after the manual compression anyway.
Also, what happens here if a client that doesn't support gzip makes a request? If you're compressing the response at the server level, it will automatically respond appropriately based on the request's accept-encoding header.
A little additional research shows a couple of good alternatives.
Issue:
There is a network channel that exists between Apache and Jboss. Without compression of any kind on the jboss end you'd have the same latency and bandwidth issues you have between Apache and your clients.
Solutions:
You can use mod_deflate on the Apache and accept uncompressed responses from jboss and compress before delivering to your clients. I could see this making some sense in certain network topologies(Proposed by Dave Ward).
You can apply a Java EE filter. This will filter responses compressing them before they exist the JBoss container. This has the benefit of compression at the JBoss level without a bunch of nasty GZIP related code in your business servlet.
JBoss with by default uses Tomcat as its Servlet engine. If you navigate to $JBOSS_HOME/deploy/jbossweb-tomcat55.sar you can edit the server.xml file to turn 'compression=on' attribute on the HTTP/1.1 connector. This will compress all responses outbound from the container.
The trade-off between 2 and 3 is compressing piece meal for different servlets or compressing all responses.
Related
I am running a Jetty-based Web Service behind an NGINX reverse proxy. Both Jetty and NGINX can handle the gzip compression/decompression for responses and requests. The typical payload is JSON, ranging from a few kilobytes up to tens of megabytes. Especially for larger payloads, the compression significantly impacts overall throughput.
What would be the most efficient point to handle the compression part - the JAVA service (Jetty) or the proxy (NGINX) if both sit on the same server?
Since NGINX uses a C-based gzip library, which is a lot more efficient and faster than JAVA's internal gzip, I would assume that NGINX should do the job. On the other hand, transferring bigger volumes of data between Jetty and NGINX has its own overhead. So I am not sure that the obvious choice is correct.
The only way to be sure would be to measure. However, I've done the same thing with .NET Core and Nginx and in that case compressing the JSON in Nginx was more efficient. Microsoft says as much.
Use server-based response compression technologies in IIS, Apache, or
Nginx. The performance of the middleware probably won't match that of
the server modules
I would assume that the same holds for Java/Jetty and Nginx.
In the HTTP/2 chapter in the High Performance Browser Networking book, there is a mention that
all existing applications can be delivered without modification.
Existing application using HTTP/1.1 use a request line, like POST /upload HTTP/1.1.
I think some code in our application should instead move the request line to a header frame. That means our application should consider the change from request line to header frame and deal with data frames as well.
Isn't that a modification?
This assumes your application is abstracted away from the raw HTTP implementation - as most applications are.
For example, let's assume you have created a Javascript web application (e.g. Angular), that talks through REST APIs to a web server (e.g. Apache), which proxies requests to a backend server (e.g. Node.js).
By adding HTTP/2 to the Apache Webserver your website and web application should benefit from HTTP/2 and be downloaded faster without any changes to your code. This despite the fact that your application (at both the front end Angular app and the back end Node.js server) likely uses a lot of HTTP semantics (e.g. Methods like GET and POST, headers... etc.). The web browser and web server should handle all the HTTP/2 stuff for you with no requirement to change your code or realise that you are using a different version of HTTP than what you originally write this app for as, fundamentally the concepts of HTTP have not changed even if the delivery method on the wire has.
Of course if you are writing at a lower level, and directly reading the bytes from the HTTP request then this may not be the case. But in most cases, unless you are writing a web server or browser, you will be going through a library and not looking at the direct request line and/or HTTP/2 frames.
Additionally, as the author of that book states above and below this quote, while changes will not be necessary in most cases to keep the application functioning, to get the most out of HTTP/2 may require changes to stop using HTTP/1.1 optimisations and learn new HTTP/2 optimisations.
To elaborate on BazzaDP's answer, from an application standpoint running on a web application framework, nothing changes. Those frameworks provide an abstraction of the underlying HTTP innards.
For example ASP.NET running on IIS provides a Request and Response object to the developer.
You can still use those objects' properties like Request.Headers or Response.Body, even though in HTTP/2 jargon those are called and transported different from HTTP/1.x.
The web server itself or the application framework running on top of it will handle the translation from network traffic to that object's properties and vice versa.
Let's say I wanted to create a collaborative web application where users can simultaneously work on e.g. a diagram. I have my interactive web site (HTML/CSS/JavaScript) on the client side, and let's say a Java application synchronizing a centralized model on the server side. How would client and server exchange messages? To get a better idea of how the system is supposed to work like, here are some details and a small illustration:
Requirements
The underlaying technology should support authorized communication to show/hide sensitive information.
The model of the diagram should only exist on the server (centralized model, no copies), whereby changes should be broadcasted to other users (other browsers who are currently editing the same document).
After receiving changes to the model, the server shall perform computationally higher demanding tasks such as consistency checks and inform the user if e.g. an action is invalid.
Constraints
The system must not poll or set flags (it should be a direct communication).
The website must not be reloaded during use.
Software running on the client must be restricted to JavaScript.
Technology I've found
Here are some of the solutions I've looked at, ranked from (imho) most suitable to least, whereby I'm not sure if the list is even complete and all my assumptions are correct.
Java Web Service using javax.jws - The service would offer an API described by WSDL and be capable of responding with SOAP messages using the HTTP protocol, but can JavaScript process these messages?
Servlets & Java Server Pages (JSPs) - Would, as far as I know, require a page reload to fetch new content (isn't this pretty much the same as PHP? Both are executed on the server to generate HTML pages..)
I've already found this question which, however, does not provide concrete technologies in the answer. Thank you for any hints and clarification, I dearly appreciate it!
As you have already found out, there are many approaches to this common problem.
SOAP (sometimes called "Web Services" or "WS*") is a standard that was developed for application to application communication. It's strengths are precise specifications (and therefore many good libraries), interface sharing for client and server (through WSDL), and discoverability.
However, SOAP has very limited -if any- support in Browsers.
The most common modern approach is probably RESTful web services based on XML or JSON. When used in a browser as client, JSON is preferred, as the unmarshalling is trivial in JavaScript. Many frameworks and libraries like Angular and jQuery take on the tedious cross-browser AJAX request crafting. Some boilerplate is required to wrap the data in HTML, however. This downside can also be an upside if you consider the cleaner architecture and maintainability.
Since you're using Java on your server, you might also want to look into JSFs AJAX capabilities. It doesn't really use REST (no well-defined resources), but loads server-side rendered chunks of your HTML page asynchronously (read: AJAX) and re-renders them in the DOM. This can be seen as a compromise between real REST and full page reloading. The good side of it is you don't have to define any resources but your backing beans. The downsides are: possible overhead, since you're downloading HTML instead of pure data; and bad testability since you cannot access the rendered chunks outside the JSF context.
Wholly different issues are 1. the synchronization of concurrent requests and 2. communication with clients from server. For the latter you can either look into Web Sockets (the next big thing) or the good-old polling.
If concurrent edits of the same data are a concern to you, you'll have to implement a sort of strategy to tell whether edits can be merged or whether one has to be declined. The client will need to handle such situations and offer the user reviewing, overriding or reverting etc.
EDIT: more on Java servlets and JSP
Servlets are nothing but Java classes that handle specific HTTP requests, usually bound to certain URL paths. They're comparable to PHP pages: In PHP the web server gets a request and searches for a corresponding PHP file. Then it parses the PHP script and returns the response. Servlets do the same, only the syntax is very different. JSP is mostly a try at bringing more PHP-ish syntax to Java. Behind the curtains, they're rendered to pure Java servlets.
Java servlets have a long history which is older than AJAX, but many frameworks have taken on the challenge of implementing flexible resource handling on the server. Most notably Jersey and RESTEasy, which are implementations of the Java EE standard JAX-RS; and Spring, which is a request-based framework that competes well against Java EE standards. Then there is also JSF, which is sometimes called a successor of JSP. To the user it's little different than JSP, but the syntax is nicer and IMHO it is more feature-rich than JSP. Especially considering extensions like PrimeFaces. In contrast to JSP, JSF embraces AJAX and many built-in components are capable of communicating with the server using AJAX, including calling Java functions and re-rendering parts of the page.
I would recommend you try websockets since connections will be persistent between clients and server and any of them can send a message at any time.
You could implement a websocket server in Java on the server and use Javascript's built in websockets functionallity on the clients.
Take a look at https://www.websocket.org/ to learn more about websockets.
My setup is a WAR deployed though elasticBeanstalk on a Tomcat7/Java7 app. I'm doing basic HTML with Servlets, and REST. Nothing fancy.
I would like to replace the default server.xml for Tomcat7/Java7 under my elasticBeanstalk.
http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/customize-containers.html
I'm a bit confused.
I'm looking for reasonable performance tuning numbers for the parameters there.
Looking for good defaults for security as well
Should I touch the AJP connector? (every request goes to a servlet) what should I configure?
Does this setup have Apache as a front-end, or do the HTTP requests go directly to Tomcat?
My instance is choking after a relatively low amount of concurrent users, with ~9% CPU, and plenty of DB connections. Am I jumping to conclusions with server.xml?
Thanks..
AJP is not necessary as you have mentioned that most of the URL requests are servlet based. You can use AJP incase if you have more static contents to serve.
Most of the cases the performance tuning needs to be done at the web frontend part. Below are my suggestions.
Use gzip compression for web contents.
Make your pages cachable by using cache related HTTP headers (Etag, Expires, Cache-control,). By doing so you will reduce the number of unwanted HTTP requests.
JS and CSS can be minified inorder to reduce their sizes.
Check if you are getting more traffic from web crawlers. If you are getting more traffic from those try to reuse web sessions with Crawler_Session_Manager_Valve.
Try to index key tables of your database.
Make sure you are using DB connection pooling instead of opening new connections for every new request.
Avoid unwanted URL redirections (302, 304).
Incase if you are looking for a good book that can help you optimize your website refer High Performance Web Sites for O'Reilly
I have a site that is being polled rather hard for the JSON representation of the same resources from multiple clients (browsers, other applications, unix shell scripts, python scripts, etc).
I would like to add some caching such that some of the resources are cached within the server for a configurable amount of time, to avoid the CPU hit of handling the request and serialising the resource to JSON. I could of course cache them myself within the handlers, but would then take the serialisation hit on every request, and would have to modify loads of handlers too.
I have looked at the openrasta-caching module but think this is only for controlling the browser cache?
So any suggestions for how I can get openrasta to cache the rendered representation of the resource, after the codec has generated it?
Thanks
openrasta-caching does have preliminary support for server-side caching, with an API you can map to the asp.net server-side cache, using the ServerCaching attribute. That said it's not complete, neither is openrasta-caching for that matter. It's a 0.2 that would need a couple of days of work to make it to a good v1 that completely support all the scenarios I wanted to support that the asp.net caching infrastructure doesn't currently support (mainly, make the caching in OpenRasta work exactly like an http intermediary rather than an object and .net centric one as exists in asp.net land, including client control of the server cache for those times you want the client to be allowed to force the server to redo the query). As I currently have no client project working on caching it's difficult to justify any further work on that plugin, so I'm not coding anything for it right now. I do have 4 days free coming up though, so DM me if you want openrasta-caching to be bumped to 0.3 with whatever requirements you have in that that would fit 4 days of work.
You can implement something simpler using an IOperationInterceptor and plugging in the asp.net pipeline using that, or be more web-friendly and implement your caching out of process using squid and rely on openrasta-caching for generating the correct http caching instructions.
That said, for your problem, you may not even need server caching if the cost is in json. If you map a last modified or an Etag to what the handler returns, it'll generate correctly a 304 where appropriate, and bypass json rendering alltogether, provided your client does conditional requests (and it should).
There's also a proposed API to allow you to further optimize your API by doing a first query on last modified/etag to return the 304 without retrieving any data.