{"id":346,"date":"2013-01-29T04:09:46","date_gmt":"2013-01-29T04:09:46","guid":{"rendered":"http:\/\/corneliadavis.com\/blog\/?p=346"},"modified":"2013-01-29T04:09:46","modified_gmt":"2013-01-29T04:09:46","slug":"the-anatomy-of-a-cloud-foundry-system-service-implementation","status":"publish","type":"post","link":"https:\/\/corneliadavis.com\/blog\/2013\/01\/29\/the-anatomy-of-a-cloud-foundry-system-service-implementation\/","title":{"rendered":"The Anatomy of a Cloud Foundry System Service Implementation"},"content":{"rendered":"<p>In the <a href=\"http:\/\/corneliadavis.com\/blog\/2013\/01\/04\/learning-how-to-add-services-to-cloud-foundry\/\">first post<\/a> of this three part series, I went through the steps we took to deploy the sample Echo service to a non-BOSH-based, single node cloud foundry instance, and in the last part we\u2019ll do the deployment into a BOSH-based cloud foundry. In this post I want to spend just a bit of time explaining the parts of the Echo service itself.<\/p>\n<p>A cloud foundry service implementation consists of three main components:<\/p>\n<ul>\n<li>The service itself: This is the actual running service, for example, for Postgres this is a set of processes that implement the running database.<\/li>\n<li>The service node: This is the code that provisions and deprovisions (and a few other things) cloud foundry service instances.  In the case of Postgres, when a service instance is created, the code in the service node will make calls to the Postgres server itself, creating a new database, user and password.  Attributes, such as the server address and the new database name, user and password will ultimately be passed back to an application that is binding to the service.<\/li>\n<li>The service gateway: This is part of the mechanism for that \u201cultimately\u201d \u2013 this code presents a RESTful service for creating and deleting service instances and gets those requests to the service node for fulfillment.  When the node responds with values, the gateway returns them to the original requestor.<\/li>\n<\/ul>\n<p>While my intent with this post is to mainly explain the Echo Service components, not to provide a general tutorial on creating cloud foundry services, there are a few general tidbits I do want to share right away.<\/p>\n<ul>\n<li>For the service itself, you are likely not writing any code here, rather, you are probably taking some piece of software and deploying it (how depends on whether you are going into a BOSH-based deployment (part III) or not (<a href=\"http:\/\/corneliadavis.com\/blog\/2013\/01\/04\/learning-how-to-add-services-to-cloud-foundry\/\">part I<\/a>)).\u00a0 For example, we\u2019re working on creating a Cassandra cloud foundry service, so the Cassandra implementation is just downloaded from <a href=\"http:\/\/cassandra.apache.org\/download\/\">here<\/a>.<\/li>\n<li>For the gateway, you have very, very little code to write.\u00a0 The code you do write is in Ruby and leverages a <a href=\"https:\/\/github.com\/cloudfoundry\/vcap-services-base\">bunch of cloud foundry code<\/a>.\u00a0 The gateway just extends these cloud foundry provided classes setting two things:\n<ul>\n<li>The service_name (this is actually set in a provisioner class that is then included in the gateway class) which is also set in the node implementation (via common base class included in both) and is used for communication between the node and gateway (messaging over NATS).<\/li>\n<li>The name of the config file.<\/li>\n<\/ul>\n<\/li>\n<li>Most of your work will be in the node implementation.\u00a0 This is written in Ruby and leverages a <a href=\"https:\/\/github.com\/cloudfoundry\/vcap-services-base\">bunch of cloud foundry code<\/a>. Your task here is to communicate with the server itself to do whatever needs to be done on provision and deprovision requests.\n<ul>\n<li>When you go into a multi-node cloud foundry deployment, your service node code will typically execute on the same VM as the actual service \u2013if there are multiple service VMs, there will be multiple node processes running (one on each vm).\u00a0 You\u2019ll probably have one or two gateways \u2013 running on VMs separate from the node\/service VMs. Think of the service gateway as a router of sorts to the set of nodes actually providing a service &#8211; one thing, the gateway is only called into action on provisioning and deprovisioning requests, not when an application is communicating with the service.<\/li>\n<li>The gateway and node communicate via messaging (NATS) embedded in cloud foundry.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>There is a lot more to say about this, but that\u2019s a topic for another post.\u00a0 In the mean time, I encourage you to study not only the Echo Service, but do look at a more real implementation such as Postgres.<\/p>\n<p>So, back to Echo.\u00a0 The original instructions are a bit confusing as they first deal with deployment of the node and gateway, getting them running, even before there is a service for the node to speak to.\u00a0 I\u2019d probably address the actual service first before worrying about connecting to it with the gateway\/node \u2013 just sayin. In fact, let me start there.<\/p>\n<h1>The Echo Cloud Foundry Service<\/h1>\n<h2>The Echo Server<\/h2>\n<p>The service itself is found as an attachment in the original article \u2013 the echo_service.jar <a href=\"http:\/\/support.cloudfoundry.com\/attachments\/token\/sc3oau0qojdqv9l\/?name=echo_service.jar\">attachment<\/a> \u2013 and it is super simple.\u00a0 It is a java program \u2013 you can find the source in the echo_src.zip <a href=\"http:\/\/support.cloudfoundry.com\/attachments\/token\/ezj4tqkfpelunfo\/?name=echo_src.zip\">attachment<\/a> of the original article \u2013 and it\u2019s a single java class.\u00a0 When you run this service it simply listens on a particular port and when something shows up on that port, it just takes that string and sends it back, over the same socket.\u00a0 The code as you originally find it will listen at the ip address 127.0.0.1 on the port passed in when you run the jar.\u00a0 The following line of code is the one that gets that localhost IP address in the method call on InetAddress:<\/p>\n<pre><code>serverSocket = new ServerSocket(port, 0, InetAddress.getLocalHost());<\/code><\/pre>\n<p>This didn\u2019t work for me. My client app (which I talk about in the last section of this post) was sending out messages on the actual IP address of the box, not 127.0.0.1, so the echo server never saw them.\u00a0 To solve this, a colleague of mine and I modified the echo server to take in, on the command line, the server ip address as well as the port.\u00a0 <a href=\"https:\/\/github.com\/cdavisafc\/cloudfoundry-misc\/tree\/master\/EchoServer\">Here<\/a> you\u2019ll find both the new jar file and the source.\u00a0 If you use this new Echo Server implementation instead of the original, when you start up the server make sure you include the ipaddress and port as follows:<\/p>\n<pre><code>java \u2013jar EchoServer-0.1.0.jar \u2013ipaddress 192.168.1.111 \u2013port 5002<\/code><\/pre>\n<p>We\u2019ll come back to this in part III when the startup of the echo server is automated.<\/p>\n<h2>The echo_node implementation<\/h2>\n<p>The echo_node implementation has the job of servicing provisioning and deprovisioning requests.\u00a0 In a \u201creal\u201d service this would likely involve communicating with the Server to change its state (i.e. create a new database) and\/or retrieve some values (username and password for the database), and then this information would be returned to the requesting party.\u00a0 For Echo it\u2019s much simpler.\u00a0 There is nothing to create within the server and the echo server doesn\u2019t expose any type of interface for asking about its state \u2013 it might, for example, have offered an API that returns the ip address and port for the socket it is listening on \u2013 but it doesn\u2019t.\u00a0 So the echo_node implementation does not communicate with the echo server at all and instead simply returns values to the requesting party.\u00a0 Where does it get these values?\u00a0 Mostly from the echo_node configuration file.\u00a0 In <a href=\"http:\/\/corneliadavis.com\/blog\/2013\/01\/04\/learning-how-to-add-services-to-cloud-foundry\/\">part I<\/a>, roughly following <a href=\"http:\/\/support.cloudfoundry.com\/entries\/20485171-how-to-add-a-system-service-to-oss-cloud-foundry-step-by-step-guide\">these instructions<\/a>, the echo_node.yml includes the following two lines:<\/p>\n<pre><code>port: 5002\nhost: 192.168.1.111<\/code><\/pre>\n<p>The host property is no longer required \u2013 cloud foundry automatically includes the host and name properties in the values returned from the services node.\u00a0\u00a0 That said, you need to make sure the ip address you provide when running the echo server is, in fact, the ip address of the machine the echo_node is running on because that is the ip address that will eventually be passed to the client application.\u00a0 And if this all seems a bit confusing, don\u2019t worry, it will get far better when we deploy with BOSH \u2013 yep, part III.<\/p>\n<h2>The echo_gateway implementation<\/h2>\n<p>If I were to stay only with talking about the echo gateway here there wouldn\u2019t be much to say.\u00a0 Most service gateways are pretty much the same.\u00a0 They present an HTTP (RESTful?) service for provisioning, deprovisioning, binding and a few other operations, they dispatch messages to NATS and wait for the service node to do its work and respond.\u00a0 The response is then made available to the requestor.\u00a0 As I said before, all that code is pretty much included in cloud foundry \u2013 you just have to do what I described earlier in this post. But let me give a very brief overview of what all of that lovely, provided-for-you code is doing.<\/p>\n<ol>\n<li>It presents an HTTP (RESTful?) service.<\/li>\n<li>It sets up a listener on NATS for responses it expects to get from the service node.<\/li>\n<li>It processes the request and dispatches the appropriate message to NATS (in step 2 we set up the mechanism for receiving a response).<\/li>\n<li>And when it gets that response, it in turn responds to the HTTP request that started the whole thing off.<\/li>\n<\/ol>\n<p>There is a good bit of code in there that does things like handling the getting back of multiple values for a particular key and converts them into an array, and other goodies like that.<\/p>\n<p>So, who is the recipient of the gateway response?\u00a0 Well, ultimately it is the client application, and that is what I will talk about next.<\/p>\n<h1>The Echo Client<\/h1>\n<p>The echo client is also quite simple.\u00a0 It\u2019s a plain-old java web application \u2013 not spring.\u00a0 Cloud foundry knows how to reconfigure certain types of applications by looking at the artifacts for that application type, like spring config files, finding common patterns, like the use of the <a href=\"http:\/\/docs.oracle.com\/javase\/6\/docs\/api\/javax\/sql\/DataSource.html\">javax.sql.DataSource<\/a> interface for database connectivity, and setting values, like database server ip addresses, in there. It\u2019s the cloud foundry stager that does this. But for a plain old java web app, the set of things that cloud foundry knows how to configure is limited to some basic things in the web.xml; beyond that, it has no idea how that app is configured. Does the app look for a property file? Or does it look things up in environmental variables? Dunno.\u00a0 So in this case the dea, <span style=\"text-decoration: underline;\">who has the values that came back from the service gateway<\/span>, just writes them into environmental variables\u00a0.\u00a0 In fact, the dea always writes these values into environmental variables regardless of whether the stager does anything extra with any of those values.<\/p>\n<p>And that is how the echo client is consuming them.\u00a0 If you have a look in the <a href=\"http:\/\/support.cloudfoundry.com\/attachments\/token\/a2zivrnqdixxrg3\/?name=testapp_src.zip\">source for the echo client<\/a>, you\u2019ll see the following in the index.jsp:<\/p>\n<pre><code>String services_json = System.getenv(\"VCAP_SERVICES\");<\/code><\/pre>\n<p>The services_json is then parsed to find the credentials object which in turn contains the host and port.<\/p>\n<p>Summarizing, the echo_node obtained the host and port from its config file, which until part III you are responsible for keeping in synch with the arguments you provide when you run the echo server.\u00a0 Through the echo_gateway, the dea took those values and wrote them to environmental variables, the client picked them up from there and configured itself to send messages over the socket at that ip address and port.<\/p>\n<p><strong><span style=\"text-decoration: underline;\">One point to emphasize<\/span><\/strong>: once the service instance is bound to the application, the node and gateway are out of the picture \u2013 at that point the app communicates directly with the echo server.<\/p>\n<p>Got it? \ud83d\ude42<\/p>\n<p>It takes a bit of study but in the end it all makes sense.<\/p>\n<p>Have I mentioned that I love this stuff?<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the first post of this three part series, I went through the steps we took to deploy the sample Echo service to a non-BOSH-based, single node cloud foundry instance, and in the last part we\u2019ll do the deployment into a BOSH-based cloud foundry. In this post I want to spend just a bit of [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"nf_dc_page":"","_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[5,13,21],"tags":[53],"class_list":["post-346","post","type-post","status-publish","format-standard","hentry","category-cloud","category-howto","category-paas","tag-cloudfoundry"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/corneliadavis.com\/blog\/wp-json\/wp\/v2\/posts\/346","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/corneliadavis.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/corneliadavis.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/corneliadavis.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/corneliadavis.com\/blog\/wp-json\/wp\/v2\/comments?post=346"}],"version-history":[{"count":0,"href":"https:\/\/corneliadavis.com\/blog\/wp-json\/wp\/v2\/posts\/346\/revisions"}],"wp:attachment":[{"href":"https:\/\/corneliadavis.com\/blog\/wp-json\/wp\/v2\/media?parent=346"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/corneliadavis.com\/blog\/wp-json\/wp\/v2\/categories?post=346"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/corneliadavis.com\/blog\/wp-json\/wp\/v2\/tags?post=346"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}