MILAN November 28th/29th, 2014
REST in Practice, in Practice
@iansrobinson
Ian Robinson
MILAN November 28th/29th, 2014 – Ian Robinson
Internal Mail
Work in the 1950s Office
Business
MILAN November 28th/29th, 2014 – Ian Robinson
RESTful Web App
Domain Model
Web Technologies
http://app
http://app/abc
http://app/xyz
HTTP
HTTP
MILAN November 28th/29th, 2014 – Ian Robinson
Protocols Coordinate Processes
v HTTP
v ?
MILAN November 28th/29th, 2014 – Ian Robinson
Protocols
MILAN November 28th/29th, 2014 – Ian Robinson
Protocol SpecificaBon
MILAN November 28th/29th, 2014 – Ian Robinson
Protocol Discovery
MILAN November 28th/29th, 2014 – Ian Robinson
Everyday Protocol Discovery
MILAN November 28th/29th, 2014 – Ian Robinson
Hypermedia Constraint
Hypermedia As
The
Engine Of
Application State
MILAN November 28th/29th, 2014 – Ian Robinson
Graph database Clustered
MILAN November 28th/29th, 2014 – Ian Robinson
Infrastructure and Tooling
• Performance tesBng • Soak tesBng • Stress tesBng • Proof of concept • Reproduce customer issues
http://www.danzigergallery.com/artists/yuji-obata/7
MILAN November 28th/29th, 2014 – Ian Robinson
MILAN November 28th/29th, 2014 – Ian Robinson
TestLab Manager
Workflows Application State
MILAN November 28th/29th, 2014 – Ian Robinson
Provision Estate
Install Database
Configure Database
Install Dataset
Install Extension
Start Database Archive Logs
Backup Database
Check Database Status
Capture Heap Dump
Install Workload
Execute Workload
Publish Results
Analyze Results
1. Design Around CapabiliBes
MILAN November 28th/29th, 2014 – Ian Robinson
Provision Estate
Install Database
Configure Database
Install Dataset
Install Extension
Start Database Archive Logs
Backup Database
Check Database Status
Capture Heap Dump
Install Workload
Execute Workload
Publish Results
Analyze Results
Implement as Resource Families
MILAN November 28th/29th, 2014 – Ian Robinson
Deploy in Services
Provision Estate
Install Database
Configure Database
Install Dataset
Backup Database
Check Database Status
Capture Heap Dump
Install Extension
Start Database Archive Logs
Database Agent
Install Workload
Execute Workload
Load Generator
Publish Results
Analyze Results
Results Service
MILAN November 28th/29th, 2014 – Ian Robinson
Client Creates an ApplicaBon • Client-‐specific applicaBon goal
• Applies resources to saBsfy this goal • Intelligence at the edges
• Client understands/reconstructs state of the applicaBon
MILAN November 28th/29th, 2014 – Ian Robinson
Neo-‐Workbench Java SDK
Database Agent
Command-‐Line Tools Tests (e.g. Soak Tests)
Database Agent
Database Agent
Servers
Clients
MILAN November 28th/29th, 2014 – Ian Robinson
Database Agent Demo • Browser • Command-‐line • Code
MILAN November 28th/29th, 2014 – Ian Robinson
<table> <tr> <td> <a href="http://localhost:38000/database-agent/001" rel="database-admin">001</a> </td> </tr> ...</table>
<form class="install-database" method="POST" action="http://localhost:38000/database-agent/" enctype="application/x-www-form-urlencoded"> <input type="hidden" name="_redirect_" value="http://localhost:38000/database-agent/"></input> <input type="text" name="installUri"></input> <button type="submit" id="submit-form-install-database">Install</button></form>
2. Choose a Hypermedia Format
MILAN November 28th/29th, 2014 – Ian Robinson
<table> <tr> <td> <a href="http://localhost:38000/database-agent/001" rel="database-admin">001</a> </td> </tr> ...</table>
<form class="install-database" method="POST" action="http://localhost:38000/database-agent/" enctype="application/x-www-form-urlencoded"> <input type="hidden" name="_redirect_" value="http://localhost:38000/database-agent/"></input> <input type="text" name="installUri"></input> <button type="submit" id="submit-form-install-database">Install</button></form>
Link – Safe OperaBons
SemanBc context
MILAN November 28th/29th, 2014 – Ian Robinson
<table> <tr> <td> <a href="http://localhost:38000/database-agent/001" rel="database-admin">001</a> </td> </tr> ...</table>
<form class="install-database" method="POST" action="http://localhost:38000/database-agent/" enctype="application/x-www-form-urlencoded"> <input type="hidden" name="_redirect_" value="http://localhost:38000/database-agent/"></input> <input type="text" name="installUri"></input> <button type="submit" id="submit-form-install-database">Install</button></form>
Form – Unsafe OperaBons
SemanBc context
MILAN November 28th/29th, 2014 – Ian Robinson
<table> <tr> <td> <a href="http://localhost:38000/database-agent/001" rel="database-admin">001</a> </td> </tr> ...</table>
<form class="install-database" method="POST" action="http://localhost:38000/database-agent/" enctype="application/x-www-form-urlencoded"> <input type="hidden" name="_redirect_" value="http://localhost:38000/database-agent/"></input> <input type="text" name="installUri"></input> <button type="submit" id="submit-form-install-database">Install</button></form>
Program the Client
MILAN November 28th/29th, 2014 – Ian Robinson
<table> <tr> <td> <a href="http://localhost:38000/database-agent/001" rel="database-admin">001</a> </td> </tr> ...</table>
<form class="install-database" method="POST" action="http://localhost:38000/database-agent/" enctype="application/x-www-form-urlencoded"> <input type="hidden" name="_redirect_" value="http://localhost:38000/database-agent/"></input> <input type="text" name="installUri"></input> <button type="submit" id="submit-form-install-database">Install</button></form>
Machines First, Browsers Second
Conven&on Fields with _underscores_ target the browser
MILAN November 28th/29th, 2014 – Ian Robinson
POST /database-agentinstallUri=file:///neo4j-enterprise-2.1.5-unix.tar.gz
Client Database Agent
ProgrammaBc Client
201 CREATEDLocation: /database-agent/001/
MILAN November 28th/29th, 2014 – Ian Robinson
Database Agent
Browser Client
303 SEE OTHERLocation: /database-agent
GET/database-agent
200 OKContent-Type: text/html
POST /database-agentinstallUri=file:///neo4j-enterprise-2.1.5-unix.tar.gz_redirect_=/database-agent
MILAN November 28th/29th, 2014 – Ian Robinson
3. Long-‐Running Processes • Request triggers long-‐running operaBon (e.g. backup)
• Client waits for response: • What happens if the connecBon breaks?
MILAN November 28th/29th, 2014 – Ian Robinson
202 Accepted • Indicates request has been accepted for processing
• Response includes URI of status monitor • Client polls status monitor
MILAN November 28th/29th, 2014 – Ian Robinson
Client Database Agent
202 Accepted
202 ACCEPTEDLocation: /database-agent/jobs/3e4d0
POST /database-agent/001/storesinstallUri=s3://.../graph.db.zip
GET /database-agent/jobs/3e4d0
202 ACCEPTEDLocation: /database-agent/jobs/3e4d0
GET /database-agent/jobs/3e4d0
201 CREATEDLocation: /database-agent/002/stores/graph.db
Install Store
MILAN November 28th/29th, 2014 – Ian Robinson
Polling Demo
MILAN November 28th/29th, 2014 – Ian Robinson
4. Client-‐Side OrchestraBon
Neo-‐Workbench Java APIs
Command-‐Line Tools Tests (e.g. Soak Tests)
Servers
Clients
1. Install Database 1 2. Install Database 2 3. Install Database 3 4. Upload Store 1-A 5. Upload Store 2-A 6. Upload Store 3-A 7. Start Database 1 8. Start Database 2 9. Start Database 3 10. etc…
Sequential = Slow
MILAN November 28th/29th, 2014 – Ian Robinson
Client Database Agent
Database Agent
Database Agent
Install Database Install Database
Install Database
Upload Dataset Upload Dataset
Upload Dataset
MILAN November 28th/29th, 2014 – Ian Robinson
ReacBve Extensions Iterables Observables
Synchronous Asynchronous
Pull Push for ( Integer integer : stats.counters() ){ System.out.println( integer );}
stats.counters().subscribe( new Action1<Integer>() { @Override public void call( Integer integer ) { System.out.println( integer ); } });
h^ps://github.com/Ne`lix/RxJava/wiki
MILAN November 28th/29th, 2014 – Ian Robinson
new StartCluster() .execute( cluster ) .subscribe( new Action1<URI>() { @Override public void call( URI uri ) { System.out.println( format( "Database started: %s", uri ) ); } } );
Client-‐Side OrchestraBon
MILAN November 28th/29th, 2014 – Ian Robinson
new StartCluster() .execute( cluster ) .subscribe( new Action1<URI>() { @Override public void call( URI uri ) { System.out.println( format( "Database started: %s", uri ) ); } } );
Client-‐Side OrchestraBon
MILAN November 28th/29th, 2014 – Ian Robinson
{ "estate" : { "estateId" : "est51b65", "owner" : "neo-workbench", "scenario" : "soak-test", "blocks" : [ { "blockId" : "blke16a8", "name" : "db-cluster", "size" : 3, "machines" : [ { "id" : "mace5508", "publicIpAddress" : "127.0.0.1", "publicDnsName" : "localhost", "links" : [ { "rel" : "database-agent", "uri" : "http://localhost:38001/database-agent" }, { "rel" : "database-admin", "uri" : "http://localhost:38001/database-agent/003" }, { "rel" : "database", "uri" : "http://localhost:7475" } ],
5. Bookmark ApplicaBon State
MILAN November 28th/29th, 2014 – Ian Robinson
{ "estate" : { "estateId" : "est51b65", "owner" : "neo-workbench", "scenario" : "soak-test", "blocks" : [ { "blockId" : "blke16a8", "name" : "db-cluster", "size" : 3, "machines" : [ { "id" : "mace5508", "publicIpAddress" : "127.0.0.1", "publicDnsName" : "localhost", "links" : [ { "rel" : "database-agent", "uri" : "http://localhost:38001/database-agent" }, { "rel" : "database-admin", "uri" : "http://localhost:38001/database-agent/003" }, { "rel" : "database", "uri" : "http://localhost:7475" } ],
5. Bookmark ApplicaBon State
MILAN November 28th/29th, 2014 – Ian Robinson
6. Automate Deployment
Database Results Load
MILAN November 28th/29th, 2014 – Ian Robinson
Automated Provisioning
Provisioning API AWS
CloudFormation SDK
Local Provisioning Provider
Azure SDK Vagrant
MILAN November 28th/29th, 2014 – Ian Robinson
Fluent API
Estate estate = new Estate() .addBlock( new Block<>( "results", 1, ResultsServiceConfig.DEFAULT, AwsPlatformConfig.DEFAULT ) .addBlock( new Block<>( "db-cluster", 3, DatabaseAgentConfig.builder().withPackageDownloadUri( URI.create( "http://dist.neo4j.org/neo4j-enterprise-2.1.2-unix.tar.gz" ) ).build(), AwsPlatformConfig.DEFAULT ) ) .addBlock( new Block<>( "load-generator", 1, LoadGeneratorConfig.DEFAULT, LocalPlatformConfig.DEFAULT ) );
EstateProvisioning provisioning = new EstateProvisioning();provisioning.provision( estate );
MILAN November 28th/29th, 2014 – Ian Robinson
Graphite Block in AWS
Estate estate = new Estate() .addBlock( new Block<>( "results", 1, ResultsServiceConfig.DEFAULT, AwsPlatformConfig.DEFAULT ) .addBlock( new Block<>( "db-cluster", 3, DatabaseAgentConfig.builder().withPackageDownloadUri( URI.create( "http://dist.neo4j.org/neo4j-enterprise-2.1.2-unix.tar.gz" ) ).build(), AwsPlatformConfig.DEFAULT ) ) .addBlock( new Block<>( "load-generator", 1, LoadGeneratorConfig.DEFAULT, LocalPlatformConfig.DEFAULT ) );
EstateProvisioning provisioning = new EstateProvisioning();provisioning.provision( estate );
MILAN November 28th/29th, 2014 – Ian Robinson
Database Block in AWS
Estate estate = new Estate() .addBlock( new Block<>( "results", 1, ResultsServiceConfig.DEFAULT, AwsPlatformConfig.DEFAULT ) .addBlock( new Block<>( "db-cluster", 3, DatabaseAgentConfig.builder().withPackageDownloadUri( URI.create( "http://dist.neo4j.org/neo4j-enterprise-2.1.2-unix.tar.gz" ) ).build(), AwsPlatformConfig.DEFAULT ) ) .addBlock( new Block<>( "load-generator", 1, LoadGeneratorConfig.DEFAULT, LocalPlatformConfig.DEFAULT ) );
EstateProvisioning provisioning = new EstateProvisioning();provisioning.provision( estate );
MILAN November 28th/29th, 2014 – Ian Robinson
Local Load Generator Block
Estate estate = new Estate() .addBlock( new Block<>( "results", 1, ResultsServiceConfig.DEFAULT, AwsPlatformConfig.DEFAULT ) .addBlock( new Block<>( "db-cluster", 3, DatabaseAgentConfig.builder().withPackageDownloadUri( URI.create( "http://dist.neo4j.org/neo4j-enterprise-2.1.2-unix.tar.gz" ) ).build(), AwsPlatformConfig.DEFAULT ) ) .addBlock( new Block<>( "load-generator", 1, LoadGeneratorConfig.DEFAULT, LocalPlatformConfig.DEFAULT ) );
EstateProvisioning provisioning = new EstateProvisioning();provisioning.provision( estate );
MILAN November 28th/29th, 2014 – Ian Robinson
Fluent API
Estate estate = new Estate() .addBlock( new Block<>( "results", 1, ResultsServiceConfig.DEFAULT, AwsPlatformConfig.DEFAULT ) .addBlock( new Block<>( "db-cluster", 3, DatabaseAgentConfig.builder().withPackageDownloadUri( URI.create( "http://dist.neo4j.org/neo4j-enterprise-2.1.2-unix.tar.gz" ) ).build(), AwsPlatformConfig.DEFAULT ) ) .addBlock( new Block<>( "load-generator", 1, LoadGeneratorConfig.DEFAULT, LocalPlatformConfig.DEFAULT ) );
EstateProvisioning provisioning = new EstateProvisioning();provisioning.provision( estate );
MILAN November 28th/29th, 2014 – Ian Robinson
Ian Robinson, Jim Webber & Emil Eifrem
Graph Databases
h
Compliments
of Neo Technology
@iansrobinson
MILAN November 28th/29th, 2014 – Ian Robinson
Soak Test
Database Agent
Database Agent
Database Agent
Load Server
Results Server
Graphite Graphite
Database Cluster
Workload
Estate
Top Related