• No results found

Apache with HTTP

In document Servers for Hackers - Chris Fidao (Page 107-114)

Apache can proxy requests to gateways or programs using HTTP. Some languages can speak HTTP directly while some gateways prefer to use HTTP.

Technically this means we could skip using a web server altogether and serve HTTP requests to them directly.

Apache 94 A more typical setup, however, is to put a web server such as Apache “in front of” an application.

In such a setup, Apache would handle all HTTP requests. It would either handle the request itself or “proxy” the request to the application gateway.

This has certain benefits:

• Apache can handle requests for static assets. This frees the application from wasting resources on static assets.

• Apache can send requests to pools of resources of the application. Instead of one running NodeJS process, picture 3-4 running! Apache can send requests to each of them. This would substantially increase the number of requests the application could simultaneously handle.

This essentially is load balancing.

• Some gateways monitor and manage multiple application processes for us. A gateway will expose one HTTP listener for Apache to send requests to. The gateway would then be responsible for sending requests to each running process. Some gateways can dynamically spin up and destroy running application processes.

Let’s see how Apache can proxy requests off to an application listening for HTTP requests.

Here’s an example NodeJS application. It will accept any HTTP request and respond with “Hello, World!”.

File: /srv/http.js

1 #!/usr/bin/env node

2 var http = require('http');

3

4 function serve(ip, port) 5 {

6 http.createServer(function (req, res) {

7 res.writeHead(200, {'Content-Type': 'text/plain'});

8 res.end("Hello, World!\n");

9 }).listen(port, ip);

10 console.log('Server running at http://'+ip+':'+port+'/');

11 } 12

13 // Create a server listening on all networks 14 serve('0.0.0.0', 9000);

We can run this node “application” with the simple command: nodejs /srv/http.js. This application will listen on all network interfaces on port 9000. We can test this once it’s running.

You may need to open a new terminal window to test this while the NodeJS process is running:

Apache 95

1 # From within the server 2 $ curl localhost:9000 3 Hello, World!

Once that application is working, we need to configure Apache to send requests to it.

We’re proxying requests directly to a test application. This NodeJS application is not a gateway. We’ll see how to proxy requests to a gateway such as uWSGI or PHP-FPM in this chapter.

First we need to ensure the proxy and proxy_http modules are enabled. These allow Apache to proxy requests off to another process (application or gateway) over HTTP.

1 # Enable modules

2 sudo a2enmod proxy proxy_http 3

4 # Restart Apache

5 sudo service apache2 restart

Then we can adjust our vhost file to proxy requests off to our NodeJS application.

1 <VirtualHost *:80>

9 Options -Indexes +FollowSymLinks +MultiViews 10 AllowOverride All

Apache 96

27 # Possible values include: debug, info, notice, warn, error, crit, 28 # alert, emerg.

This vhost file is just like what we used earlier in this chapter. However there are some additions within the<Directory ...>directive. Let’s cover those:

1 <Proxy *>

2 Require all granted 3 </Proxy>

TheProxy³⁰directive let’s you configure all matched proxies. In this case, we’re adding settings for for all configured proxies, as denoted by the wildcard ‘*’.

With the Proxy directive, we simply repeatRequire all granted. This authorizes the request to be proxied from any host. This can be used to restrict what clients can use the proxy. In this case, we want the whole world to reach our application, and so we’ll have Apache send requests to our application from any host.

Next we have a<Location ...>directive:

1 <Location />

2 ProxyPass http://localhost:9000/

3 ProxyPassReverse http://localhost:9000/

4 </Location>

The “location” represents a URI (and any sub-directory URIs) used. In this case,/effectively means

“any URI”. This will proxy all requests to the application by directing it tolocalhost:9000. Using httpin the socket location tells Apache to proxy this as an HTTP request.

Lastly, we have a<Location ...>directive for the/staticURI:

³⁰http://httpd.apache.org/docs/current/mod/mod_proxy.html#proxy

Apache 97

1 <Location /static>

2 ProxyPass ! 3 </Location>

We want Apache to handle requests for static assets. This is easy with PHP, whose files typically end in the.php. This allows us to pass requests ending in .php off to an application. We can say

“Only send files ending in.phpto the application”.

Ths becomes an issue with other languages. Application of other languages typically don’t run through a specific file.

One popular solution for informing Apache when to serve static assets is to put all static assets a specific directory. The above configuration does just that. Any URI which starts with/staticwill not be passed to the application. TheProxyPass !directive tells Apache not to proxy the request.

Apache will automatically add X-Forwarded-* headers³¹ to servers when ProxyPass is used. More information about these headers and their use is in the Multi-Server Environments section of this book.

Multiple back-ends

We can proxy between multiple back-ends.

For example, let’s pretend our application spawns multiple processes to listen on. This might be done to increase the number of concurrent requests it can handle. We’ll simulate that by adjusting the last line of our NodeJS script to listen on three addresses:

File: /srv/http.js, bottom of file

1 serve('0.0.0.0', 9000);

2 serve('0.0.0.0', 9001);

3 serve('0.0.0.0', 9002);

Once edited, we can restart this process runningnodejs /srv/http.js. It will then be listening on all network interfaces at port 9000, 9001 and 9002.

Next we can adjust our Apache configuration. We’re essentially load balancing between the three back-end servers. To do so, we can use Apache’sproxy_balancermodule.

We also need to enablelbmethod_byrequests. This is the default method used byproxy_balancer to determine how Apache will balance between the back-ends.

³¹http://httpd.apache.org/docs/current/mod/mod_proxy.html#x-headers

Apache 98 You can find information on Apache’s various Load Balancing algorithms in the

proxy_-balancerdocumentation³².“By Requests”³³attempts to distribute traffic evenly amongst Apache workers. T> T> We’ll cover load balancing in depth in the Multi-Server Environ-ments section. However we won’t cover load balancing in Apache, as there are better and simpler tools.

1 # Enable the needed modules

2 sudo a2enmod proxy_balancer lbmethod_byrequests 3

4 # Restart Apache

5 sudo service apache2 restart

Then we can adjust the vhost file:

1 <VirtualHost *:80>

9 Options -Indexes +FollowSymLinks +MultiViews 10 AllowOverride All

Apache 99

26

27 ErrorLog ${APACHE_LOG_DIR}/example.com-error.log 28

29 # Possible values include: debug, info, notice, warn, error, crit, 30 # alert, emerg.

This setup is fairly similar. Let’s go over the edited directives.

1 <Proxy balancer://mycluster>

2 BalancerMember http://localhost:9000/

3 BalancerMember http://localhost:9001/

4 BalancerMember http://localhost:9002/

5 </Proxy>

This defines a balancer cluster named ‘mycluster’. The name can be anything. Then we define our three back-ends. In this case, the back-ends are the three Node HTTP listeners that we defined above.

Then our<Location...>directive needs tweaking to proxy requests to this balancer cluster rather than to the HTTP listener directly:

1 <Location />

2 ProxyPass balancer://mycluster/

3 ProxyPassReverse balancer://mycluster/

4 </Location>

That’s it! This will distribute traffic amongst the three defined members of the balance cluster.

Our<Location...>directive for the/staticdirectory is the same. It will continue to serve static assets.

The proxy module is handy for proxying to HTTP listeners. It can proxy requests to applications written in NodeJS or Golang. It’s also commonly used to communicate with gateways listening on HTTP. Unicorn, Gunicorn and uWSGI are three common gateways which may create HTTP listeners.

Apache 100

In document Servers for Hackers - Chris Fidao (Page 107-114)

Related documents