Upload
edita
View
32
Download
0
Tags:
Embed Size (px)
DESCRIPTION
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 & - PowerPoint PPT Presentation
Citation preview
Mobile Services: Going Live and BeyondKirill Gavrylyuk, Lead Program ManagerPaul Batum, Program Manager3-511
REST
API
Data
Notifications
Auth
Server Logic
Scale
Scheduler
Diagnostics &Logging
Connected Apps
Windows StoreiOS
Android
Windows Phone 8iOS
AndroidHTML 5/JS
Dev&Test
Tune Perf
Go LiveMonitor
Version
Event BuddyDEMO
Source Control and Deployment
Local git repository
Mobile Services(git repository)
Team Foundation Service(git repository)
AutomationDEMO
Using ZumockScripts Unit TestingDEMO
Node.js Tools
.NET Node.js
NuGet <----> Node Package Manager (NPM)
NUnit / MS test / etc <----> Mocha
Keep scripts in source control (TFS) Use Git to deploy server scriptsAutomate using Azure CLITest scripts using mock frameworks
Dev & Test Summary
Dev&Test
Tune Perf
Go LiveMonitor
Version
Use SQL Database forrelational datarich query, sorting, filtering, multiple indexes
Use Table forkey-value pair tuples (e.g. game state)simple queries, basic or no filtering
SQL Database vs Table
Table Storage with Custom APIsexports.get = function (request, response) {
var azure = require('azure');
var tableService = azure.createTableService(‘session', '<your storage key>');
var query = azure.TableQuery.select().from(‘session').where(‘eventId eq ?‘, eventId);
tableService.queryEntities(query, function (error, todoitems) {
if (!error) {
response.send(200, todoitems);
} else { /* … */}
});
};
Working with images / blobsBlob Storage
Mobile Service
1
2
34 1. Request a blob url
2. Request a SAS token3. Send back a blob url4. Post a blob
Blob Storage SAS function insert(item, user, request) {
var azure = require('azure');
var blobService = azure.createBlobService('<account-name>', 'account-key>');
blobService.createContainerIfNotExists(item.containerName,
accessLevel, function (error) {
if (error) { return errorHandler(error); }
var sharedAccessPolicy = {Permissions : /* ... */, Expiry : /* ... */};
var sasQueryUrl = blobService.generateSharedAccessSignature(item.containerName,
item.resourceName, sharedAccessPolicy);
item.imageUri = sasQueryUrl.baseUrl + sasQueryUrl.path;
request.execute();
});
}
DO NOT use compute intense scriptsfunction insert(item, user, request) {
//...
images.forEach(function (image) {
var png = easyimg.jpg2png(image, quality:10};
//...
}
USE SQL where appropriatepostTable.where({id : commment.postId}).read( { success : pushToUsers });
//…
function pushToUsers(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 var sql = "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 parallelvar sql = "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” } );
});
}
• Use Notification Hubs
• Split the work into batches and process in the background
AVOID client side JOINs IEnumerable<Session> sessions;
Events = await App.MobileService.GetTable<Event>()
.Where(e => e.Start > DateTime.Now)
.ToEnumerableAsync();
foreach (var e in Events)
{
sessions = await App.MobileService
.GetTable<Session>()
.ToEnumerableAsync();
/*....*/
}
IEnumerable<Session> sessions;
Events = await App.MobileService
.GetTable<Session>()
.Where(e => s.Start > DateTime.Now)
.ToEnumerableAsync();
/*....*/
//JOIN in server scripts:
var sql = "SELECT * FROM sessions " +
"INNER JOIN events ON events.date > ?";
mssql.query(sql, [startDate], {
/*....*/
}
LOTS OF API
CALLS
Choose the right data storeUse Blob Storage for binary blobsAVOID 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
Perf tuning tips
Dev&Test
Tune Perf
Go LiveMonitor
Version
Mobile Services Tierspricing & licensing $ service level
agreementsGeneral Availability99.9%
Free Standard Premium
Price FreeUp to 10 services,Up to 100 Active
Devices**
$25 USD/mo(per unit**)
$199 USD/mo(per unit**)
API Calls 500K (per subscription)
1.5M(per unit)
15M(per unit)
Scale N/A Up to 6 Standard units
Up to 10 Enterprise units
Min Burstper instance
10 RPS 100 RPS
SQL Database (required)
20MB Included, Standard rates apply
for more capacity
20MB Included, Standard rates apply
for more capacity
20MB Included, Standard rates apply
for more capacity
*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.
Choose the right TierDisable Dynamic SchemaEnsure Auth is ON, use SSLLock permissionsSetup dev / test environmentsThink versioning
Go Live!
Dev&Test
Tune Perf
Go LiveMonitor
Version
Creating & Configuring AlertsDEMO
Monitor your app with New RelicDEMO
Availability monitoring / alertsBetter with partners: New Relic
Monitoring & Troubleshooting
Dev&Test
Tune Perf
Go LiveMonitor
Version
Add version to your Mobile Services clientpublic class VersioningHandler : DelegatingHandler{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken
cancellationToken) {
request.RequestUri = new Uri(request.RequestUri.AbsoluteUri.ToString() + “?version=2.0"); return base.SendAsync(request, cancellationToken); }}
public static MobileServiceClient MobileService = new MobileServiceClient(
"https://eventbuddykg.azure-mobile.net/",
"lLsNsvgOmQBfUGOHgKkIgnFwblJpla63",
new VersioningHandler()
);
Add version to your scriptsfunction insert(item, user, request) {
if (request.parameters.version < 2.0) {
session.room = 'Not entered';
}
request.execute({
success: function () {
if (request.parameters.version < 2.0) {
delete session.room;
}
request.respond();
}
});
}
DEMOPrepare for breaking changes
Include client version in requestsHandle version differences in scriptsPlan your upgrade strategy
Versioning Considerations
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
Summary
Mobile Services at BuildMobile Services – Soup to NutsJosh Twist – Thursday 2pm
Protips for Mobile ServicesChris Risner – Thursday 5pm
Cross-Platform w/ Mobile ServicesChris Risner – Thursday 4pm
Connected Win Phone AppsYavor Georgiev – Friday 9am
Going Live and BeyondKirill and Paul – Friday 10:30am
Delivering Push Notifications to MillionsElio Demaggio – Friday 12pm
Who’s that user?Dinesh Kulkarni – Friday 2pm
Developing Windows AppsNick Harris – Friday 2pm
ResourcesGet 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/
Evaluate this session
Scan this QR code to evaluate this session and be automatically entered in a drawing to win a prize!
© 2013 Microsoft Corporation. All rights reserved. Microsoft, Windows, Windows Vista and other product names are or may be registered trademarks and/or trademarks in the U.S. and/or other countries.The information herein is for informational purposes only and represents the current view of Microsoft Corporation as of the date of this presentation. Because Microsoft must respond to changing market conditions, it should not be interpreted to be a commitment on the part of Microsoft, and Microsoft cannot guarantee the accuracy of any information provided after the date of this presentation. MICROSOFT MAKES NO WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, AS TO THE INFORMATION IN THIS PRESENTATION.