developing polyglot applications on cloud foundry (#oredev 2012)

Post on 08-May-2015

1.730 Views

Category:

Technology

1 Downloads

Preview:

Click to see full reader

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

Developing polyglot applications on Cloud Foundry

Chris Richardson

Author of POJOs in Action

Founder of the original CloudFoundry.com

@crichardson

crichardson@vmware.com

http://plainoldobjects.com/

Presentation goal

Modular, polyglot applications:

what, why and how?

How Cloud Foundry simplifies

their development and deployment

About Chris

(About Chris)

About Chris()

About Chris

About Chris

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

vmc push About-Chris

Signup at http://cloudfoundry.com

Developer Advocate for CloudFoundry.com

Agenda

• The (sometimes evil) monolith

• Refactoring to a modular, polyglot architecture

• Deploying modular, polyglot applications

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

Traditional web application architecture

Tomcat

Browser

WAR

MySQL Database

ShippingService

AccountingService

InventoryService

StoreFrontUI

developtestdeploy

Simple to

Apache

scale

But there are problems

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

Limitations of relational databases

• Scalability

• Distribution

• Schema updates

• O/R impedance mismatch

• Handling semi-structured data

Monolithic architecture=

Problems

Intimidates developers

• 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

Overloads your IDE and container

Slows down development

Lots of coordination and communication required

Obstacle to scaling developmentI want to update

the UI

But the backend is not working yet!

Requires long-term commitment to a technology stack

Agenda

• The (sometimes evil) monolith

• Refactoring to a modular, polyglot architecture

• Decomposing applications into services

• Using NoSQL

• Presentation layer design

• Deploying modular, polyglot applications

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

Y-axis scaling - application level

WAR

ShippingService

AccountingService

InventoryService

StoreFrontUI

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

Drawbacks of Y-axis splits

• Complexity

• Partitioned databases and transaction management

• Deciding when to use this approach

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

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

Modular, polyglot, applications

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

StoreFrontUI

storefront web application

AccountingService

accounting application

InventoryService

inventory application

ShippingService

shipping application

MySQL

RabbitMQ(Message Broker)

Asynchronous message-based communication

Agenda

• The (sometimes evil) monolith

• Refactoring to a modular, polyglot architecture

• Decomposing applications into services

• Using NoSQL

• Presentation layer design

• Deploying modular, polyglot applications

Solution: Use NoSQL

Benefits

• Higher performance

• Higher scalability

• Richer data-model

• Schema-less

Drawbacks

• Limited transactions

• Limited querying

• Relaxed consistency

• Unconstrained data

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

NoSQL and the scale cube

MongoDB replica setsCassandra replication

Mongo

DB sha

rding

Cassan

dra

parti

tionin

g

The future is polyglot

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

StoreFrontUI

storefront web application

AccountingService

accounting application

InventoryService

inventory application

ShippingService

shipping application

MySQL

RabbitMQ(Message Broker)

Polyglot persistence architecture

Redis

Mongo

Agenda

• The (sometimes evil) monolith

• Refactoring to a modular, polyglot architecture

• Decomposing applications into services

• Using NoSQL

• Presentation layer design

• Deploying modular, polyglot applications

Modular application

Choice of presentation layer technology

NodeJS is the fashionable technology

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

Why not NodeJS?

a.k.a. callback hell

A modern web application

BrowserService 1

Service 2

...

HTML 5ApplicationSocket.io

client

Events

REST

Server ApplicationSocket.io

server

Node JS

NodeJS as a mediator

Node JS

Service

RabbitMQ Service

REST

AMQP AMQP

REST

Events

socket.io

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

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

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?

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

Simple, Open, Flexible,

Scalable

The Open Platform as a Service

Deploy and scale polyglot applications in seconds, without

locking yourself into a single cloud

Applica'on  Service  Interface

OSS community

Private  Clouds  

PublicClouds

MicroClouds

Data Services

Other Services

Msg Services

vFabric Postgres

vFabric RabbitMQTM

Additional partners services …

CloudFoundry.COM - Multi-tenant PaaS operated by VMware

Runtimes & FrameworksServices

vCenter / vSphere

CloudFoundry.COM (beta)

Infrastructure

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

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

CloudFoundry.ORG

DownloadCode

Setup Environment

Deploy Behind FirewallBOSH

Your Infrastructure

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

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

Using Cloud Foundry

$ 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

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

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

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

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

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

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

Cloud Foundry services

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

$ vmc services......

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

$

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

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"

....

}

}] }

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

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>...

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

The human body as a system

50 to 70 billion of your cells die each day

Yet you (the system) remain you

Can we build software systems with these characteristics?

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

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

Questions?

@crichardson crichardson@vmware.comhttp://plainoldobjects.com/presentations/

www.cloudfoundry.com @cloudfoundry

top related