Deploying the hipstr application

The lein-ring plugin can create 2 different types of packages for deployment: an uberjar or an uberwar. These are created using lein ring uberjar or lein ring uberwar respectively:

  • uberjar: Creates an executable .jar file containing all dependencies, including an embedded Jetty server
  • uberwar: Creates a standard .war file containing all dependencies, which can be deployed to any Java web application server (such as Tomcat or GlassFish)

    Note

    Check out the official lein-ring documentation to get more details about the various options available for ring uberwar/uberjar at https://github.com/weavejester/lein-ring.

How you're going to deploy your application determines how you're going to package your application.

When to use an uberjar

Because Ring applications have an embedded Jetty server, we have the option of creating a self-contained, fully independent uberjar, which contains all the required dependencies and can run on its own. The advantage of this is that deployment becomes dead simple – you simply copy the uberjar to a server and run it as you would any other Java application (we'll do this later in the chapter). If we want another instance of our app, we can simply fire it up like any other Java app – Ring will automatically determine which port to serve on (starting at 3000 and going up from there).

Running as an uberjar has some drawbacks though: You don't get a fancy administrative console like you do with a Java application server, which means that you'll be rolling a lot of configuration by hand. The standalone uberjar is pretty barebones, but in the world of web applications, rarely have I worked on anything that actually required all the functionality that's embedded inside an application server.

When to use an uberwar

If you plan on deploying to an application server, then you'll need to package the application as an uberwar.

Application servers provide a whole truckload of features, such as queuing, configuration management, clustering (though we can use Nginx and multiple instances of a standalone server to accomplish this), and so on. Most application servers allow you to configure their features through a UI (though in my experience these are often clunky). Some application servers, such as GlassFish, are free and open source. Others, however, such as WebSphere and WebLogic, cost an arm and a leg.

The downsides of application servers are cost and, often times, bloated. They can be fairly resource intensive, expensive, and complicated. Also, chances are you aren't going to need an application server; in the world of Clojure web application development, I've yet to write anything that requires the golden handcuffs of an application server. Most Clojure web applications are deployed as a standalone application.

Deploying as a standalone

The easiest way to deploy a Ring application is as a standalone application, and just use the embedded Jetty server. This is the killer feature as far as I'm concerned. To create a standalone hipstr application, perform the following steps:

  1. In a terminal, and from the project root folder, run lein ring uberjar. This produces 2 jars:
    • ./target/hipstr-0.1.0-SNAPSHOT.jar: Contains all our hipstr application code and dependencies.
    • ./target/hipstr-0.1.0-SNAPSHOT-standalone.jar: An executable, standalone version which includes an embedded Jetty server and all dependencies. This is entirely self-contained.
  2. Fire up the hipstr application by doing the following in the ./target directory (keeping in mind that we can use Java system properties to set the environment configuration, such as the -D Java system properties below):
    # java -jar -Ddb.classname=org.postgresql.Driver -Ddb.subprotocol=postgresql -Ddb.subname=//localhost/postgres -Ddb.user=hipstr -Ddb.password=p455w0rd hipstr-0.1.0-SNAPSHOT-standalone.jar

    Tip

    If you get an error about "could not find users.sql", ensure the [:uberjar :omit-source] in project.clj file is set to false. If set to true, then lein ring uberjar will remove our .sql files from the packaged jar.

As is the case with the development server, the above command will serve on port 3000. Also like the development server, the above command will execute in the foreground, which you can stop by hitting Ctrl + C, or by shutting down the terminal. However, in a non-dev/local environment you'll want to run the application in the background, which can be done by using nohup:

# nohup java -jar -Ddb.classname=org.postgresql.Driver -Ddb.subprotocol=postgresql -Ddb.subname=//localhost/postgres -Ddb.user=hipstr -Ddb.password=p455w0rd hipstr-0.1.0-SNAPSHOT-standalone.jar &

This will persist the application after you close down the terminal. To stop the application, you first get the process ID using ps -ef, and then kill -15 that process:

# ps -ef | grep hipstr
>> 501 68443 58530   0  6:07pm ttys000 0:09.00 /usr/bin/java -jar...
# kill -15 68443

Keep in mind that you can export environment variables (using "_" instead of ".", such as using DB_CLASSNAME instead of db.classname) if you don't want to use Java system properties. However, this will force every instance of the hisptr application on that machine to have the same database connection. You'll have to decide which makes more sense.

Running the application behind Nginx

Nginx is quickly becoming a popular web-server/reverse-proxy. Its configuration is relatively simple and clean compared to the now-dated Apache. And it's fast. Blisteringly fast. Scary fast!

We can use Nginx to reverse-proxy port 80 to our hipstr application's port 3000 by performing the following steps:

  1. Download and install Nginx for your platform. You can download Nginx from http://wiki.nginx.org/Install.
  2. Deploy and run a standalone hipstr, as outlined in the Deploying as a standalone section earlier in this chapter.
  3. Back up the Nginx default site configuration (note that your location may differ):
    # mv /etc/nginx/sites-available/default /etc/nginx/sites-available/default.bak
    
  4. Create a new default site configuration file with whatever your favorite tool is (I tend to use nano because I've never bothered to learn vi. Blasphemy, I know):
    # nano /etc/nginx/sites-available/default
    
  5. Add the following configuration to the new default configuration file, specifying values for anything [inside square brackets], except the [::] wildcard:
    server {
        # listen on port 80, but apply this explicitly to 
        # only the default server
           listen 80 default_server;
    
        # only allow IPv6 socket to process 
        # IPv6 connections
          listen [::] 80 default_server ipv6only=on;
    
        # specify a "catch-all"; any host name on port 80 
        # will be affected.
        server_name _;
    
        # log files
           access_log /var/log/hipstr_access.log;
           error_log /var/log/hipstr_error.log;
    
        # proxy settings
           location / {
              # proxies all requests under "/" to 
              # our hipstr standalone instance
              proxy_pass http://localhost:3000/;
    
              # forwards the original Host header
              proxy_set_header Host $http_host;
    
              # forwards the X-Forwarded-For client 
              # request header, if it exist,
              # as well as the client's remote 
              # address (IP), separated by a comma.
              proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    
              # forwards the original protocol 
              # (eg. https or http)
              # in the real world you'd likely want
              # to do SSL termination, and setup 
              # whatever's hosting the hipstr 
              # standalone to only trust incoming 
              # traffic from the fronting nginx's 
              # IP.
              proxy_set_header X-Forwarded-Proto $scheme;
    
              # cancel the effect of all 
              # proxy_redirect directives
              proxy_redirect off;
              }
    }
  6. Reload Nginx.
    # nginx -s reload;

Now whenever you hit up port 80, instead of explicitly stating port 3000, you'll get our hipstr application.

Load balancing behind Nginx

Using Nginx, we can easily proxy multiple hipstr applications by employing a round-robin approach between all of them:

  1. Open /etc/nginx/sites-available/default to edit it.
  2. Before the server {...} block, add the following:
    upstream hipstr {
        server localhost:3000;
        server localhost:3001;
        server localhost:3002;
    }
  3. Lastly, adjust proxy_pass in the location / configuration section of the server block so that it looks like the following:
    location / {
        # proxies all requests under "/" to 
        # our hipstr standalone instance
           proxy_pass http://hipstr;
  4. Save and close the configuration file, then reload Nginx:
    # nginx -s reload
  5. Now fire up a couple more instances of the hipstr application using the nohup command.

That's all there is to it! You are now running a round-robin balanced cluster of hipstr applications! How easy was that!

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.147.59.198