In HowTo: Install Netflix Prana we looked at how to install Netflix Prana. In this article we look at making use of Netflix Prana.

Ping

We can check that Prana is running by connecting to http://127.0.0.1:8078/ping

Console - user@hostname ~ $

1
curl -v "http://127.0.0.1:8078/ping"

Output

1
2
3
4
5
6
7
8
9
10
11
12
13
14
* Hostname was NOT found in DNS cache
*   Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 8078 (#0)
> GET /ping HTTP/1.1
> User-Agent: curl/7.39.0
> Host: 127.0.0.1:8078
> Accept: */*
>
< HTTP/1.1 200 OK
< Cache-Control: must-revalidate,no-cache,no-store
< Transfer-Encoding: chunked
<
* Connection #0 to host 127.0.0.1 left intact
pong

Proxy

For making a call to one of applications, proxying through Prana, we would go to http://127.0.0.1:8078/proxy and set the parameter vip for the VIP of the application (eureka.vipAddress in the application’s configuration file), and path which will be the path on the VIP that is being proxied.

Prana Apache

To continue with our Prana Apache example, we’ll access the VIP prana-apache.example.com and the path /index.html.

Console - user@hostname ~ $

1
curl -v "http://127.0.0.1:8078/proxy?vip=prana-apache.example.com&path=/index.html"

Output

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
* Hostname was NOT found in DNS cache
*   Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 8078 (#0)
> GET /proxy?vip=prana-apache.example.com&path=/index.html HTTP/1.1
> User-Agent: curl/7.39.0
> Host: 127.0.0.1:8078
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Fri, 14 Nov 2014 05:24:32 GMT
< Server: Apache
< Last-Modified: Wed, 12 Nov 2014 06:43:12 GMT
< ETag: "9b6a-2d-507a3b5a59732"
< Accept-Ranges: bytes
< Content-Length: 45
< Content-Type: text/html
<
<html><body><h1>It works!</h1></body></html>
* Connection #0 to host 127.0.0.1 left intact

If we wanted to put a query string on the proxied path, we need to URL encode at least the query string part. We’ll repeat the previous request, but have the path be /index.html?a=b&c=d.

Console - user@hostname ~ $

1
curl -v "http://127.0.0.1:8078/proxy?vip=prana-apache.example.com&path=/index.html%3Fa%3Db%26c%3Dd"

Output

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
*   Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 8078 (#0)
> GET /proxy?vip=prana-apache.example.com&path=/index.html%3Fa%3Db%26c%3Dd HTTP/1.1
> Host: 127.0.0.1:8078
> User-Agent: curl/7.43.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Thu, 07 Jan 2016 23:31:31 GMT
< Server: Apache
< Last-Modified: Wed, 12 Nov 2014 06:43:12 GMT
< ETag: "9b6a-2d-507a3b5a59732"
< Accept-Ranges: bytes
< Content-Length: 45
< Content-Type: text/html
<
<html><body><h1>It works!</h1></body></html>
* Connection #0 to host 127.0.0.1 left intact

Eureka

Since the Eureka servers are themselves applications, we can make a call to them.

VIP

In this example we’ll lookup by VIP (eureka.vipAddress in the configuration file). We’ll access the VIP eureka.example.com with the path /eureka/v2/vips/prana-apache.example.com.

Console - user@hostname ~ $

1
2
3
curl -v "http://127.0.0.1:8078/proxy?vip=eureka.example.com&path=/eureka/v2/vips/prana-apache.example.com" \
-X GET \
--header "Accept: application/json" | zcat

Output

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Note: Unnecessary use of -X or --request, GET is already inferred.
*   Trying 127.0.0.1...
* TCP_NODELAY set
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0* Connected to 127.0.0.1 (127.0.0.1) port 8078 (#0)
> GET /proxy?vip=eureka.example.com&path=/eureka/v2/vips/prana-apache.example.com HTTP/1.1
> Host: 127.0.0.1:8078
> User-Agent: curl/7.53.0
> Accept: application/json
>
< HTTP/1.1 200 OK
< Date: Sun, 12 Mar 2017 18:48:02 GMT
< Vary: Accept-Encoding
< Content-Encoding: gzip
< Content-Type: application/json
< Connection: close
< Transfer-Encoding: chunked
< Transfer-Encoding: chunked
<
{ [685 bytes data]
100   668    0   668    0     0   2002      0 --:--:-- --:--:-- --:--:--  2006
* Closing connection 0
{"applications":{"versions__delta":"-1","apps__hashcode":"UP_1_","application":[{"name":"PRANA-APACHE","instance":[{"hostName":"ec2-54-147-214-155.compute-1.amazonaws.com","app":"PRANA-APACHE","ipAddr":"172.30.0.189","status":"UP","overriddenstatus":"UNKNOWN","port":{"$":80,"@enabled":"true"},"securePort":{"$":443,"@enabled":"false"},"countryId":1,"dataCenterInfo":{"@class":"com.netflix.appinfo.AmazonInfo","name":"Amazon","metadata":{"public-ipv4":"54.147.214.155","public-hostname":"ec2-54-147-214-155.compute-1.amazonaws.com","instance-id":"i-0ff758289b286ffac","local-ipv4":"172.30.0.189","instance-type":"c4.large","ami-id":"ami-52872744","availability-zone":"us-east-1a"}},"leaseInfo":{"renewalIntervalInSecs":30,"durationInSecs":90,"registrationTimestamp":1489344377832,"lastRenewalTimestamp":1489344557858,"evictionTimestamp":0,"serviceUpTimestamp":1489344357827},"metadata":{"@class":"java.util.Collections$EmptyMap"},"appGroupName":"UNKNOWN","homePageUrl":"http://ec2-54-147-214-155.compute-1.amazonaws.com:80/","statusPageUrl":"http://ec2-54-147-214-155.compute-1.amazonaws.com:80/Status","healthCheckUrl":"http://ec2-54-147-214-155.compute-1.amazonaws.com:80/healthcheck","vipAddress":"prana-apache.example.com","isCoordinatingDiscoveryServer":"false","lastUpdatedTimestamp":"1489344377832","lastDirtyTimestamp":"1489344357323","actionType":"ADDED"}]}]}}

It’s a bit difficult to read the JSON like that, so here it is in a prettier format:

Console - user@hostname ~ $

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
{
  "applications": {
    "versions__delta": "-1",
    "apps__hashcode": "UP_1_",
    "application": [
      {
        "name": "PRANA-APACHE",
        "instance": [
          {
            "hostName": "ec2-54-147-214-155.compute-1.amazonaws.com",
            "app": "PRANA-APACHE",
            "ipAddr": "172.30.0.189",
            "status": "UP",
            "overriddenstatus": "UNKNOWN",
            "port": {
              "$": 80,
              "@enabled": "true"
            },
            "securePort": {
              "$": 443,
              "@enabled": "false"
            },
            "countryId": 1,
            "dataCenterInfo": {
              "@class": "com.netflix.appinfo.AmazonInfo",
              "name": "Amazon",
              "metadata": {
                "public-ipv4": "54.147.214.155",
                "public-hostname": "ec2-54-147-214-155.compute-1.amazonaws.com",
                "instance-id": "i-0ff758289b286ffac",
                "local-ipv4": "172.30.0.189",
                "instance-type": "c4.large",
                "ami-id":"ami-52872744",
                "availability-zone":"us-east-1a"
              }
            },
            "leaseInfo": {
              "renewalIntervalInSecs": 30,
              "durationInSecs": 90,
              "registrationTimestamp": 1489344377832,
              "lastRenewalTimestamp": 1489344557858,
              "evictionTimestamp": 0,
              "serviceUpTimestamp": 1489344357827
            },
            "metadata": {
              "@class": "java.util.Collections$EmptyMap"
            },
            "appGroupName": "UNKNOWN",
            "homePageUrl": "http://ec2-54-147-214-155.compute-1.amazonaws.com:80/",
            "statusPageUrl": "http://ec2-54-147-214-155.compute-1.amazonaws.com:80/Status",
            "healthCheckUrl": "http://ec2-54-147-214-155.compute-1.amazonaws.com:80/healthcheck",
            "vipAddress": "prana-apache.example.com",
            "isCoordinatingDiscoveryServer": "false",
            "lastUpdatedTimestamp": "1489344377832",
            "lastDirtyTimestamp": "1489344357323",
            "actionType": "ADDED"
          }
        ]
      }
    ]
  }
}

App Name

We can instead query by app name instead (eureka.name in the configuration). Here we’ll query for instances running with the prana-apache app name by using the path /eureka/v2/apps/prana-apache.

Console - user@hostname ~ $

1
2
3
curl -v "http://127.0.0.1:8078/proxy?vip=eureka.example.com&path=/eureka/v2/apps/prana-apache" \
-X GET \
--header "Accept: application/json" | zcat

Output

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Note: Unnecessary use of -X or --request, GET is already inferred.
*   Trying 127.0.0.1...
* TCP_NODELAY set
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0* Connected to 127.0.0.1 (127.0.0.1) port 8078 (#0)
> GET /proxy?vip=eureka.example.com&path=/eureka/v2/apps/prana-apache HTTP/1.1
> Host: 127.0.0.1:8078
> User-Agent: curl/7.53.0
> Accept: application/json
>
< HTTP/1.1 200 OK
< Date: Sun, 12 Mar 2017 19:03:43 GMT
< Vary: Accept-Encoding
< Content-Encoding: gzip
< Content-Type: application/json
< Connection: close
< Transfer-Encoding: chunked
< Transfer-Encoding: chunked
<
{ [654 bytes data]
100   637    0   637    0     0  58499      0 --:--:-- --:--:-- --:--:-- 63700
* Closing connection 0
{"application":{"name":"PRANA-APACHE","instance":[{"hostName":"ec2-54-147-214-155.compute-1.amazonaws.com","app":"PRANA-APACHE","ipAddr":"172.30.0.189","status":"UP","overriddenstatus":"UNKNOWN","port":{"$":80,"@enabled":"true"},"securePort":{"$":443,"@enabled":"false"},"countryId":1,"dataCenterInfo":{"@class":"com.netflix.appinfo.AmazonInfo","name":"Amazon","metadata":{"public-ipv4":"54.147.214.155","public-hostname":"ec2-54-147-214-155.compute-1.amazonaws.com","instance-id":"i-0ff758289b286ffac","local-ipv4":"172.30.0.189","instance-type":"c4.large","ami-id":"ami-52872744","availability-zone":"us-east-1a"}},"leaseInfo":{"renewalIntervalInSecs":30,"durationInSecs":90,"registrationTimestamp":1489344377832,"lastRenewalTimestamp":1489345488167,"evictionTimestamp":0,"serviceUpTimestamp":1489344357827},"metadata":{"@class":"java.util.Collections$EmptyMap"},"appGroupName":"UNKNOWN","homePageUrl":"http://ec2-54-147-214-155.compute-1.amazonaws.com:80/","statusPageUrl":"http://ec2-54-147-214-155.compute-1.amazonaws.com:80/Status","healthCheckUrl":"http://ec2-54-147-214-155.compute-1.amazonaws.com:80/healthcheck","vipAddress":"prana-apache.example.com","isCoordinatingDiscoveryServer":"false","lastUpdatedTimestamp":"1489344377832","lastDirtyTimestamp":"1489344357323","actionType":"ADDED"}]}}

And here is the prettier version of the output:

Console - user@hostname ~ $

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
{
  "application": {
    "name": "PRANA-APACHE",
    "instance": [
      {
        "hostName": "ec2-54-147-214-155.compute-1.amazonaws.com",
        "app": "PRANA-APACHE",
        "ipAddr": "172.30.0.189",
        "status": "UP",
        "overriddenstatus": "UNKNOWN",
        "port": {
          "$": 80,
          "@enabled": "true"
        },
        "securePort": {
          "$": 443,
          "@enabled": "false"
        },
        "countryId": 1,
        "dataCenterInfo": {
          "@class": "com.netflix.appinfo.AmazonInfo",
          "name": "Amazon",
          "metadata": {
            "public-ipv4": "54.147.214.155",
            "public-hostname": "ec2-54-147-214-155.compute-1.amazonaws.com",
            "instance-id": "i-0ff758289b286ffac",
            "local-ipv4": "172.30.0.189",
            "instance-type": "c4.large",
            "ami-id": "ami-52872744",
            "availability-zone": "us-east-1a"
          }
        },
        "leaseInfo": {
          "renewalIntervalInSecs": 30,
          "durationInSecs": 90,
          "registrationTimestamp": 1489344377832,
          "lastRenewalTimestamp": 1489345488167,
          "evictionTimestamp": 0,
          "serviceUpTimestamp": 1489344357827
        },
        "metadata": {
          "@class":"java.util.Collections$EmptyMap"
        },
        "appGroupName": "UNKNOWN",
        "homePageUrl": "http://ec2-54-147-214-155.compute-1.amazonaws.com:80/",
        "statusPageUrl": "http://ec2-54-147-214-155.compute-1.amazonaws.com:80/Status",
        "healthCheckUrl": "http://ec2-54-147-214-155.compute-1.amazonaws.com:80/healthcheck",
        "vipAddress": "prana-apache.example.com",
        "isCoordinatingDiscoveryServer": "false",
        "lastUpdatedTimestamp": "1489344377832",
        "lastDirtyTimestamp": "1489344357323",
        "actionType":"ADDED"
      }
    ]
  }
}

Eureka Hosts

If instead of proxying the request, we just want to know what hosts are running a given application, we can look that up at http://127.0.0.1:8078/eureka/hosts and set the parameter appName to the application name (eureka.name in the application’s configuration file).

Prana Apache

Console - user@hostname ~ $

1
curl -v "http://127.0.0.1:8078/eureka/hosts?appName=prana-apache"

Output

1
2
3
4
5
6
7
8
9
10
11
12
13
14
* Hostname was NOT found in DNS cache
*   Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 8078 (#0)
> GET /eureka/hosts?appName=prana-apache HTTP/1.1
> User-Agent: curl/7.39.0
> Host: 127.0.0.1:8078
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-type: application/json
< Transfer-Encoding: chunked
<
* Connection #0 to host 127.0.0.1 left intact
["ec2-54-165-210-142.compute-1.amazonaws.com"]

Eureka

Console - user@hostname ~ $

1
curl -v "http://127.0.0.1:8078/eureka/hosts?appName=eureka"

Output

1
2
3
4
5
6
7
8
9
10
11
12
13
14
* Hostname was NOT found in DNS cache
*   Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 8078 (#0)
> GET /eureka/hosts?appName=eureka HTTP/1.1
> User-Agent: curl/7.39.0
> Host: 127.0.0.1:8078
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: application/json
< Transfer-Encoding: chunked
<
* Connection #0 to host 127.0.0.1 left intact
["ec2-54-173-165-241.compute-1.amazonaws.com","ec2-54-164-65-221.compute-1.amazonaws.com","ec2-54-173-91-84.compute-1.amazonaws.com"]

Health Check

If using Prana to register a non-JVM based service with Eureka, you can run the health check manually at http://127.0.0.1:8078/healthcheck.

Console - user@hostname ~ $

1
curl -v "http://127.0.0.1:8078/healthcheck"

Output

1
2
3
4
5
6
7
8
9
10
11
12
13
14
* Hostname was NOT found in DNS cache
*   Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 8078 (#0)
> GET /healthcheck HTTP/1.1
> User-Agent: curl/7.39.0
> Host: 127.0.0.1:8078
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: application/xml
< Transfer-Encoding: chunked
<
* Connection #0 to host 127.0.0.1 left intact
<health>ok</health>

Status

If using Prana to register a non-JVM based service with Eureka, you can check it’s discovery status at http://127.0.0.1:8078/status.

Console - user@hostname ~ $

1
curl -v "http://127.0.0.1:8078/status"

Output

1
2
3
4
5
6
7
8
9
10
11
12
13
14
* Hostname was NOT found in DNS cache
*   Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 8078 (#0)
> GET /status HTTP/1.1
> User-Agent: curl/7.39.0
> Host: 127.0.0.1:8078
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-type: application/json
< Transfer-Encoding: chunked
<
* Connection #0 to host 127.0.0.1 left intact
{"status":"STARTING"}

Dynamic Properties

In addition to interfacing with Eureka and proxying calls to applications, Prana can also fetch dynamic properties using Netflix Archaius. While we will not be going into specifics of the full extent of places Archaius can load properties from, it can load from configuration files, system properties, environment variables, URLs, JDBC, Amazon DynamoDB, and others; see GitHub - Netflix/archaius for more details.

For this example, we’ll look at the following properties:

  • JAVA_HOME
  • _system_arch
  • archaius.deployment.applicationId

We go to http://127.0.0.1:8078/dynamicproperties and set the parameter id for each property we want to look up.

Console - user@hostname ~ $

1
curl -v "http://127.0.0.1:8078/dynamicproperties?id=JAVA_HOME&id=_system_arch&id=archaius.deployment.applicationId"

Output

1
2
3
4
5
6
7
8
9
10
11
12
13
14
* Hostname was NOT found in DNS cache
*   Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 8078 (#0)
> GET /dynamicproperties?id=JAVA_HOME&id=_system_arch&id=archaius.deployment.applicationId HTTP/1.1
> User-Agent: curl/7.39.0
> Host: 127.0.0.1:8078
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: application/json
< Transfer-Encoding: chunked
<
* Connection #0 to host 127.0.0.1 left intact
{"JAVA_HOME":"/etc/java-config-2/current-system-vm","_system_arch":"x86_64","archaius.deployment.applicationId":"prana"}

References

Parts in this series