Search This Blog

Thursday, 18 January 2018

Pivotal Cloud Foundry App Instance Routing in HTTP Headers

Developers who want to obtain debug data for a specific instance of an app can use the HTTP header X-CF-APP-INSTANCE to make a request to an app instance. To demonstrate how we can write a Spring Boot application which simply outputs the current CF app index so we are sure we are hitting the right application container.

Simplest way to do that is to define a RestController using Spring Boot as follows which then enables us to get the current application index and verify we are hitting the right container instance.
  
package com.example.pas;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class DemoRest
{
    private final String ip;
    private final String index;

    @Autowired
    public DemoRest
            (@Value("${CF_INSTANCE_IP:127.0.0.1}") String ip, 
             @Value("${CF_INSTANCE_INDEX:0}") String index) {
        this.ip = ip;
        this.index = index;
    }

    @RequestMapping("/")
    public InstanceDetail getAppDetails()
    {
        InstanceDetail instanceDetail = new InstanceDetail(ip, index);

        return instanceDetail;
    }
}

So with the application deployed as see we have 3 instances as follows

pasapicella@pas-macbook:~$ cf app pas-pcf-routingdemo
Showing health and status for app pas-pcf-routingdemo in org pivot-papicella / space dotnet as papicella@pivotal.io...

name:                pas-pcf-routingdemo
requested state:     started
instances:           3/3
isolation segment:   main
usage:               756M x 3 instances
routes:              pas-pcf-routingdemo-incidental-curia.pcfbeta.io
last uploaded:       Thu 18 Jan 20:41:26 AEDT 2018
stack:               cflinuxfs2
buildpack:           client-certificate-mapper=1.4.0_RELEASE container-security-provider=1.11.0_RELEASE java-buildpack=v4.7.1-offline-https://github.com/cloudfoundry/java-buildpack.git#6a3361a
                     java-main java-opts java-security jvmkill-agent=1... (no decorators apply)

     state     since                  cpu    memory           disk           details
#0   running   2018-01-18T09:44:07Z   0.4%   224.8M of 756M   137.5M of 1G
#1   running   2018-01-18T09:44:13Z   0.8%   205M of 756M     137.5M of 1G
#2   running   2018-01-18T09:44:06Z   0.7%   221.1M of 756M   137.5M of 1G

Now lets simply access our application a few times using the "/" end point and verify we are accessing different application containers via round robin routing as per GoRouter

pasapicella@pas-macbook:~$ http https://pas-pcf-routingdemo-incidental-curia.pcfbeta.io/
HTTP/1.1 200 OK
Content-Length: 34
Content-Type: application/json;charset=UTF-8
Date: Thu, 18 Jan 2018 09:58:10 GMT
Set-Cookie: dtCookie=6$B570EBB532CD9D8DAA2BCAE14C4277FC|RUM+Default+Application|1; Domain=pcfbeta.io; Path=/
X-Vcap-Request-Id: 336ba633-685b-4235-467d-b9833a9e6435

{
    "index": "2",
    "ip": "192.168.16.34"
}

pasapicella@pas-macbook:~$ http https://pas-pcf-routingdemo-incidental-curia.pcfbeta.io/
HTTP/1.1 200 OK
Content-Length: 34
Content-Type: application/json;charset=UTF-8
Date: Thu, 18 Jan 2018 09:58:15 GMT
Set-Cookie: dtCookie=5$3389B3DFBAD936D68CBAF30657653465|RUM+Default+Application|1; Domain=pcfbeta.io; Path=/
X-Vcap-Request-Id: aa74e093-9031-4df5-73a5-bc9f1741a942

{
    "index": "1",
    "ip": "192.168.16.32"
}

Now we can request access to just the container with application index "1" as follows

1. First get the Application GUID as shown below

pasapicella@pas-macbook:~$ cf app pas-pcf-routingdemo --guid
5bdf2f08-34a5-402f-b7cb-f29c81d171e0

2. Now lets invoke a call to the application and set the HEADER required to instruct GoRouter to target a specific application index

eg: curl app.example.com -H "X-CF-APP-INSTANCE":"YOUR-APP-GUID:YOUR-INSTANCE-INDEX"

Example below is using HTTPie 

Accessing Instance 1

pasapicella@pas-macbook:~$ http https://pas-pcf-routingdemo-incidental-curia.pcfbeta.io/ "X-CF-APP-INSTANCE":"5bdf2f08-34a5-402f-b7cb-f29c81d171e0:1"
HTTP/1.1 200 OK
Content-Length: 34
Content-Type: application/json;charset=UTF-8
Date: Thu, 18 Jan 2018 10:20:31 GMT
Set-Cookie: dtCookie=5$FD08A5C88469AF379C8AD3F36FA7984B|RUM+Default+Application|1; Domain=pcfbeta.io; Path=/
X-Vcap-Request-Id: cb19b960-713a-49d0-4529-a0766a8880a7

{
    "index": "1",
    "ip": "192.168.16.32"
}

Accessing Instance 2 

pasapicella@pas-macbook:~$ http https://pas-pcf-routingdemo-incidental-curia.pcfbeta.io/ "X-CF-APP-INSTANCE":"5bdf2f08-34a5-402f-b7cb-f29c81d171e0:2"
HTTP/1.1 200 OK
Content-Length: 34
Content-Type: application/json;charset=UTF-8
Date: Thu, 18 Jan 2018 10:21:09 GMT
Set-Cookie: dtCookie=7$53957A744D473BB024EB1FF4F0CD60A9|RUM+Default+Application|1; Domain=pcfbeta.io; Path=/
X-Vcap-Request-Id: 33cc7922-9b43-4182-5c36-13eee42a9919

{
    "index": "2",
    "ip": "192.168.16.34"
}

More Information

https://docs.cloudfoundry.org/concepts/http-routing.html#http-headers