Developing polyglot applications on Cloud Foundry (#oredev 2012)

76
Developing polyglot applications on Cloud Foundry Chris Richardson Author of POJOs in Action Founder of the original CloudFoundry.com @crichardson [email protected] http://plainoldobjects.com/

description

Developing web applications used to be simple. Your single war-file web application served up HTML to a desktop browser and used a relational database. Today however, web applications are much more complex: the front-end uses HTML5 and NodeJS, the middle tier is decomposed into multiple services, and the back-end uses a mix of SQL and NoSQL databases. Developing these kind of applications can be challenging since there are so many moving parts that need to be correctly installed and configured. Deployment is even more difficult. In this talk, you will learn why we need to build applications with this architectural style and how Cloud Foundry, which is modern, multi-lingual, multi-service, extensible open-source PaaS, can help. We will talk about how to develop modern applications that run on Cloud Foundry and cover what’s new and different about the cloud environment. You will learn how your application can consume the various services that are provided by Cloud Foundry. We will discuss the various ways of using Cloud Foundry including the Micro Cloud that runs on a laptop as well as the hosted CloudFoundry.com.

Transcript of Developing polyglot applications on Cloud Foundry (#oredev 2012)

Page 1: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Developing polyglot applications on Cloud Foundry

Chris Richardson

Author of POJOs in Action

Founder of the original CloudFoundry.com

@crichardson

[email protected]

http://plainoldobjects.com/

Page 2: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Presentation goal

Modular, polyglot applications:

what, why and how?

How Cloud Foundry simplifies

their development and deployment

Page 3: Developing polyglot applications on Cloud Foundry (#oredev 2012)

About Chris

Page 4: Developing polyglot applications on Cloud Foundry (#oredev 2012)

(About Chris)

Page 5: Developing polyglot applications on Cloud Foundry (#oredev 2012)

About Chris()

Page 6: Developing polyglot applications on Cloud Foundry (#oredev 2012)

About Chris

Page 7: Developing polyglot applications on Cloud Foundry (#oredev 2012)

About Chris

http://www.theregister.co.uk/2009/08/19/springsource_cloud_foundry/

Page 8: Developing polyglot applications on Cloud Foundry (#oredev 2012)

vmc push About-Chris

Signup at http://cloudfoundry.com

Developer Advocate for CloudFoundry.com

Page 9: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Agenda

• The (sometimes evil) monolith

• Refactoring to a modular, polyglot architecture

• Deploying modular, polyglot applications

Page 10: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Let’s imagine you are building an e-commerce application

Page 11: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Traditional web application architecture

Tomcat

Browser

WAR

MySQL Database

ShippingService

AccountingService

InventoryService

StoreFrontUI

developtestdeploy

Simple to

Apache

scale

Page 12: Developing polyglot applications on Cloud Foundry (#oredev 2012)

But there are problems

Page 13: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Users expect a rich, dynamic and interactive experience

Java Web ApplicationBrowser

HTTP Request

HTML/Javascript

Old style UI architecture isn’t good enough

Real-time web ≅ NodeJS

Page 14: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Limitations of relational databases

• Scalability

• Distribution

• Schema updates

• O/R impedance mismatch

• Handling semi-structured data

Page 15: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Monolithic architecture=

Problems

Page 16: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Intimidates developers

Page 17: Developing polyglot applications on Cloud Foundry (#oredev 2012)

• Need to redeploy everything to change one component

• Increases risk of failure, e.g. interrupts background jobs

Fear of change

• Extensive test cycle

• Updates will happen less often, e.g. Makes A/B testing UI really difficult

Obstacle to frequent deployments

Page 18: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Overloads your IDE and container

Slows down development

Page 19: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Lots of coordination and communication required

Obstacle to scaling developmentI want to update

the UI

But the backend is not working yet!

Page 20: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Requires long-term commitment to a technology stack

Page 21: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Agenda

• The (sometimes evil) monolith

• Refactoring to a modular, polyglot architecture

• Decomposing applications into services

• Using NoSQL

• Presentation layer design

• Deploying modular, polyglot applications

Page 22: Developing polyglot applications on Cloud Foundry (#oredev 2012)
Page 23: Developing polyglot applications on Cloud Foundry (#oredev 2012)

The scale cube

X axis - horizontal duplication

Z axis

- data

parti

tionin

g

Y axis - functionaldecomposition

Scale

by sp

litting

similar

thing

s

Scale by splitting different things

Page 24: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Y-axis scaling - application level

WAR

ShippingService

AccountingService

InventoryService

StoreFrontUI

Page 25: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Y-axis scaling - application level

Store front web application

shipping application

inventory application

Apply X axis cloning and/or Z axis partitioning to each service

ShippingService

AccountingService

InventoryServiceStoreFrontUI

accounting application

Page 26: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Drawbacks of Y-axis splits

• Complexity

• Partitioned databases and transaction management

• Deciding when to use this approach

Page 27: Developing polyglot applications on Cloud Foundry (#oredev 2012)

But there are many benefits

• Scales development: develop, deploy and scale each service independently

• Less for each developer to learn

• Doesn’t overload IDE or container

• Improves fault isolation

• Eliminates long-term commitment to a single technology stack

Page 28: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Two levels of architecture

System-level

ServicesInter-service glue: interfaces and communication mechanismsSlow changing

Service-level

Internal architecture of each serviceEach service can use a different technology stackPick the best tool for the jobRapidly evolving - regularly rewrite

Page 29: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Modular, polyglot, applications

Page 30: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Inter-service communication options

• Transports: Synchronous HTTP ⇔ asynchronous AMQP

• Formats: JSON, XML, Protocol Buffers, Thrift, ...

Asynchronous is preferred but REST is fine

JSON is fashionable but binary format is more efficient

Page 31: Developing polyglot applications on Cloud Foundry (#oredev 2012)

StoreFrontUI

storefront web application

AccountingService

accounting application

InventoryService

inventory application

ShippingService

shipping application

MySQL

RabbitMQ(Message Broker)

Asynchronous message-based communication

Page 32: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Agenda

• The (sometimes evil) monolith

• Refactoring to a modular, polyglot architecture

• Decomposing applications into services

• Using NoSQL

• Presentation layer design

• Deploying modular, polyglot applications

Page 33: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Solution: Use NoSQL

Benefits

• Higher performance

• Higher scalability

• Richer data-model

• Schema-less

Drawbacks

• Limited transactions

• Limited querying

• Relaxed consistency

• Unconstrained data

Page 34: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Example NoSQL Databases

Database Key features

Cassandra Extensible column store, very scalable, distributed

Neo4j Graph database

MongoDB Document-oriented, fast, scalable

Redis Key-value store, very fast

http://nosql-database.org/ lists 122+ NoSQL databases

Page 35: Developing polyglot applications on Cloud Foundry (#oredev 2012)

NoSQL and the scale cube

MongoDB replica setsCassandra replication

Mongo

DB sha

rding

Cassan

dra

parti

tionin

g

Page 36: Developing polyglot applications on Cloud Foundry (#oredev 2012)

The future is polyglot

IEEE Software Sept/October 2010 - Debasish Ghosh / Twitter @debasishg

Page 37: Developing polyglot applications on Cloud Foundry (#oredev 2012)

StoreFrontUI

storefront web application

AccountingService

accounting application

InventoryService

inventory application

ShippingService

shipping application

MySQL

RabbitMQ(Message Broker)

Polyglot persistence architecture

Redis

Mongo

Page 38: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Agenda

• The (sometimes evil) monolith

• Refactoring to a modular, polyglot architecture

• Decomposing applications into services

• Using NoSQL

• Presentation layer design

• Deploying modular, polyglot applications

Page 39: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Modular application

Choice of presentation layer technology

Page 40: Developing polyglot applications on Cloud Foundry (#oredev 2012)

NodeJS is the fashionable technology

Page 41: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Why NodeJS?• Familiar JavaScript

• High-performance, scalable event-driven, non-blocking I/O model

• Over 13,000 17,000 modules developed by the community

• Many JavaScript client frameworks have a NodeJS counterpart, e.g. socket.io and SockJS

Page 42: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Why not NodeJS?

a.k.a. callback hell

Page 43: Developing polyglot applications on Cloud Foundry (#oredev 2012)

A modern web application

BrowserService 1

Service 2

...

HTML 5ApplicationSocket.io

client

Events

REST

Server ApplicationSocket.io

server

Node JS

Page 44: Developing polyglot applications on Cloud Foundry (#oredev 2012)

NodeJS as a mediator

Node JS

Service

RabbitMQ Service

REST

AMQP AMQP

REST

Events

socket.io

Page 45: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Socket.io - server-sidevar express = require('express') , http = require('http') , amqp = require(‘amqp’) ....;

server.listen(8081);...var amqpCon = amqp.createConnection(...);

io.sockets.on('connection', function (socket) { function amqpMessageHandler(message, headers, deliveryInfo) { var m = JSON.parse(message.data.toString()); socket.emit(‘tick’, m); }; amqpCon.queue(“myQueue”, {}, function(queue) { queue.bind(“myExchange”, “myBindingKey”); queue.subscribe(amqpMessageHandler); });});

Handle socket.io connection

Subscribe to AMQP queue

Republish as socket.io event

Page 46: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Socket.io - client-side

var socket = io.connect(location.hostname);

function ClockModel() { self.ticker = ko.observable(1); socket.on('tick', function (data) { self.ticker(data); });};

ko.applyBindings(new ClockModel());

<html><body>

The event is <span data-bind="text: ticker"></span>

<script src="/socket.io/socket.io.js"></script><script src="/knockout-2.0.0.js"></script><script src="/clock.js"></script>

</body></html>

clock.js

Connect to socket.io server

Subscribe to tick event

Bind to model

Update model

Page 47: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Inventory Service Shipping

NodeJS

Modular, polyglot architecture

RabbitMQ

NodeJS

Inventory Service Shipping Service

Billing Service Redis Inventory Database

Mongo Order Database

Standalone“headless” Spring/Java applications

Spring/Scala web application

MySQL Customer Database

Desktop Browser Native Mobile application HTML5 mobile application

StoreUI StoreUI StoreUI

StoreUIJavascriptAsynchronous,

scalable communication

How

do w

e dev

elop,

test

and d

eplo

y th

is?

Page 48: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Agenda

• The (sometimes evil) monolith

• Refactoring to a modular, polyglot architecture

• Deploying modular, polyglot applications

• Overview of Cloud Foundry

• Using Cloud Foundry

• Consuming Cloud Foundry services

Page 49: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Simple, Open, Flexible,

Scalable

The Open Platform as a Service

Deploy and scale polyglot applications in seconds, without

locking yourself into a single cloud

Page 50: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Applica'on  Service  Interface

OSS community

Private  Clouds  

PublicClouds

MicroClouds

Data Services

Other Services

Msg Services

vFabric Postgres

vFabric RabbitMQTM

Additional partners services …

Page 51: Developing polyglot applications on Cloud Foundry (#oredev 2012)

CloudFoundry.COM - Multi-tenant PaaS operated by VMware

Runtimes & FrameworksServices

vCenter / vSphere

CloudFoundry.COM (beta)

Infrastructure

Page 52: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Micro Cloud FoundryTM – Industry first downloadable PaaS

Open source Platform as a Service project

App Instances Services

A cloud packaged as a VMware Virtual Machine

Page 53: Developing polyglot applications on Cloud Foundry (#oredev 2012)

CloudFoundry.ORG - Vibrant Apache 2 licensed open-source project

CloudFoundry.ORG

DownloadCode

Setup Environment

Deploy Behind FirewallBOSH

Your Infrastructure

Page 54: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Cloud Foundry: you can trade-off effort vs flexibility

Public PaaS

Private PaaS

Custom Private PaaS

Less

More

Less

More

.COM....

....

git clone git://github.com/cloudfoundry/vcap.git

Effort Flexibility

Page 55: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Agenda

• The (sometimes evil) monolith

• Refactoring to a modular, polyglot architecture

• Deploying modular, polyglot applications

• Overview of Cloud Foundry

• Using Cloud Foundry

• Consuming Cloud Foundry services

Page 56: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Using Cloud Foundry

Page 57: Developing polyglot applications on Cloud Foundry (#oredev 2012)

$ vmc target <any cloud>

$ vmc login <credentials> $ vmc push <my-app>

> bind services? Yes

$ vmc update <my-app>

$ vmc instances <my-app> +100

Example vmc commands

Page 58: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Sinatra + Redisrequire 'sinatra'require 'redis'

configure do $r = Redis.new(:host => '127.0.0.1', :port => '6379') if !$r end

get '/' do "Hello World! " + $r.incr("hitcounter").to_send

http://sgce2012.cloudfoundry.com/

Connect to Redis

Increment hit counter

Page 59: Developing polyglot applications on Cloud Foundry (#oredev 2012)
Page 60: Developing polyglot applications on Cloud Foundry (#oredev 2012)

One step deployment--- applications: ./storefront: name: nodestore framework: name: node info: mem: 64M description: Node.js Application exec: url: ${name}.${target-base} mem: 64M instances: 1 services: si-redis: type: redis si-rabbit: type: rabbitmq

Path to application

Required platform services

Page 61: Developing polyglot applications on Cloud Foundry (#oredev 2012)

applications: standalone-inventory/target/appassembler: name: standalone-shipping framework: name: standalone info: description: Standalone Application exec: runtime: java command: bin/standalone-shipping url: mem: 512M instances: 1 services: si-rabbit: type: rabbitmq si-mongo: type: mongodb

One step deployment

Path to application

Required platform services

Page 62: Developing polyglot applications on Cloud Foundry (#oredev 2012)

One step deployment$ vmc push

Would you like to deploy from the current directory? [Yn]:

Pushing application 'inventory'...

Creating Application: OK

Creating Service [si-rabbit]: OK

Binding Service [si-rabbit]: OK

Creating Service [si-mongo]: OK

Binding Service [si-mongo]: OK

Creating Service [si-redis]: OK

Binding Service [si-redis]: OK

Uploading Application:

Checking for available resources: OK

Processing resources: OK

Packing application: OK

Uploading (12K): OK

Push Status: OK

Staging Application 'inventory': OK

Starting Application 'inventory': OK

Pushing application 'store'...

vmc push:•Reads the manifest file•Creates the required platform services•Deploys all the applications

Page 63: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Micro Cloud Foundry = your sandbox

Open source Platform as a Service project

App Instances Services

10.04

A PaaS packaged as a VMware Virtual Machine

Use as a developer sandbox• Use the services from Junit integration tests

• Deploy your application for functional testing

• Remote debugging from STS

Page 64: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Agenda

• The (sometimes evil) monolith

• Refactoring to a modular, polyglot architecture

• Deploying modular, polyglot applications

• Overview of Cloud Foundry

• Using Cloud Foundry

• Consuming Cloud Foundry services

Page 65: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Cloud Foundry services

Page 66: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Creating a service instance$ vmc create-service mysql mysql1Creating Service: OK

$ vmc services......

=========== Provisioned Services ============+-------------+---------+| Name | Service |+-------------+---------+| mysql1 | mysql |+-------------+---------+

$

Page 67: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Binding a service to an application

$ vmc push cer-spring --path web/target/Application Deployed URL [cer-spring.cloudfoundry.com]: Detected a Java SpringSource Spring Application, is this correct? [Yn]:

Memory Reservation (64M, 128M, 256M, 512M, 1G) [512M]:

Creating Application: OKWould you like to bind any services to 'cer-spring'? [yN]: y

Would you like to use an existing provisioned service? [yN]: yThe following provisioned services are available

1: mysql1

2: mysql-135e0Please select one you wish to use: 1

Binding Service [mysql1]: OKUploading Application:

Checking for available resources: OK

Processing resources: OK Packing application: OK

Uploading (12K): OK

Would you like to bind any services to 'cer-spring'? [yN]: yWould you like to use an existing provisioned service? [yN]: yThe following provisioned services are available1: mysql12: mysql-135e0Please select one you wish to use: 1Binding Service [mysql1]: OK

Page 68: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Bindings exposed through VCAP_SERVICES environment variable

{ "mysql-5.1": [{

"name": "mysql1", "label": "mysql-5.1",

"plan": "free", "tags": ["mysql", "mysql-5.1", "relational"],

"credentials": {

"name": "da81b57c25cca4c65929a223f0ed068a0",

"host": "172.99.99.99",

"port": 3306,

"username": "secretusername",

"password": "secretuserpassword"

....

}

}] }

Page 69: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Accessing bound services:low-level

var services = JSON.parse(process.env.VCAP_SERVICES);var creds = services['mysql-5.1'][0].credentials

configure do services = JSON.parse(ENV['VCAP_SERVICES']) mysql_key = services.keys.select { |svc| svc =~ /mysql/i }.first mysql = services[mysql_key].first['credentials'] mysql_conf = {:host => mysql['hostname'], :port => mysql['port'], :username => mysql['user'], :password => mysql['password']} @@client = Mysql2::Client.new mysql_confend

Page 70: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Accessing bound services:high-level, Spring/Java

<bean id="dataSource" class="…"> … DataSource for MySQL instance … </bean>

reconfigured automatically

CloudEnvironment environment = new CloudEnvironment();RdbmsServiceInfo mysqlSvc = environment.getServiceInfo("mysqlService", RdbmsServiceInfo.class);RdbmsServiceCreator dataSourceCreator = new RdbmsServiceCreator();DataSource dataSource = dataSourceCreator.createService(mysqlSvc);

<cloud:data-source id="dataSource" service-name="mysql1"> <cloud:pool pool-size="1-5"/> <cloud:connection properties="charset=utf-8"/></cloud:data-source>...

Page 71: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Accessing bound services:high-level, Ruby

RedisHost = "127.0.0.1"RedisPort = 10000$r = Redis.new(:host => RedisHost, :port => RedisPort) if !$r

reconfigured automatically

production: adapter: sqlite3 database: db/production.sqlite3 pool: 5 timeout: 5000

rewritten automatically

Page 72: Developing polyglot applications on Cloud Foundry (#oredev 2012)

The human body as a system

Page 73: Developing polyglot applications on Cloud Foundry (#oredev 2012)

50 to 70 billion of your cells die each day

Page 74: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Yet you (the system) remain you

Page 75: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Can we build software systems with these characteristics?

http://dreamsongs.com/Files/WhitherSoftware.pdf

http://dreamsongs.com/Files/DesignBeyondHumanAbilitiesSimp.pdf

Page 76: Developing polyglot applications on Cloud Foundry (#oredev 2012)

Questions?

@crichardson [email protected]://plainoldobjects.com/presentations/

www.cloudfoundry.com @cloudfoundry