Using the IBM Pattern Development Kit to build virtual application patterns, Part 3: Build Memcached as a shared service

Virtual application patterns in IBM® PureApplication System™ provide easy and powerful capabilities to construct Platform as a Service Pattern. Part 3 of this series describes how to create Memcached as a shared service to support the Tomcat auto failover capability. With this shared service, Tomcat can construct clusters with a session auto failover.

Share:

Qi Liu (lqliulq@cn.ibm.com), Software Engineer, IBM

Photo of Qi LiuQi (Colin) Liu is a Software Engineer leading the IBM Pattern Development Kit (PDK) development from Version 1.0.1.0. Previously, he worked as a key developer on the Composite Application Pattern (CAP) project and the lead for BPM Process Server plug-in development.



Scott Walden (sw@us.ibm.com), Software Engineer, IBM

Photo of Scott WaldenScott Walden works on the enablement team for IBM PureApplication System. The team charter includes customer enablement and internal enablement for various teams. Previously, he was the technical lead for IBM Business Monitor on the AIM Early Programs team that managed early design programs, beta programs, customer acceleration programs, and skills transfers.


developerWorks Contributing author
        level

Qiang Wang (wqwqbj@cn.ibm.com), Software Engineer, IBM

Photo of Qiang WangQiang (Ace) Wang is a Staff Software Engineer in the PureApplication Pattern Enablement and Pattern Development Kit team in IBM Software Group. He has participated in many industry solutions, which include digital media, banking, healthcare, and so on. Currently, he is working in the cloud computing area.



Wei Feng Li (lwfli@cn.ibm.com), Software Engineer, IBM

Photo of Wei Feng LiWei Feng (Banny) Li is a key developer of the PureApplication System Pattern Development Kit. He has rich experience in pattern development and is now mainly responsible for the PDK Eclipse user interface part. He is a key contributor in such projects as Application Delivery Pattern (ADP) and Composite Application Pattern (CAP). He also participates in Digital Media Management (DMM) and Knowledge Driver Application (KDA) accelerators development.



04 December 2013

Also available in Japanese

Introduction

Part 3 of this series introduces Memcached and shared services in virtual application patterns. The article also explains the reason for creating Memcached as a shared service.


What is Memcached?

Memcached is a free and open source, high-performance, distributed memory object caching system, which is generic in nature, but it is intended for use in speeding up dynamic web applications by alleviating database load. It is an in-memory key-value store for small chunks of arbitrary data (strings, objects) from the results of database calls, API calls, or page rendering. Memcached is simple, yet powerful. Its simple design promotes quick deployment, ease of deployment, and solves many problems facing large data caches. Its API is available for most popular languages.


What is a shared service?

Shared services provide a predefined virtual application pattern that is deployed and shared by multiple application deployments in the cloud, including virtual applications, virtual systems, and virtual appliances. A shared service provides certain runtime services to multiple applications or services to the user on behalf of multiple applications. Usually, only one single reference to the shared service exists per cloud group, which is a physical group of hardware that defines a cloud. That shared service can be used by all application deployments in the cloud group.

Why create Memcached as a shared service?

In order for auto failover to work seamlessly without users' noticing the redeployment of applications, sessions must be replicated between application servers. Without session replication, users will lose sessions that may result in getting logged out when the request is served by a different application server.

Tomcat has built-in facilities, including DeltaManager and BackupManager that enables session replication. However, in practice, both of these are complicated to configure. As an alternative, the Memcached session manager not only works great, but it is also easy to configure. It is suitable to set up Tomcat auto failover using Memcached and Memcached session manager on a multi-machine clustered environment.

Since a Memcached instance can provide session replication among multiple Tomcat instances in one cloud, it is suitable to create it as shared service. Memcached instances would be a session replication pool for multiple Tomcat clusters. Note that Memcached also can be created as a normal plug-in project, which is created in every deployment.


Configure Tomcat high availability with Memcached

Tomcat high availability requires constructing a Tomcat server cluster to avoid a single point of failure. Firstly, let's go through how to build a Tomcat server cluster manually.

Set up Tomcat instances

For auto failover to work, at least two Tomcat instances need to be set up. To enable an existing Tomcat server for Memcached, make a copy of JAR files to another Tomcat node machine. For each copy, download the following JARs and install them to the ${tomcat_dir}/lib directory:

  • memcached-session-manager-x.y.z.jar
  • memcached-session-manager-tc7-x.y.z.jar (for Tomcat 7)
  • Spymemcached-x.y.z.jar

The latest version of memcached-session-manager is 1.6.4 and spymemcached is 2.8.12, which are selected in these projects. After each copy, open ${tomcat_dir}/conf/context.xml, and add the following lines inside the <Context> tag as show in Listing 1.

Listing 1. locales/en/message.json file
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
    memcachedNodes="n1:${memcachedNodeHostName}:${memcachedNodePort}"
    requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$" />

Replace the memcachedNodeHostName and memcachedNodePort variables with the appropriate values of the Memcached server.

Install Memcached

Before installing Memcached, install libevent first. Then, after the Memcached installation is finished, start Memcached as shown in Listing 2.

Listing 2. Command to start Memcached
memcached -u virtuser -d -m 2048 -l ${memcachedNodeHostName} -p ${memcachedNodePort}

Test the auto failover

After performing the manual configuration as previously described, you are ready to test the failover in the cluster. Figure 1 shows the built-in developer tool within the Chrome® browser, which is used to check the cookies set.

Figure 1. Resource in the Chrome developer's tools
Resource in the Chrome developer's tools
  1. Deploy any web applications that use sessions onto both Tomcat servers. Start the Tomcat servers, Apache, and Memcached.
  2. Access the existing web address of Apache in the browser.
  3. Check that the cookies are set. Take Chrome as an example, this can be done with the built-in Developer Tools. As Figure 1 shows, JSESSIONID value reveals the current Tomcat instance for the session. Then shut down this Tomcat server.
  4. Refresh the web console. The cookie value should indicate that the other Tomcat instance is taking over.
  5. Check if the session values set by the application remain. For example, if the application deployed allows a user to log in, the user should still be able to remain logged in after auto failover.

In conclusion, together with Memcached and HTTPD, it is possible to perform round-robin deployments of web applications on Tomcat with zero downtime. This capability allows you to achieve continuous delivery and to frequently push out new features. Based on the previous manual configuration, the following sections will show you how to implement this as a shared service.


Create a PatternType project

A shared service is a predefined pattern that is deployed and shared by multiple client application deployments. This is a pattern, which requires creating a normal pattern type.

  1. From Eclipse, choose File > New > Other -> IBM Workload Plug-in Development > IBM Workload Pattern Type Project. Enter the project name as patterntype.sample.memchached as shown in Figure 2.
    Figure 2. Pattern Type project creation
    Pattern Type project creation
  2. Click the Finish button. The IBM Pattern Development Kit (PDK) creates a pattern type project, where the project structure looks like Figure 3.
    Figure 3. Pattern type project structure
    Pattern type project structure
  3. The patterntype.json file is the core file (Listing 3), which is used to describe the pattern type.
    Listing 3. patterntype.json file
    {
        "name": "patterntype.sample.memcached",
        "shortname": "patterntype.sample.memcached",
        "version": "1.0.0.0",
        "description": "",
        "status": ""
    }
  4. Later, when you add the pattern type to the deployer, the value of parameter of name shows up in the Pattern Types list of the IBM PureApplication System console, along with the version as shown in Figure 4.
    Figure 4. Pattern type in PureApplication System/Workload Deployer
    Pattern type in PureApplication System/Workload Deployer

The value of the shortname parameter will be referenced in the config.json file in the plug-in project.


Create plug-in projects

The development of a shared service is similar to plug-in development for virtual applications. For the patterntype.sample.memcached pattern type, there are two plug-in projects included with this article:

  • plugin.com.ibm.sample.memcached.base: This is a plug-in project, which is like any other plug-in project. It is used for basic Memcached installation, configuration and restful API implementation.
  • plugin.com.ibm.sample.memcached.shareservice: This is the shared service implementation plug-in project that includes extra metadata and capabilities, which make the pattern type a shared service.
  1. From Eclipse, choose File > New > Other > IBM Workload Plug-in Development > IBM Workload Plug-in Project, then enter the project name of plugin.com.ibm.sample.memcached.shareservice as shown Figure 5.
    Figure 5. Plug-in Project creation – input a project name
    Plug-in Project creation – input a project name
  2. Click the Next button and choose the existing pattern type in the current workspace as shown in Figure 6.
    Figure 6. Plug-in Project creation – select a pattern type
    Plug-in Project creation – select a pattern type
  3. Click Finish.

You can use a similar procedure to create the plugin.com.ibm.sample.memcached.base plug-in project.


Create a shared service implementation

The "appmodel.json" file (see Listing 4) represents the serialization of the model that is defined in the Virtual Application Builder user interface for a regular virtual application. Components (nodes) and links, along with user-specified property values, are represented. For shared services, the properties must be predefined. In addition to nodes, links and other attributes of an application model, additional attributes are required for a shared service.

Listing 4. Sample appmodel.json file
{
	"model": {
		"description": "share service for distributed memory object caching system",
		"app_type": "service",
		"patterntype": "patterntype.sample.memcached",
		"version": "1.0",
		"name":"Memcached Shared Service",
		"servicename":"memcached",
		"servicedisplayname":"Memcached Shared Service",
		"serviceversion":"1.0.0.0",
		"servicesupportedclients":"[0.0,3.0]",
		
		"nodes": [
			{
				"attributes": {
				},
				"id": "MemcachedId",
				"type": "Memcached"
			},
			{
				"id": "MemcachedPlaceholderId",
				"type": "MemcachedPlaceholder"
			}
		]
	}
}

Here is a brief description of the attributes shown in Listing 4.

  • app_type: This is set to "service".
  • serviceversion: This is a unique shared service application model version, for example, 1.0.0.0.
  • servicesupportedclients: This is a list of supported client versions that can use this shared service. Example patterns are:
    • *: matches all versions
    • [a,b]: matches all versions between a and b, including a and b
    • (a,b): matches all versions between a and b, excluding a and b
    • [*,b]: matches all versions up to b, including b
    • a,*]: matches all versions a and greater
  • servicedisplayname: This displays a name for similarly grouped services.
  • servicename: This is the name of the service. Use as the name of the service registry documents.

The "appmodel/metadata.json" file (see Listing 5) describes the components, links, and policies that are implemented by the plug-in. Shared services use the same attribute design. Default attributes can be used for the specific attribute inside the predefined appmodel, or by using the sample value field in metadata.json.

Listing 5. Sample metadata.json file
[
   {
      "id": "Memcached",
      "label": "Memcached",
      "description": "Memcached Shared Service",
      "thumbnail": "",
      "image": "",
      "type": "component",
      "category": "Memcached",
      "attributes": [
         {
            "id": "memcached_vm_instances",
            "type": "string",
            "required": false,
            "sampleValue":"5",
            "options": [
               {
                  "name": "1",
                  "value": "1"
               },
               {
                  "name": "2",
                  "value": "2"
               },
               {
                  "name": "3",
                  "value": "3"
               },
               {
                  "name": "4",
                  "value": "4"
               },
               {
                  "name": "5",
                  "value": "5"
               },
               {
                  "name": "6",
                  "value": "6"
               },
               {
                  "name": "7",
                  "value": "7"
               },
               {
                  "name": "8",
                  "value": "8"
               },
               {
                  "name": "9",
                  "value": "9"
               },
               {
                  "name": "10",
                  "value": "10"
               }
            ],
            "label": "memcached_vm_instance_number"
         }
      ]
   }
]

The memcached_vm_instances attribute with the type string specifies how many Memcached VM instances are contained in the pool with a default value of 5.

Define a registry provider class

The shared service registry contains information that clients can look up to find information that is shared by the service. The infrastructure provides this ability through the shared service specific implementation of the "com.ibm.maestro.iaas.RegistryProvider" class. The method shown in Listing 6 allows a shared service to return information to the client based on its model and deployment configuration.

Listing 6. Method getRegistry

Click to see code listing

Listing 6. Method getRegistry

public JSONArtifact getRegistry(String clientVersion, Map<String, JSONObject> deploymentInfo) throws HttpException;

The "deploymentInfo" parameter contains JSON fragments for appmodel (appmodel.json), deployment (deployment.json), topology (topology.json), and registry (registry.json).

The Memcached shared service provides the information of the manager node's IP address, which is used as the Memcached instances pool manager. This provides the unique entry for a shared service client to get available Memcached instances. Shared service clients interact with the shared service in the lifecycle scripts through the REST API. This interaction and the REST API are illustrated later in this article.

Create the topology template for the appmodel

Transformers are services that convert the application model from a logical description into a topology document fragment that is used to deploy the virtual application. A shared service can also define a template for a topology document. Transformers convert the template to an actual topology document during deployment. The attribute shown in Listing 7 must be provided by a shared service to reference the shared service registry provider class.

Listing 7. Sample topology template for appmodel
{
    "service-registry": [
        {
            "type":"com.ibm.memcached.MemcachedRegistryProvider"                 
        }
    ]
}

Do not include the "vm-templates" attribute section for an external shared service topology template since it is pointing to an external resource implementation of the shared service. Since no virtual machine instances will be generated for this component, the vm-templates attribute section is not added either.

Create a base plug-in implementation

While the shared service implementation makes the pattern type as a shared service, the base plug-in implementation does the actual work: installation, configuration, role dependency, and REST API generation. Since the base plug-in is like any other plug-in, this section focuses on REST API creation and validation.

Figure 7. Structure of base plug-in implementation
Structure of base plug-in implementation

In Figure 7, the base plug-in project contains two roles:

  • MEMCACHED: This handles Memcached installation and configuration.
  • MEMCACHEDMANAGER: This is the manager for the collection of Memcached VM instances. It decides which Memcached VM instance is available for the shared service client. It keeps a map for all these Memcached VM instances. When a client requests or releases a Memcached VM instance, it updates the map and performs the corresponding action. All these actions are implemented by the REST API.

Generic shared service REST API support

The generic shared service REST infrastructure helps provide a common HTTP-based interaction model for clients to start methods that are exposed by shared services. Shared services can provide operation metadata and Python scripts that implement the methods. The client can call the generic shared service REST APIs to start the operations. For example, a client might call GET on the REST URL using this format: https://<Master_Agent_VM>:9999/sharedservice/<servicename>/<resource>.

In this sample, the REST URL is: https://<MEMCACHEDMANAGER_HOSTNAME>:9999/sharedservice/memcached/test

Follow these steps to configure the server-side metadata and scripts:

  1. The service metadata must be provided in a JSON file and packaged in shared service nodepart data (Listing 8). For example: plugin/nodeparts/memcachedapi/properties/memcachedapi.json.
    Listing 8. Service metadata memcachedapi.json file
    {
        "servicename": "memcached",
        "operations": [{
            "type": "GET",
            "parms": [{
                "resource": "test",
                "clientdeploymentexposure": true,
                "role": "memcached-vm-instance-manager.MEMCACHEDMANAGER",
                "script": "api.py get",
                "timeout": 120000,
                "pattern": "{vappInstId}"
            }
            ]
        },
        {
            "type": "DELETE",
            "parms": [
            {
                "resource": "test",
                "clientdeploymentexposure": true,
                "role": "memcached-vm-instance-manager.MEMCACHEDMANAGER",
                "script": "api.py delete",
                "timeout": 120000,
                "pattern": "{vappInstId}"
            }
            ]
        }
        ]
    }

    The JSON object in the metadata must contain the following attributes:

    1. servicename: This is the name of the shared service, memcached.
    2. operations: This is the JSON array of operations that is exposed by the service. Each object in this array defines the following attributes:
      1. type: This is the HTTP operation type of GET, PUT, POST or DELETE.
      2. parms: This is the JSON array of objects that represents parameters for each call of that type. The object must define the following attributes:
        1. resource: This is the resource on which the operation is carried out. This maps to the URL segment after the servicename on the REST URL.
        2. role: This is the role this operation is to run against, which is the combination of a VM name and a role name.
        3. script (<script_name> <method_name>): This is the Python script that defines the operation and the method that starts.
        4. clientdeploymentexposure: This is optional. It determines whether the call can originate from client deployed VMs in addition to the kernelServices process. The default value is false.
        5. timeOut: This is optional. The default value is 6000. If this attribute is 0, the operation runs synchronously with no timeout. If this attribute is greater than 0, the operation waits the specified amount of time in milliseconds for this call to return. The operation responds with an HTTP 202 response if a timeout occurs.
        6. pattern: This attribute can be used to match further segments of the URL to feed further parameters into the operation. An entry that is wrapped in curly braces matches as a name-value pair against the incoming URL and passes into the operation as a parameter. For example, consider a REST URL in the form of https://<host>:<port>/sharedservice/memcached/test/vappID and a pattern of {vappInstId}. The name and value pair of vappInstId=vappID feeds into the operation as an additional argument.
    3. Copy the metadata to the appropriate location. During VM start of the shared service deployment, the metadata must be copied to the following location on VM: /0config/sharedservices/restmetadata/. This metadata can be copied by providing a nodepart installation script to run during the deployment. For example: /plugin/nodeparts/memcachedapi/common/install/memcachedapi.py. Listing 9 is the nodepart installation script that copies the metadata to the appropriate location.
      Listing 9. memcachedapi.py
      import os
      import maestro
      
      CONFIGDIR = maestro.sharedservice.getJSONCfgDir()
      FILENAME = '/memcachedapi.json'
      DEST = CONFIGDIR + FILENAME
      SRC = '../../memcachedapi/properties' + FILENAME
      
      os.popen('mkdir -p ' + CONFIGDIR)
      os.popen("mv " + SRC + " " + DEST)
    4. Provide the implementation of methods in a Python script. Define the operations that run based on parameters from the different sources, and input JSON objects to the REST call for the URL pattern matching.
    5. Provide the implementation of methods in a Python script. It should implement all the methods defined in the memcachedapi.json file. For example: /parts/memcached.scripts/scripts/MEMCACHEDMANAGER/api.py. For further details of the REST API implementation, refer to the downloadable source code provided with this article.

Client interaction and validation

The client can call APIs in several ways:

  1. Invoke within the "KernelServices" process. If the operations on the service are invoked within the KernelServices process (through a Service Provisioner), use the method shown in Listing 10 that is defined on com.ibm.maestro.iaas.RegistryService.
    Listing 10. Method callOperationOnSharedService

    Click to see code listing

    Listing 10. Method callOperationOnSharedService

    public OperationResponse callOperationOnSharedService(String serviceName, String clientCloudGroup, String clientVersion,String serviceIP, String resourceUrl, String operationType, JSONObject operationParms) throws HttpException;
  2. Invoke within the lifecycle scripts. For virtual application deployments, shared services infrastructure provides a utility to interact with shared services. This utility can be accessed within the lifecycle scripts. The utility script provides only one method:

    Click to see code listing

    callSSrestapi: sharedservices.callSSrestapi(url, method, data=None,filepath_input=None, filepath_output=None)

    It makes the REST API call to the specified URL with the specified method. This function returns the HTTP status code of the call and the returned JSON document, if one is provided. To access this function, the script has to import the sharedservices module, as shown in Listing 11.

    Listing 11. Sample invocation within lifecycle scripts
    import maestro
    import sys
    sharedServicePath = '/0config/nodepkgs/helper/scripts'
    if not sharedServicePath in sys.path:
    	sys.path.append(sharedServicePath)
    import sharedservices
    
    vappInstId = 'someVappId'
    sharedServiceInfo = maestro.registry.getRegistry('memcached','1.0')
    if sharedServiceInfo:
    	if sharedServiceInfo.has_key('memcached_manager_ip'):
    		mip =  sharedServiceInfo['memcached_manager_ip']
    		ipaddress = str(mip)
    		urlGet = 'https://' + ipaddress + ':9999/sharedservice/memcached/test' + '/' + vappInstId
    		http_code,mem_response = sharedservices.callSSrestapi(urlGet,'GET')
  3. Manual testing of the API is possible through the following on the deployed VM, as shown in Listing 12.
    Listing 12. Sample manual testing

    Click to see code listing

    Listing 12. Sample manual testing

    cd /0config
    export $(./get_userdata.sh)
    export header=$(/opt/python-2.6.4/bin/python create_security_header.py)
    curl -H "X-IWD-Authorization : $header" -kv -H Content-Type:application/json -X GET https://172.20.102.10:9999/sharedservice/memcached/test/someVappId

    The elements of the API call are:

    • 172.20.102.10: This is the IP address of the shared service. It is the IP address of the MEMCACHEDMANAGER node.
    • memcached: This is the servicename defined in memcachedapi.json.
    • test: This is the resource name.
    • someVappId: This is the input parameter of the {vappInstId} pattern.

Conclusion

This last part of the series, Part 3, showed you how to implement Memcached as a shared service, including creating the pattern type project, creating plug-in projects, implementing the shared service, and validating the REST API service.

Download files

See the provided sample code for samples.memcached. Download the package and select from the menu: File > Import… > IBM Workload Plug-in Development > IBM Workload Pattern type Package, to import the projects.


Download

DescriptionNameSize
Code samplepatterntype.sample.memcached-1.0.0.0.zip18KB

Resources

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Cloud computing on developerWorks


  • Bluemix Developers Community

    Get samples, articles, product docs, and community resources to help build, deploy, and manage your cloud apps.

  • developerWorks Labs

    Experiment with new directions in software development.

  • DevOps Services

    Software development in the cloud. Register today to create a project.

  • Try SoftLayer Cloud

    Deploy public cloud instances in as few as 5 minutes. Try the SoftLayer public cloud instance for one month.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Cloud computing
ArticleID=955548
ArticleTitle=Using the IBM Pattern Development Kit to build virtual application patterns, Part 3: Build Memcached as a shared service
publish-date=12042013