• 380 likes • 495 Views
Mobile Services: Going Live and Beyond. Kirill Gavrylyuk, Lead Program Manager Paul Batum, Program Manager 3-511. Connected Apps Windows Store iOS Android Windows Phone 8 iOS Android HTML 5/JS. Notifications. Auth. Data. Scheduler. REST API. Server Logic. Scale. Diagnostics &
E N D
Mobile Services: Going Live and Beyond Kirill Gavrylyuk, Lead Program Manager Paul Batum, Program Manager 3-511
Connected Apps Windows Store iOS Android Windows Phone 8 iOS Android HTML 5/JS Notifications Auth Data Scheduler REST API Server Logic Scale Diagnostics & Logging
DEMO Event Buddy
Source Control and Deployment Mobile Services (git repository) Team Foundation Service (git repository) Local git repository
DEMO Automation
DEMO Scripts Unit Testing Using Zumock
Dev & Test Summary • Keep scripts in source control (TFS) • Use Git to deploy server scripts • Automate using Azure CLI • Test scripts using mock frameworks
SQL Database vs Table • Use SQL Database for • relational data • rich query, sorting, filtering, multiple indexes • Use Table for • key-value pair tuples (e.g. game state) • simple queries, basic or no filtering
Table Storage with Custom APIs • exports.get = function (request, response) { • varazure = require('azure'); • vartableService = azure.createTableService(‘session', '<your storage key>'); • varquery = azure.TableQuery.select().from(‘session').where(‘eventIdeq?‘, eventId); • tableService.queryEntities(query, function (error, todoitems) { • if(!error) { • response.send(200, todoitems); • } else { /* … */} • }); • };
Working with images / blobs Blob Storage Mobile Service 2 3 1 4 • Request a blob url • Request a SAS token • Send back a blob url • Post a blob
Blob Storage SAS • function insert(item, user, request) { • varazure = require('azure'); • varblobService = azure.createBlobService('<account-name>', 'account-key>'); • blobService.createContainerIfNotExists(item.containerName, • accessLevel, function (error) { • if(error) { returnerrorHandler(error); } • varsharedAccessPolicy = {Permissions : /* ... */, Expiry : /* ... */}; • varsasQueryUrl = blobService.generateSharedAccessSignature(item.containerName, • item.resourceName, sharedAccessPolicy); • item.imageUri = sasQueryUrl.baseUrl + sasQueryUrl.path; • request.execute(); • }); • }
DO NOT use compute intense scripts • function insert(item, user, request) { • //... • images.forEach(function (image) { • varpng = easyimg.jpg2png(image, quality:10}; • //... • }
USE SQL where appropriate • postTable.where({id : commment.postId}).read( { success : pushToUsers }); • //… • functionpushToUsers(users) { • users.forEach(function (userId) { • channelTable.where(userId : userId).read({ • success: function(channels) { • channels.forEach(function(channel) { • push.wns.sendToastText04(channel.uri, {text1: item.text } ); • }); • } • }); • }); • } JOINS BETTER IN SQL
USE SQL where appropriate • varsql = "SELECT channel FROM devices " + • "INNER JOIN posts ON devices.userId = posts.userId " + • "WHERE posts.id = ?"; • mssql.query(sql, [comment.postId], { • success: function(channels) { • channels.forEach(function(channel) { • push.wns.sendToastText04(channel.uri, {text1: item.text } ); • }); • }
AVOID doing 1000s requests in parallel • Use Notification Hubs • Split the work into batches and process in the background • varsql = "SELECT channel FROM devices " + • "INNER JOIN users ON "; // TO DO: query users in SF • mssql.query(sql, [geofences.SF], { • success: function(channels) { • channels.forEach(function(channel) { • push.wns.sendToastText04(channel.uri, • {text1: “New Coffee” } ); • }); • }
AVOID client side JOINs • IEnumerable<Session> sessions; • Events = awaitApp.MobileService.GetTable<Event>() • .Where(e => e.Start > DateTime.Now) • .ToEnumerableAsync(); • foreach (var e in Events) • { • sessions = awaitApp.MobileService • .GetTable<Session>() • .ToEnumerableAsync(); • /*....*/ • } IEnumerable<Session> sessions; Events = awaitApp.MobileService .GetTable<Session>() .Where(e => s.Start > DateTime.Now) .ToEnumerableAsync(); /*....*/ LOTS OF API CALLS //JOIN in server scripts: varsql = "SELECT * FROM sessions " + "INNER JOIN events ON events.date > ?"; mssql.query(sql, [startDate], { /*....*/ }
Perf tuning tips • Choose the right data store • Use Blob Storage for binary blobs • AVOID compute-intense scripts • USE MSSQL when SQL is best • AVOID 1000s requests in parallel • USE client-server communication efficiently • DO NOT join tables on the client • DO batch updates as appropriate
Mobile Services Tiers service level agreements pricing & licensing $ General Availability99.9% *prorated daily **Active devices refers to the number of unique devices that have both obtained your Mobile Services powered app from a public app store and have made at least one call to your mobile service over the past 30 days.
Go Live! • Choose the right Tier • Disable Dynamic Schema • Ensure Auth is ON, use SSL • Lock permissions • Setup dev/ test environments • Think versioning
DEMO Creating & Configuring Alerts
DEMO Monitor your app with New Relic
Monitoring & Troubleshooting • Availability monitoring / alerts • Better with partners: New Relic
Add version to your Mobile Services client • publicclassVersioningHandler : DelegatingHandler{ • protectedoverride Task<HttpResponseMessage> SendAsync(HttpRequestMessagerequest, CancellationTokencancellationToken) { • request.RequestUri = newUri(request.RequestUri.AbsoluteUri.ToString() + “?version=2.0"); • returnbase.SendAsync(request, cancellationToken); }} • publicstaticMobileServiceClientMobileService = newMobileServiceClient( • "https://eventbuddykg.azure-mobile.net/", • "lLsNsvgOmQBfUGOHgKkIgnFwblJpla63", • newVersioningHandler() • );
Add version to your scripts • function insert(item, user, request) { • if (request.parameters.version < 2.0) { • session.room = 'Not entered'; • } • request.execute({ • success: function () { • if (request.parameters.version < 2.0) { • deletesession.room; • } • request.respond(); • } • }); • }
Prepare for breaking changes • DEMO
Versioning Considerations • Include client version in requests • Handle version differences in scripts • Plan your upgrade strategy
Summary • Use source control for server scripts • Automate using CLI & PowerShell • Unit test using mock frameworks • Be efficient about network and server scripts • Pick the appropriate tier • Think about versioning upfront
Mobile Services at Build Mobile Services – Soup to Nuts Josh Twist – Thursday 2pm Cross-Platform w/ Mobile Services Chris Risner – Thursday 4pm Protips for Mobile Services Chris Risner – Thursday 5pm Connected Win Phone Apps YavorGeorgiev – Friday 9am Going Live and Beyond Kirill and Paul – Friday 10:30am Delivering Push Notifications to Millions ElioDemaggio – Friday 12pm Who’s that user? Dinesh Kulkarni – Friday 2pm Developing Windows Apps Nick Harris – Friday 2pm
Resources • Get started with Mobile Services: • http://www.windowsazure.com/en-us/develop/mobile/ • Get started with the Azure CLI: • http://www.windowsazure.com/en-us/develop/nodejs/how-to-guides/command-line-tools/ • Copying a SQL Azure Database: • http://msdn.microsoft.com/en-us/library/windowsazure/ff951631.aspx • Setting up New Relic: • http://blog.newrelic.com/
Required Slide *delete this box when your slide is finalized Your MS Tag will be inserted here during the final scrub. Evaluate this session • Scan this QR codeto evaluate this session and be automatically entered in a drawing to win a prize!