In the previous section, you created a network load balancer that is restricted to one region in the Google Cloud Platform. This type of setup works well for companies whose customers are in one geographical region. For global enterprises that have customers around the globe, having a setup in one geographical region means low-latency network access to customers in one region but medium- to high-latency network access to other groups of users. Hence, many organizations with customers spread globally need multiple points of presence for their IT footprint. This requirement is well served by the HTTP load balancer and is covered in this section.
The key components of the HTTP load balancer are as follows:
-
Global forwarding rule
-
Target proxy
-
URL map
-
Backend services
-
Instance groups
Global Forwarding Rules
Global forwarding rules route incoming network traffic by IP address, port, and protocol to a load-balancing configuration, which consists of a target proxy, a URL map, and one or more backend services. Similar to the forwarding rules in network loading balancing, global forwarding rules assign a single global IP address, which can be either static or an ephemeral IP address. This single global IP address can be used in a DNS record, negating the need for traditional DNS-based round-robin load balancing.
Target HTTP Proxy
The target HTTP proxy, as the name suggests, is the endpoint on the Compute Engine side that terminates the incoming HTTP/TCP connection from the user. A new connection is then made by the proxy to the next internal network hop, known as the URL map. The proxy also adds additional request/response HTTP headers to the HTTP connection, as follows:
Via: 1.1 Google (requests and responses)
X-Forwarded-For: <client IP>, <global forwarding rule external IP> (requests only)
By inspecting the HTTP headers, the clients and the server can extract key information. For example, an analytics module on the server side should use the <client IP> in the X-Forwarded-For header instead of the source-ip of the TCP connection, because the latter is always the proxy IP. The clients can also parse the HTTP connection and know that a Google proxy is serving them, and not the actual server, although the DNS resolution of the domain provides the server’s IP address.
URL Maps
URL maps define regular-expression matching patterns to filter the incoming requests and forward them to different sets of backend services. They are typically used in content-based routing architectures where different backend services serve different type of content, such as images, videos, and text. A default service is defined to handle any requests that are not matched by any other rule. This is sufficient for a multi-region load-balancing setup.
Backend Services
Backend services define groups of backend instances and their serving capacity. The serving capacity is defined either as CPU usage or requests per second (RPS). The backend service also specifies the health checks that will be performed against the available instances. The health checks are the same as described earlier for network load balancing.
Instance Groups
Instance groups are a grouping mechanism that defines VM instances that are available as a backend-services group. A backend service may list a set of instance groups instead of individual instances. You can add instances to and remove them from an instance group, and the instance group can be used for other cloud services in addition to load balancing.
Load-Distribution Algorithm
HTTP load balancing provides two methods of determining an instance load: RPS and CPU utilization modes. Both modes let you specify a maximum value. Incoming requests are sent to the region that is closest to the user and that has remaining capacity.
Going Live
This example uses the two instances you created in the previous two sections. In addition to these two instances in the Asia region, you add four more instances: two in Europe and two in the United States. All the instances are in different zones. In addition, you automate the installation of a web server using a startup script. Compute Engine executes the startup script as part of VM startup. Following are the required Linux commands and the output of these steps:
$ echo "apt-get update
&
apt-get install -y apache2
&
hostname > /var/www/index.html" > \
$ HOME/gce:startup.sh
$ gcloud compute instances create frontend-us1 --image debian-7 \
--zone us-central1-a --metadata-from-file startup-script= $ HOME/gce:startup.sh
Created [
https://www.googleapis.com/compute/v1/projects/cloud-platform-book/zones/us-central1-a/instances/frontend-us1
].
NAME ZONE MACHINE_TYPE INTERNAL_IP EXTERNAL_IP STATUS
frontend-us1 us-central1-a n1-standard-1 10.240.154.170 130.211.186.207 RUNNING
$ gcloud compute instances create frontend-us2 --image debian-7 \
--zone us-central1-b --metadata-from-file startup-script= $ HOME/gce:startup.sh
Created [
https://www.googleapis.com/compute/v1/projects/cloud-platform-book/zones/us-central1-b/instances/frontend-us2
].
NAME ZONE MACHINE_TYPE INTERNAL_IP EXTERNAL_IP STATUS
frontend-us2 us-central1-b n1-standard-1 10.240.124.81 104.154.39.159 RUNNING
$ gcloud compute instances create frontend-eu1 --image debian-7 --zone europe-west1-b --metadata-from-file startup-script= $ HOME/gce:startup.sh
Created [
https://www.googleapis.com/compute/v1/projects/cloud-platform-book/zones/europe-west1-b/instances/frontend-eu1
].
NAME ZONE MACHINE_TYPE INTERNAL_IP EXTERNAL_IP STATUS
frontend-eu1 europe-west1-b n1-standard-1 10.240.232.37 146.148.126.134 RUNNING
$ gcloud compute instances create frontend-eu2 --image debian-7 \
--zone europe-west1-c --metadata-from-file startup-script= $ HOME/gce:startup.sh
Created [
https://www.googleapis.com/compute/v1/projects/cloud-platform-book/zones/europe-west1-c/instances/frontend-eu2
].
NAME ZONE MACHINE_TYPE INTERNAL_IP EXTERNAL_IP STATUS
frontend-eu2 europe-west1-c n1-standard-1 10.240.95.225 104.155.11.26 RUNNING
Using a web browser, verify that you can access each instance through its public IP address. If they are not accessible, check whether the firewall rules have been added to enable access at port 80.
The following are the logical steps to set up the HTTP load-balancing service:
-
1.
Create instance groups, one per zone.
-
2.
In these zones, add instances to the instance groups.
-
3.
Add the required HTTP service to each instance group.
-
4.
Create or reuse an HTTP health-check object.
-
5.
Create a backend service linking the health check.
-
6.
Add instance groups as backends to the backend service.
-
7.
Create a URL map to direct ingress traffic to the backend service.
-
8.
Create a target HTTP proxy to route requests to the URL map.
-
9.
Create a global forwarding rule to send traffic to the HTTP proxy.
Here are the gcloud commands to carry out these steps:
Note
Some gcloud commands use preview instead of the compute option. This is because they are in a beta state, and it is possible the API and gcloud options may change as the product goes into GA release. If the following commands do not work, check the current versions at
http://cloud.google.com/compute/docs
.
# Step 1 - gcloud commands to create instances groups
$ gcloud preview instance-groups --zone us-central1-a create ig-usc1a
Instance group ig-usc1a created.
$ gcloud preview instance-groups --zone us-central1-b create ig-usc1b
Instance group ig-usc1b created.
$ gcloud preview instance-groups --zone europe-west1-b create ig-euw1b
Instance group ig-euw1b created.
$ gcloud preview instance-groups --zone europe-west1-c create ig-euw1c
Instance group ig-euw1c created.
$ gcloud preview instance-groups --zone asia-east1-a create ig-ape1a
Instance group ig-ape1a created.
$ gcloud preview instance-groups --zone asia-east1-b create ig-ape1b
Instance group ig-ape1b created.
# Step 2 - gcloud commands to add instances to instance groups
$ gcloud preview instance-groups --zone us-central1-a instances \
--group ig-usc1a add frontend-us1
Instances added to instance group ig-usc1a.
$ gcloud preview instance-groups --zone us-central1-b instances \
--group ig-usc1b add frontend-us2
Instances added to instance group ig-usc1b.
$ gcloud preview instance-groups --zone europe-west1-b instances \
--group ig-euw1b add frontend-eu1
Instances added to instance group ig-euw1b.
$ gcloud preview instance-groups --zone europe-west1-c instances \
--group ig-euw1c add frontend-eu2
Instances added to instance group ig-euw1c.
$ gcloud preview instance-groups --zone asia-east1-a instances \
--group ig-ape1a add frontend-master
Instances added to instance group ig-ape1a.
$ gcloud preview instance-groups --zone asia-east1-b instances \
--group ig-ape1b add frontend-slave
Instances added to instance group ig-ape1b.
# Step 3 - gcloud commands to add required http service to each instance group
$ gcloud preview instance-groups --zone us-central1-a add-service ig-usc1a \
--port 80 --service http
Service http:80 added.
$ gcloud preview instance-groups --zone us-central1-b add-service ig-usc1b \
--port 80 --service http
Service http:80 added.
$ gcloud preview instance-groups --zone europe-west1-b add-service ig-euw1b \
--port 80 --service http
Service http:80 added.
$ gcloud preview instance-groups --zone europe-west1-c add-service ig-euw1c \
--port 80 --service http
Service http:80 added.
$ gcloud preview instance-groups --zone asia-east1-a add-service ig-ape1a \
--port 80 --service http
Service http:80 added.
$ gcloud preview instance-groups --zone asia-east1-b add-service ig-ape1b \
--port 80 --service http
Service http:80 added.
You created an HTTP health check earlier, in the network load-balancing section, and you reuse it here. If you have deleted it, you can create a new one using the following command:
# Step 4a - List any existing http health check objects
$ gcloud compute http-health-checks list
NAME HOST PORT REQUEST_PATH
http-check 80 /
# Step 4b - Create a new http health check object (if required)
$ gcloud compute http-health-checks create http-check
# Step 5 - Create a backend service
$ gcloud compute backend-services create web-service --http-health-check http-check
Created [
https://www.googleapis.com/compute/v1/projects/cloud-platform-book/global/backendServices/web-service
].
NAME BACKENDS PROTOCOL
web-service HTTP
# Step 6 - Add instance groups as backends to backend service
$ gcloud compute backend-services add-backend web-service \
--group ig-usc1a --zone us-central1-a
Updated [
https://www.googleapis.com/compute/v1/projects/cloud-platform-book/global/backendServices/web-service
].
$ gcloud compute backend-services add-backend web-service \
--group ig-usc1b --zone us-central1-b
Updated [
https://www.googleapis.com/compute/v1/projects/cloud-platform-book/global/backendServices/web-service
].
$ gcloud compute backend-services add-backend web-service \
--group ig-euw1b --zone europe-west1-b
Updated [
https://www.googleapis.com/compute/v1/projects/cloud-platform-book/global/backendServices/web-service
].
$ gcloud compute backend-services add-backend web-service \
--group ig-euw1c --zone europe-west1-c
Updated [
https://www.googleapis.com/compute/v1/projects/cloud-platform-book/global/backendServices/web-service
].
$ gcloud compute backend-services add-backend web-service \
--group ig-ape1a --zone asia-east1-a
Updated [
https://www.googleapis.com/compute/v1/projects/cloud-platform-book/global/backendServices/web-service
].
$ gcloud compute backend-services add-backend web-service \
--group ig-ape1b --zone asia-east1-b
Updated [
https://www.googleapis.com/compute/v1/projects/cloud-platform-book/global/backendServices/web-service
].
# Step 7 - Create URL Map to direct ingress traffic to backend service
$ gcloud compute url-maps create web-map --default-service web-service
Created [
https://www.googleapis.com/compute/v1/projects/cloud-platform-book/global/urlMaps/web-map
].
NAME DEFAULT_SERVICE
web-map web-service
# Step 8 - Create target HTTP proxy to route requests to URL map
$ gcloud compute target-http-proxies create web-proxy --url-map web-map
Created [
https://www.googleapis.com/compute/v1/projects/cloud-platform-book/global/targetHttpProxies/web-proxy
].
NAME URL_MAP
web-proxy web-map
# Step 9 - Create Global forwarding rule to send traffic to HTTP proxy
$ gcloud compute forwarding-rules create http-rule --global \
--target-http-proxy web-proxy --port-range 80
Created [
https://www.googleapis.com/compute/v1/projects/cloud-platform-book/global/forwardingRules/http-rule
].
NAME REGION IP_ADDRESS IP_PROTOCOL TARGET
http-rule 107.178.245.89 TCP web-proxy
At this stage, if you open a web browser with http://<global-forwarding-rule-ip>, your request is routed to the instance that is nearest to you. Let us send some traffic to the HTTP load balancer you have set up, and see its responses. Note that my workstation was in Singapore for this test:
$ while true; do curl -m1 107.178.245.89; done
frontend-master
frontend-master
frontend-master
Let us simulate system maintenance in the setup by shutting down the Apache web servers in both of Asian nodes and see if the traffic is automatically routed to the next-best location:
$ gcloud compute ssh frontend-master --zone asia-east1-a
...
Last login: Sun Jan 25 04:06:14 2015 from 1.2.1.1
VM$ sudo service apache2 stop
[ ok ] Stopping web server: apache2 ... waiting .
VM$ exit
logout
Connection to 104.155.206.70 closed.
$ gcloud compute ssh frontend-slave --zone asia-east1-b
...
Last login: Sat Jan 24 14:31:53 2015 from 1.2.1.1
VM$ sudo service apache2 stop
[ ok ] Stopping web server: apache2 ... waiting .
VM$ exit
logout
Connection to 130.211.244.80 closed.
$ while true; do curl -m1 107.178.245.89; done
frontend-us2
frontend-us2
frontend-us1
This experiment shows that the HTTP load balancer is transparently detecting backend failure and automatically routing traffic to the next-nearest node. When the nodes return to service, the routing will automatically reset. Using the HTTP load balancer, IT operations can be assured that customers always reach a good node.
A variation of the HTTP load-balancing setup is content-based load balancing. In this architecture, incoming traffic is distributed to various backend services based on predefined patterns in the request URLs. This is a very useful feature that can be used to select appropriate backend services to serve different type of data such as images, video, and text.
You can obtain this desirable behavior by making a minor modification to the HTTP load-balancing setup discussed in this section. You make the change in the step where you define a URL map. In addition to defining the default map, you also need to define more specific maps that route traffic to those URLs to a different backend. Let us look at an example:
# Example URL map
hostRules:
- hosts: ["*"]
pathMatcher: pathmap
pathMatchers:
- name: pathmap
defaultService:
https://www.googleapis.com/compute/v1/projects/PROJECT_ID/global/backendServices/www-service
pathRules:
- paths: ["/video", "/video/*"]
service:
https://www.googleapis.com/compute/v1/projects/PROJECT_ID/global/backendServices/video-service
- paths: ["/static", "/static/*"]
service:
https://www.googleapis.com/compute/v1/projects/PROJECT_ID/global/backendServices/static-service
In this example, requests to URLs /video/* are sent to a backend service called video-service, and requests to /static/* are sent to a backend service called static-service. All other requests are sent to a backend service called www-service.