Developing modular, polyglot applications with Spring (SpringOne India 2012)

5,901 views

Published on

Published in: Technology

Developing modular, polyglot applications with Spring (SpringOne India 2012)

  1. 1. Developing modular, polyglot applications with SpringChris RichardsonAuthor of POJOs in Action, Founder of the original CloudFoundry.com @crichardson chris.richardson@springsource.com http://plainoldobjects.com/
  2. 2. Presentation goal Modular, polyglot applications: what, why and how?Why Spring is the ideal technology for building these applications
  3. 3. About Chris
  4. 4. (About Chris)
  5. 5. About Chris - 1999CORBAEnterprise WebLogic ServerJavaBeans
  6. 6. About Chris - 2004
  7. 7. Spring programming model Dependency Injection POJO Portable Aspect- Service OrientedAbstractions Programming
  8. 8. Transformed how I developed software!
  9. 9. About Chris()
  10. 10. About Chris - 2006Oakland JUG Cloud Computing
  11. 11. Transformed how I deployed software!
  12. 12. About Chris
  13. 13. About Chrishttp://www.theregister.co.uk/2009/08/19/ springsource_cloud_foundry/
  14. 14. vmc push About-Chris Developer Advocate for CloudFoundry.comSignup at http://cloudfoundry.com
  15. 15. Agenda• The (sometimes evil) monolith• Refactoring to a modular, polyglot architecture• Presentation layer design• Using NoSQL databases• Inter-service communication options
  16. 16. Let’s imagine you are building an e-commerce application
  17. 17. Traditional web application architecture WAR StoreFrontUI Accounting Service MySQLBrowser Apache Database InventoryServiceSimple to Shipping Service develop test Tomcat deploy scale
  18. 18. But there are problems
  19. 19. Users expect a rich, dynamic and interactive experience h oug d en HTTP Request oo ’t g Browser e isn Java Web Application HTML/Javascript ec tur it ar ch e UI s tyl Old HTML5/JavaScript browser applications Real-time web ≅ NodeJS
  20. 20. Limitations of relational databases• Scalability• Distribution• Schema updates• O/R impedance mismatch• Handling semi-structured data
  21. 21. Intimidates developers
  22. 22. Scalability issues• Different components have different scalability needs but you can only scale the entire system• Some components might not be scalable can’t scale system
  23. 23. Obstacle to frequent deployments• 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
  24. 24. Overloads your IDE and container Slows down development
  25. 25. Obstacle to scaling development But the I want to update backend is not the UI working yet! Lots of coordination and communication required
  26. 26. Requires long-term commitment to a technology stack
  27. 27. Agenda• The (sometimes evil) monolith• Refactoring to a modular, polyglot architecture• Presentation layer design• Using NoSQL databases• Inter-service communication options
  28. 28. The scale cubeY axis -functionaldecomposition ila g sim ninScale by r ing ing tiosplitting th litt r ti sp padifferent things by data s ale - Sc is ax Z X axis - horizontal duplication
  29. 29. Y-axis scaling - application level WAR StoreFrontUI Accounting Service InventoryService Shipping Service
  30. 30. Y-axis scaling - application level accounting application Accounting ServiceStore front web application inventory application StoreFrontUI InventoryService shipping application Shipping Service Apply X axis cloning and/or Z axis partitioning to each service
  31. 31. Real world examples http://techblog.netflix.com/ Between 100-150 services are accessed to build a page. http://highscalability.com/amazon-architecture http://www.addsimplicity.com/downloads/ eBaySDForum2006-11-29.pdf http://queue.acm.org/detail.cfm?id=1394128
  32. 32. Drawbacks of Y-axis splits• Complexity• Partitioned databases and transaction management• Deciding when to use this approach
  33. 33. But there are many benefits• Scales development: develop, deploy and scale each service independently• Enables frequent deployments• Less for each developer to learn• Doesn’t overload IDE or container• Improves fault isolation• Easily adopt new technologies
  34. 34. Two levels of architecture System-levelServicesInter-service glue: interfaces and communication mechanismsSlow changing Service-levelInternal architecture of each serviceEach service can use a different technology stackRapidly evolving - regularly rewritePick the best tool for the job
  35. 35. Modular, polyglot, applications
  36. 36. Lots of languages andframeworks to choose from And many more...
  37. 37. But there are lots of awesome, and mature Spring projects• Spring Framework • Spring Integration• Spring Security • Spring AMQP• Spring Mobile • Spring Social• Spring Data • Spring Shell• Spring Web Services • ...• Spring Batch
  38. 38. Spring works with Scala@Controllerclass TwilioController { @Autowired var surveyManagementService: SurveyManagementService = _ @RequestMapping(value = Array("/begincall.html")) @ResponseBody def beginCall(@RequestParam("From") callerId: String) = { surveyManagementService.findSurveyByCallerId(callerId) match { case None => <Response> <Say>Sorry dont recognize your number</Say> <Hangup/> </Response> case Some(survey) => <Response> <Say>{ survey.prompt }</Say> <Gather action="handleresponse.html" method="POST" numDigits="1"> { for ((choice, index) <- survey.choices zipWithIndex) yield <Say>Press { index } for { choice }</Say> } </Gather> <Say>We are sorry you could not decide</Say> <Hangup/> </Response> } }
  39. 39. The Spring Scala project class  PersonConfiguration                            extends  FunctionalConfiguration  {        val  jack  =  bean()  {                new  Person("Jack",  "Doe")        }• Scala-style “setters/getters”        val  jane  =  bean()  {                new  Person("Jane",  "Doe")        }• Bean configuration DSL        val  john  =  bean()  {                val  john  =  new  Person("John",  "Doe")                john.father  =  jack()• Scala-style template classes                john.mother  =  jane()                john        } } https://github.com/SpringSource/spring-scala
  40. 40. Coming in 2013 Java 8 closures = concise code!List<Album> albums = ... PredicateList<Album> sortedFavorites = albums.stream() .filter(a -> a.tracks.anyMatch(t -> (t.rating >= 4))) .sorted(comparing(a -> a.name)) .into(new ArrayList<>()); Parallelismint sum = shapes.parallel() .filter(s -> s.getColor() == BLUE) .map(s -> s.getWeight()) .sum(); http://cr.openjdk.java.net/~briangoetz/lambda/sotc3.html
  41. 41. Key benefits of Spring are still Modularity Productivity Portability Testability
  42. 42. Agenda• The (sometimes evil) monolith• Refactoring to a modular, polyglot architecture• Presentation layer design• Using NoSQL databases• Inter-service communication options
  43. 43. Presentation layer evolution.... WAR StoreFrontUI HTML / HTTP View ControllerBrowser Model
  44. 44. ...Presentation layer evolutionBrowser Web application Static content View Controller JSON-REST RESTful Endpoints Model Events EventHTML 5 - JavaScript publisherNo elaborate, server-side web framework required
  45. 45. How to publish events to browser?
  46. 46. NodeJS is the fashionable technology
  47. 47. Why NodeJS?• Familiar JavaScript• High-performance, scalable event-driven, non-blocking I/O model• Compact runtime, e.g. 64M• Over 13,000 17,000 modules developed by the community• ManyJavaScript client frameworks have a NodeJS counterpart, e.g. socket.io and SockJS
  48. 48. Why not NodeJS? a.k.a. callback hell
  49. 49. Dealing with JavaScript “...Still the consequence of this is that we must take javascriptseriously as a first-class language and concentrate on how to limit the damage its flaws cause....”http://martinfowler.com/bliki/gotoAarhus2012.html
  50. 50. NodeJS as a mediator... Node JS Service 1Browser Server app Static content REST Service 2 HTML 5Application EventsSocket.io Socket.io client server ...
  51. 51. ...NodeJS as a mediatorREST REST Service Node JSEvents AMQP AMQP socket.io RabbitMQ Service
  52. 52. Example NodeJS applicationvar express = require(express) , http = require(http) , amqp = require(‘amqp’) , server = http.createServer(app) , io = require(socket.io).listen(server) ....;server.listen(8081); Handle socket.io... connectionvar amqpCon = amqp.createConnection(...);io.sockets.on(connection, function (socket) { Republish as function amqpMessageHandler(message, headers, deliveryInfo) { var m = JSON.parse(message.data.toString()); socket.io event socket.emit(‘tick’, m); }; amqpCon.queue(“”, {}, Subscribe to AMQP function(queue) { queue.bind(“myExchange”, “myBindingKey”); queue queue.subscribe(amqpMessageHandler); });});
  53. 53. Example browser application<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> Bind to model Connect to</html> socket.io server clock.jsvar socket = io.connect(location.hostname);function ClockModel() { self.ticker = ko.observable(1); Subscribe to tick socket.on(tick, function (data) { event self.ticker(data); });}; Update modelko.applyBindings(new ClockModel());
  54. 54. About Cujojs & s2js Dependency Injection www.cujojs.com github.com/s2js JavaScript Portable Aspect- Service OrientedAbstractions Programming
  55. 55. Agenda• The (sometimes evil) monolith• Refactoring to a modular, polyglot architecture• Presentation layer design• Using NoSQL databases• Inter-service communication options
  56. 56. Why NoSQL? Benefits Drawbacks• Higher performance • Limited transactions• Higher scalability • Limited querying• Richer data-model • Relaxed consistency• Schema-less • Unconstrained data
  57. 57. Example NoSQL DatabasesDatabase Key featuresCassandra Extensible column store, very scalable, distributedNeo4j Graph database Document-oriented, fast, scalableMongoDBRedis Key-value store, very fast http://nosql-database.org/ lists 122+ NoSQL databases
  58. 58. NoSQL and the scale cube nin a ing itio dr rd r t an ha pa ss s Ca DB g go on M MongoDB replica sets Cassandra replication
  59. 59. The future is polyglot IEEE Software Sept/October 2010 - Debasish Ghosh / Twitter @debasishg
  60. 60. Polyglot persistence architecture accounting application Accounting Service MySQLstorefront web application inventory application StoreFrontUI InventoryService Redis shipping application ShippingService Mongo
  61. 61. Spring Data = simplifying data access• Redis• MongoDB• Neo4j• JPA• REST• Apache Hadoop• Gemfire http://www.springsource.org/spring-data
  62. 62. Agenda• The (sometimes evil) monolith• Refactoring to a modular, polyglot architecture• Presentation layer design• Using NoSQL databases• Inter-service communication options
  63. 63. Inter-service communication options• Synchronous HTTP asynchronous AMQP• Formats: JSON, XML, Protocol Buffers, Thrift, ... • JSON is fashionable and easier to debug • Binary format is more efficient
  64. 64. Asynchronous message-based communication wgrus-billing.war Accounting Servicewgrus-store.war wgrus-inventory.war RabbitMQStoreFrontUI (Message InventoryService MySQL Broker) wgrus-shipping.war ShippingService
  65. 65. Benefits• Decouples caller from server• Caller unaware of server’s coordinates (URL)• Message broker buffers message when server is down/slow• Supports a variety of communication patterns
  66. 66. Drawbacks• Additional complexity of message broker• Request/reply using messaging is more complex• Firewall unfriendly
  67. 67. Spring AMQP• Encapsulates low-level Producer Consumer details• Simplifiessending and Amqp Listener receiving of messages Template Container Spring AMQP AMQP
  68. 68. Spring Integration• Provides the building blocks for a pipes and filters architecture• Enables development of application components that are • loosely coupled • insulated from messaging infrastructure• Messaging defined declaratively
  69. 69. Development time: same JVM@Servicepublic class OrderServiceImpl { @Service public class ShippingServiceImpl {@Autowiredprivate ShippingService shippingService; public void shipOrder(String orderId) { ....public void placeOrder() { } String orderId = generateOrderId(); … } shippingService.shipOrder(orderId);}} Order Shipping Service service shipOrder() Messaging Gateway Channel Service Activator
  70. 70. Test and production: distributed Application code is unchanged Order Shipping Service serviceMessaging Gateway RabbitMQ Channel AMQP AMQP Channel Service Activator
  71. 71. Synchronous REST wgrus-billing.war Accounting Servicewgrus-store.war REST wgrus-shipping.war StoreFrontUI Shipping MySQL Service wgrus-inventory.war ... InventoryService
  72. 72. Pros and cons of REST• Pros • Cons • Simple and familiar • Only supports request/ reply • Request/reply is easy • Server must be available • Firewall friendly • Clientneeds to know • No intermediate broker URL(s) of server(s)
  73. 73. Spring MVC makes REST easy URL matching @Controller & public class AccountController {object destructuring @AutowiredXML/JSON private MoneyTransferService moneyTransferService; @RequestMapping(value = "/accounts/{accountId}", method = RequestMethod.GET) @ResponseBody public AccountInfo getAccount(@PathVariable String accountId) { Account account = moneyTransferService.findAccountByid(accountId); return makeAccountInfo(account); } @RequestMapping(value = "/accounts", method = RequestMethod.POST) @ResponseStatus( HttpStatus.CREATED ) public void createAccount(@RequestBody AccountInfo accountInfo, UriComponentsBuilder builder, HttpServletResponse response) { ... } XML/JSON object
  74. 74. Not all APIs are RESTfulFrom http://martinfowler.com/articles/richardsonMaturityModel.html
  75. 75. About Hypertext As The Engine Of Application State• Single well known URL• Entity representation has typed relationship links• Client discovers what it can do to an entity via those linksSee http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven
  76. 76. About HATEOAS The well known URL$ curl http://cf-auto-scaler.cloudfoundry.com{"links": [ {"rel":"autoscaledapps", "href":"http://cf-auto-scaler.cloudfoundry.com/autoscaledapps"}]} Link link type$ curl http://cf-auto-scaler.cloudfoundry.com/autoscaledapps{"content":[ {"name":"vertx-clock", "links":[ {"rel":"self","href":"http://cf-auto-scaler.cloudfoundry.com/autoscaledapps/vertx-clock"}, {"rel":"rules","href":"http://cf-auto-scaler.cloudfoundry.com/autoscaledapps/vertx-clock/rules"} ] }],... Links to act on this app}
  77. 77. Spring HATEOAS@Controller@RequestMapping(value = "/autoscaledapps")public class AutoscaledAppController { @RequestMapping(value = "/{appName}", method = RequestMethod.GET) public HttpEntity<AutoscaledAppResource> get(@PathVariable String appName) { AutoscaledAppResource ar = new AutoscaledAppResource(appName); ar.add(linkTo(AutoscaledAppController.class) .slash(appName).withSelfRel()); ar.add(linkTo(AutoscaledAppController.class) .slash(appName).slash("rules").withRel("rules")); return new HttpEntity<AutoscaledAppResource>(ar); } ... public class AutoscaledAppResource} extends ResourceSupport { private String name;https://github.com/SpringSource/spring-hateoas
  78. 78. Consuming RESTful WSRestTemplate restTemplate = new RestTemplate();AccountInfo accountInfo = new AccountInfo(...);URI accountUrl = restTemplate.postForLocation("http://localhost/accounts", accountInfo);ResponseEntity<AccountInfo> accountInfoResponse = restTemplate.getForEntity(accountUrl, AccountInfo.class);Assert.assertEquals(HttpStatus.SC_OK, accountInfoResponse.getStatusCode());AccountInfo accountInfo2 = accountInfoResponse.getBody();...
  79. 79. The Spring REST shell$ rest-shellhttp://localhost:8080:> baseUri http://cf-auto-scaler.cloudfoundry.comhttp://cf-auto-scaler.cloudfoundry.com:> discoverrel href=======================================================================autoscaledapps http://cf-auto-scaler.cloudfoundry.com/autoscaledappshttp://cf-auto-scaler.cloudfoundry.com:> follow --rel autoscaledappshttp://cf-auto-scaler.cloudfoundry.com/autoscaledapps:> post --from src/test/resources/examplejson/createapp1.json --follow true1 files uploaded to the server using POSThttp://cf-auto-scaler.cloudfoundry.com/autoscaledapps/vertx-clock:> discoverrel href================================================================================self http://cf-auto-scaler.cloudfoundry.com/autoscaledapps/vertx-clockrules http://cf-auto-scaler.cloudfoundry.com/autoscaledapps/vertx-clock/ruleshttp://cf-auto-scaler.cloudfoundry.com/autoscaledapps/vertx-clock:> follow --rel ruleshttp://cf-auto-scaler.cloudfoundry.com/autoscaledapps/vertx-clock/rules:> post --from src/test/resources/examplejson/createrule1.json --follow true1 files uploaded to the server using POSThttp://cf-auto-scaler.cloudfoundry.com/autoscaledapps/vertx-clock/rules/idle:> uphttp://cf-auto-scaler.cloudfoundry.com/autoscaledapps/vertx-clock/rules:> up
  80. 80. Original architecture WAR StoreFrontUI Accounting Service MySQLBrowser Apache Database InventoryServiceSimple to Shipping Service develop test Tomcat deploy scale
  81. 81. Modular, polyglot architecture Desktop Browser Native Mobile application HTML5 mobile application oy StoreUI StoreUI StoreUI pl NodeJS !?! eAsynchronous, NodeJS Javascript scalable is d StoreUIcommunication th we RabbitMQ Spring/Scala doweb application Inventory Standalone Inventory Shipping Service Service Shipping “headless” Service Spring ow Integration/Java applications Billing Service Redis Inventory Mongo Order H Database Database MySQL Customer Database
  82. 82. OSS community vFabricPostgres Ap Private   Clouds   p Data Services lica o n  S vFabric Public erv RabbitMQTM ice Msg Services Clouds  In ter fac Micro e Other Services Clouds Additional partners services …
  83. 83. Cloud Foundry simplifies thedeployment of modular, polyglot applications
  84. 84. Spring makes it easy to consume Cloud Foundry services
  85. 85. Many Spring applications run on Cloud Foundry unchanged
  86. 86. Summary• Modern applications have a modular, polyglot architecture• Springis the ideal technology for building these applications• Cloud Foundry is the ideal way to deploy these applications
  87. 87. @crichardson chris.richardson@springsource.com http://plainoldobjects.com Thank you! www.cloudfoundry.com @cloudfoundry

×