Deploying a decoupled front + backend of an applic

2019-02-20 21:09发布

问题:

I've written a web app using two completely decoupled components:

  1. An API that is based off the Place Framework and serves requests of type: /api/* to any client.
  2. A decoupled front end based on AngularJS built using grunt build

Now, the front end talks to the API but I'd like both of these units to be deployed behind a proxy, something like nginx that can proxy incoming requests to the respective component. For example, I'd like all the /web/* requests to be served off a web directory containing all the client side source (js/html/etc.) and all the /api/* requests to be proxied to my Play framework server (we will need to pass on the path to the server to make sure the right paths are served back) to return all the API related data. For example, a request like GET domain.com/api/users should be internally proxied to GET 127.0.0.1:9000/api/users.

I've seen some discussions online about this and I'd still like to run it through you guys to see which is the best approach for this kind of deployment.

Eventually, I'd like a service oriented architecture and I'd like the flexibility to decouple things even further.

回答1:

I have built and deployed Play Framework + AngularJS apps and found nginx to be a great approach.

Nginx also gives you a growth path to handle more services as your app architecture grows. For example, you might add a dedicated service for /api/user/* while keeping the standard service for all other /api/* routes.

At some point you might need to go to a commercial product but for my needs for now and the foreseeable future, nginx is amazing.

The relevant part of my nginx config is:

server {
    listen       80;

    # Without this, Play serves the assets from within it's bundled jar. That's
    # fine and works but seems unnecessary when nginx can serve the files directly.
    location /assets {
        alias /app/live/my-play-app-here/active/public;
    }

    location / {
        proxy_pass            http://localhost:9000;
        proxy_set_header      X-Real-IP  $remote_addr;
    }
}

The key part here is the /assets URI-space. Yours will probably be different because you package your AngularJS app completely independently. My angular app is within the Play app's /app/assets/javascripts folder. There are pros and cons to this (I quite like your idea of keeping it completely separate). What I've done with the /assets block is allowed nginx to serve the static content directly, as it seems pretty silly for Play to serve that when nginx does a fine job.

It's not so relevant in your scenario but for others that have everything within Play, for the above serving-static-assets strategy to work, the deployment process needs to unpack the public directory from the archive made by play dist, something like this (an excerpt from my bash deployment script):

    unzip lib/$SERVICE_BASE_NAME.$SERVICE_BASE_NAME-$VERSION.jar "public/*"

For your particular scenario, something like the below is probably a good start:

server {
    listen       80;

    location /api {
        proxy_pass            http://localhost:9000;
        proxy_set_header      X-Real-IP  $remote_addr;
    }

    location / {
        alias /app/live/my-angularjs-app-here/active/public;
    }
}