Developing applications with Cloud Services (jax jax2013)

709 views

Published on

Cloud computing isn't just about application deployment. There are also a growing number of cloud-based web services that you can use to develop your application. One of the most well known is Amazon's Simple Storage Service. But there are many others including web services for messaging, relational and NoSQL databases, email and telephony. Using these services allows you to build highly scalable applications without the pain and cost of having to develop and operate your own infrastructure. In this presentation, you will learn about the benefits and drawbacks of these Web services; their typical use cases and how to use them. We will describe a location aware, telephony application that is built using cloud services. You will learn about strategies for building resilient, fault tolerant applications that consume cloud services.

0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
709
On SlideShare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
0
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Developing applications with Cloud Services (jax jax2013)

  1. 1. DEVELOPING WITH CLOUDSERVICESChris RichardsonAuthor of POJOs in ActionFounder of the original CloudFoundry.com@crichardsonchris.richardson@springsource.comhttp://plainoldobjects.com
  2. 2. @crichardsonPresentation goalHow to build robust,scalable applications withCloud Services
  3. 3. @crichardsonAbout Chris
  4. 4. @crichardson(About Chris)
  5. 5. @crichardsonAbout Chris()
  6. 6. @crichardsonAbout Chris
  7. 7. @crichardsonAbout Chrishttp://www.theregister.co.uk/2009/08/19/springsource_cloud_foundry/
  8. 8. @crichardsonvmc push About-ChrisDeveloper Advocate forCloudFoundry.com
  9. 9. @crichardsonAgenda• Why use cloud services?• Developing location-based applications• Building SMS and telephony enabled applications• Developing robust, fault tolerant applications
  10. 10. @crichardsonThree phases of every galacticcivilizationSurvivalInquirySophistication
  11. 11. @crichardsonThree phases of every galacticcivilizationHowWhyWherecan we eat?do we eat?Where shall we have lunch?
  12. 12. @crichardsonWhere shall wehave lunch?
  13. 13. @crichardsonSolved byVoteMeetEat.com•What restaurants are nearby?•Which friends are close by?•Where do your friends prefer to eat?To sign up text"register" to 510-XXX-YYYY
  14. 14. @crichardsonVoteMeetEat.comFriend and restaurant location databases+SMS+Voice callsTo sign up text"register" to 510-XXX-YYYY
  15. 15. @crichardsonKey story: registration5551212
  16. 16. @crichardsonKey story: registration+5105551212
  17. 17. @crichardsonKey story: voting555 1212
  18. 18. @crichardsonKey story: announce location
  19. 19. VOTEMEETEAT.COMTo sign up text"register" to 510-XXX-YYYY
  20. 20. @crichardsonHigh-level architectureVoteMeetEatTelephonyIntegrationFriend GeoDatabaseRestaurantDatabaseMobilePhoneDo we really want tobuild all this?DIY = DIFFICULT
  21. 21. @crichardsonUse cloud-based services• Highly scalable services• Someone else’s headache to develop and maintain• Provided by IaaS/PaaS• Provided by 3rd party
  22. 22. @crichardsonCloud Foundry services
  23. 23. @crichardsonThousands of 3rd party serviceshttp://www.programmableweb.com/apis/directoryhttp://www.slideshare.net/jmusser/j-musser-apishotnotgluecon2012
  24. 24. @crichardson• Predominantly REST• Predominantly JSON• > billion API calls/day:Twitter, Google, Facebook, Netflix,Accuweather, ...• Increasing number of API-only companieshttp://www.slideshare.net/jmusser/j-musser-apishotnotgluecon2012Cloud service trends
  25. 25. @crichardsonDiverse
  26. 26. @crichardsonBenefits of cloud services• Someone else’s headache to develop and operate• Focus on your core business problem• Get up and running quickly• Elasticity• Capex Opex
  27. 27. @crichardsonDrawbacks of cloud services• Complexity and drawbacks of a distributed system• You are dependent on service provider
  28. 28. @crichardsonRisks of cloud servicesUrban Airship’s Strategic Partnership WithSimpleGeoTurns Into An Acquisition
  29. 29. @crichardsonCloud Services-basedarchitectureVoteMeetEatTwilioMongoDBFactual.ComMobilePhone
  30. 30. @crichardsonDEMO
  31. 31. @crichardsonAgenda• Why use cloud services?• Developing location-based applications• Building SMS and telephony enabled applications• Developing robust, fault tolerant applications
  32. 32. @crichardsonLocation-based services are hot!
  33. 33. @crichardsonClient-side APIs for findinglocationW3C Geolocation API
  34. 34. @crichardsonBUT what about the server-side?
  35. 35. @crichardsonLots of really difficult problems•Scalable, spatial database – CRUD records, find nearby•Data management – database of places, street information•Forward geo-coding: address lat/lon•Reverse geo-coding: lat/lon address•Maps•DirectionsEasier to use Geo-aaS
  36. 36. @crichardsonExamples of Geo-aaSBeware the terms ofservice• Maps• Forward and reverse geocoding• Directions• Elevation• Places• Freely available geographicdatabase• Various APIs includingreverse geocoding• Business+review database• Neighborhood database• Places database• Reverse geocoding
  37. 37. @crichardsonVoteMeetEat.com & Geotrait FriendService {def addOrUpdate(request : AddOrUpdateUserRequest)def findNearbyFriends(request : NearbyFriendsRequest) :FindNearbyFriendsResponse}trait RestaurantService {def findNearbyRestaurants(location: Location) :FindNearbyRestaurantResponse}
  38. 38. @crichardsontrait FriendService {def addOrUpdate(request : AddOrUpdateUserRequest)def findNearbyFriends(request : NearbyFriendsRequest) :FindNearbyFriendsResponse}Implementing the friendsdatabase
  39. 39. @crichardsonMongoDB• Document-oriented database• Very fast, highly scalable and available• Rich query language that supports location-based queries• Provided by CloudFoundry.com
  40. 40. @crichardsonMongoDB serverDatabase: VoteMeetEatCollection: friendRecordStoring friends in MongoDB{"_id": "+15105551212","name": "Chris R.","location": {"x": -122.25206103187264,"y": 37.847427441773796}}
  41. 41. @crichardsonSpring Data for MongoDB• Provides MongoTemplate• Analogous to JdbcTemplate• Hides boilerplate code• Domain object Document mapping
  42. 42. @crichardsonUsing Spring data: creating anindex on location attribute@Componentclass MongoFriendService extends FriendService {@Autowiredvar mongoTemplate: MongoTemplate = _@PostConstructdef createGeoIndex {val dbo = new BasicDBObjectdbo.put("location", "2d")mongoTemplate.getCollection("friendRecord").ensureIndex(dbo)}Create geospatial 2d indexCollection nameAttribute andindex type
  43. 43. @crichardsonUsing Spring Data: adding record@Componentclass MongoFriendService extends FriendService {override def addOrUpdate(request: AddOrUpdateUserRequest) = {val name = request.nameval phoneNumber = request.phoneNumberval fr = new FriendRecord(phoneNumber, name,new Point(request.longitude, request.latitude))mongoTemplate.save(fr)}case class FriendRecord(id : String,name : String,location : Point)
  44. 44. @crichardsonUsing Spring Data: finding nearbyfriends@Componentclass MongoFriendService extends FriendService {override def findNearbyFriends(request: NearbyFriendsRequest) = {val location = new Point(request.longitude, request.latitude)val distance = new Distance(3, Metrics.MILES)val query = NearQuery.near(location).maxDistance(distance)val result = mongoTemplate.geoNear(query, classOf[FriendRecord])val nearby = result.getContent.map(_.getContent)FindNearbyFriendsResponse(nearby.map(f => FriendInfo(f.name, f.id)))}
  45. 45. @crichardsonMongoDB and Cloud Foundry$ vmc create-service mongodb vme-mongo
  46. 46. @crichardson$ vmc push vme-user --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 vme-user? [yN]: yWould you like to use an existing provisioned service? [yN]: yThe following provisioned services are available1: vme-mongo2: mysql-135e0Please select one you wish to use: 1Binding Service [vme-mongo]: OKUploading Application:Checking for available resources: OKProcessing resources: OKPacking application: OKUploading (12K): OKPush Status: OKBinding a service to an applicationWould you like to bind any services to vme-user? [yN]: yWould you like to use an existing provisioned service? [yN]: yThe following provisioned services are available1: vme-mongo2: mysql-135e0Please select one you wish to use: 1Binding Service [vme-mongo]: OK
  47. 47. @crichardsonConnecting to MongoDB <bean id="mongoTemplate"class="org.springframework.data.mongodb.core.MongoTemplate"> <constructor-arg ref="mongoFactory" /> </bean> <beans profile="default"> <mongo:db-factory id="mongoFactory" dbname="surveygeo" /> </beans> <beans profile="cloud"> <cloud:mongo-db-factory id="mongoFactory" /> </beans>Outside of Cloud FoundryInside Cloud Foundry
  48. 48. @crichardsonImplementing the restaurantdatabasetrait RestaurantService {def findNearbyRestaurants(location: Location) :FindNearbyRestaurantResponse}
  49. 49. @crichardsonUsing Factual• Geographic database as a Service• Including 1.2M restaurants in the US• Pricing: 10K calls day free, pay per use
  50. 50. @crichardsonFactual API• RESTful/JSON interface• Uses 2-legged OAuth 1.0.• Geo and text filters• Pagination• Libraries for various languages
  51. 51. @crichardsonRestaurant Service@Serviceclass FactualRestaurantService extends RestaurantService {@Value("${factual_consumer_key}") var consumerKey: String = _@Value("${factual_consumer_secret}") var consumerSecret: String = _var factual: Factual = _@PostConstructdef initialize {factual = new Factual(consumerKey, consumerSecret, true)}override def findNearbyRestaurants(location: Location) = {...val restaurants = factual.get.fetch("restaurants-us",new Query().within(new Circle(location.lat, location.lon, 1000)).limit(5))val rs = restaurants.getData.map { map =>RestaurantInfo(map.get("name").asInstanceOf[String])}FindNearbyRestaurantResponse(rs.toList)}...5 restaurants within 1km
  52. 52. @crichardsonAgenda• Why use cloud services?• Developing location-based applications• Building SMS and telephony enabled applications• Developing robust, fault tolerant applications
  53. 53. @crichardsonThe telephony and SMS areimportanthttp://blog.nielsen.com/nielsenwire/online_mobile/new-mobile-obsession-u-s-teens-triple-data-usage/7/ waking hr !Nielsen
  54. 54. @crichardsonReporting traffic light problems in London
  55. 55. @crichardsonGoogle 2-Factor authentication
  56. 56. @crichardsonVoteMeetEat.com &Telephony• Handling registration SMS• Sending SMS notifying users to vote• Handling incoming voice call from voters:• Text-to-speech of restaurants options• Collecting digits entered via keypad• Sending SMS/Voice notifications of voting results
  57. 57. @crichardsonDIY telephony = Difficult• Difficult to setup and operate• Expensive• Complex SMS protocols• …Better to use SMS/Telephony-aaS:
  58. 58. @crichardsonTelephony/SMS - aaS• SMS• Inbound and outgoing calls• Recording and transcription• SMS• Inbound and outgoing calls• Recording and transcription• Twitter• IM
  59. 59. @crichardsonTwilio -Telephony and SMS as aservice• REST API• Allocate phone numbers• Make and receive phone calls• Send and receive SMS messages• Pay per use:• Phone calls - per-minute• SMS – per SMS sent or received• Phone number – per month• Examples• OpenVBX is a web-based, open source phone system• StubHub – notifies sellers of a pending sale via phone• SurveyMonkey – interactive polling• Salesforce – SMS-based voting for 19,000 conference attendees
  60. 60. @crichardsonUsingTwilioTwilio YourApplicationTwiML docHTTP GET/POSTREST APIManage resourcesSend SMSInitiate voice callsHandle incoming SMS and voice callsRespond to user inputVoiceSMSPhone numberSMS URL +VOICE URL
  61. 61. @crichardsonHandling SMS registration5551212Usertexts‘register’Systemreplies
  62. 62. @crichardsonHandling SMS registrationTwilioSMSREGISTRATIONHTTP POSThttp://≪smsUrl≫?From=≪PhoneNumber≫&Body=≪Message≫&...<Response><Sms>To complete registration pleasego to http://...</Sms></Response>SMS
  63. 63. @crichardsonHandling SMS registrationTwiML documentdescribing theresponse
  64. 64. @crichardsonInviting users to vote5551212555121255512125551212System sendstext
  65. 65. @crichardsonInviting users to votePOST /2010-04-01/Accounts/≪AccountSID≫/SMS/MessagesFrom=+15105551212&To=+14155551212&Body=≪MESSAGE≫Authorization: Basic ....Basic auth usingTwilioAccountSid+AuthToken
  66. 66. @crichardsonSending SMS using the SpringRestTemplate@Componentclass TwilioService { def sendSms(recipient : String, message : String) = { val response = postToTwilio("SMS/Messages", Map("From" -> twilioPhoneNumber, "To" -> recipient, "Body" -> message)) (response "SMSMessage" "Sid").text }
  67. 67. @crichardsonSending SMS using the SpringRestTemplate@Componentclass TwilioService {def postToTwilio(resourcePath : String, requestParams : Map[String, String]) = { val entity = makeEntity(requestParams) try { val response = restTemplate.postForObject(twilioUrl +"/Accounts/{accountSid}/{resource}", entity, classOf[String],accountSid, resourcePath) XML.loadString(response) } catch { case e : HttpClientErrorException if e.getStatusCode == HttpStatus.BAD_REQUEST => val body = e.getResponseBodyAsString() val xmlBody = XML.loadString(body) val code = Integer.parseInt((xmlBody "Code").text) val message = (xmlBody "Message").text throw new TwilioRestException(message, code) }}
  68. 68. @crichardsonVoting: user calls number555 1212
  69. 69. @crichardsonVotingTwilioSurvey Management<Response><Say> Chris would like to meet and eat. </Say><Gather action="handleresponse.html"method="POST" numDigits="1"><Say>Press 1 for ....</Say><Say>Press 2 for ....</Say></Gather></Response>HTTP POSThttp://≪voiceUrl≫?From=≪PhoneNumber≫Call
  70. 70. @crichardsonVotingTwilioSurvey Management<Response><Say>Thank you for choosing.The most popular place so far is ...</Say><Pause/><Say>You will hear from us soon. Good bye</Say><Hangup/></Response>HTTP POSThttp://....handleresponse.html?From=≪PhoneNumber≫&Digits=≪...≫Digits
  71. 71. @crichardsonVoting code 1@Controllerclass TwilioController {@Autowiredvar surveyManagementService: SurveyManagementService = _@RequestMapping(value = Array("/begincall.html"))@ResponseBodydef 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>}}
  72. 72. @crichardsonVoting code 2class TwilioController {...@RequestMapping(value = Array("/handleresponse.html"))@ResponseBodydef handleUserResponse(@RequestParam("From") callerId: String,@RequestParam("Digits") digits: Int) = {val survey = surveyManagementService.recordVote(callerId, digits)<Response><Say>Thank you for choosing. The most popular place so far is{ survey.map(_.mostPopularChoice) getOrElse "oops" }</Say><Pause/><Say>You will hear from us soon. Good bye</Say><Hangup/></Response>}}
  73. 73. @crichardsonAgenda• Why use cloud services?• Developing location-based applications• Building SMS and telephony enabled applications• Developing robust, fault tolerant applications
  74. 74. @crichardsonThe need for parallelismService AService BService CService Db = serviceB()c = serviceC()d = serviceD(b, c)Call in parallel
  75. 75. @crichardsonFutures are a great concurrencyabstraction• Object that will contain the result of a concurrent computation -http://en.wikipedia.org/wiki/Futures_and_promises• Various implementations• Java 7 Futures = ok• Guava ListenableFutures = better• Scala’s composable Futures = really good• Java 8 CompletableFuture = greatFuture<Integer> result =executorService.submit(new Callable<Integer>() {... });
  76. 76. @crichardsonUsing futures to parallelize requeststrait FriendService {def findNearbyFriends(request : NearbyFriendsRequest) :Future[FindNearbyFriendsResponse]}trait RestaurantService {def findNearbyRestaurants(location: Location) :Future[FindNearbyRestaurantResponse]}val f1 = friendsService.findNearbyFriends(NearbyFriendsRequest.fromLocation(vmeRecord.location))val f2 = restaurantService.findNearbyRestaurants(vmeRecord.location)val nearbyFriends = f1.get(2, TimeUnit.SECONDS)val nearbyRestaurants = f2.get(2, TimeUnit.SECONDS)Two calls execute concurrentlyClientSideProxies
  77. 77. @crichardsonUsing external web services =Distributed systemVoteMeetEatTwilioMongoDBFactual.ComMobilePhone
  78. 78. @crichardsonInternally = Distributed SystemSurveymanagementVMEmanagementRegistrationSMSRegistrationweb appVMEweb appUsermanagementRabbitMQ
  79. 79. @crichardsonHandling failureService A Service BErrors happenin distributed systems
  80. 80. @crichardsonAbout Netflixhttp://techblog.netflix.com/2012/02/fault-tolerance-in-high-volume.html> 1B API calls/day1 API call average 6 service callsFault tolerance is essential
  81. 81. @crichardsonHow to run out of threadsTomcatExecute threadpoolHTTP RequestThread 1Thread 2Thread 3Thread nService A Service BIf service B is downthen thread will beblockedXXXXXEventually all threadswill be blocked
  82. 82. @crichardsonTheir approach• Network timeouts and retries• Invoke remote services via a bounded thread pool• Use the Circuit Breaker pattern• On failure:• return default/cached data• return error to caller• https://github.com/Netflix/Hystrixhttp://techblog.netflix.com/2012/02/fault-tolerance-in-high-volume.html
  83. 83. @crichardson@Serviceclass FactualRestaurantService extends RestaurantService {@Autowired@Qualifier("factualHystrixConfig")var factualHystrixConfig: HystrixCommand.Setter = _override def findNearbyRestaurants(location: Location) = {class FindRestaurantsCommandextends HystrixCommand[FindNearbyRestaurantResponse](factualHystrixConfig.andCommandKey(HystrixCommandKey.Factory.asKey("FindRestaurantsCommand"))) {override def run() = {val restaurants = factual.fetch("restaurants",new Query().within(new Circle(location.lat, location.lon, 1000)).limit(5))val rs = for (map <- restaurants.getData) yield {RestaurantInfo(map.get("name").asInstanceOf[String])}FindNearbyRestaurantResponse(rs.toList)}}new FindRestaurantsCommand().queue()}}Using Hystrix
  84. 84. @crichardsonSummaryCloud services are highly scalable services developed andoperated by a 3rd partyLet’s you focus on your core business problemRisk: provider is acquired and stops offering serviceDeveloping an application that reliably consumes cloudservices requires careful design
  85. 85. @crichardsonQuestions?@crichardson chris.richardson@springsource.comhttp://plainoldobjects.com - code and slidesSign up for CloudFoundry.com

×