380 likes | 498 Vues
Join Kirill Gavrylyuk and Paul Batum as they explore advanced mobile services deployment techniques that go beyond just going live. This session covers best practices for managing connected applications across iOS, Android, and Windows platforms using Azure Mobile Services. You’ll learn how to ensure efficient data management, perform unit testing, and automate deployment scripts with Git and Azure CLI. Enhance your knowledge of working with SQL and Blob Storage, optimize APIs for performance, and streamline backend processes for a scalable mobile service environment.
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!