building a scalable web application by combining modern front-end stuff and azure services
TRANSCRIPT
Building a scalable web application by combining modern front-end stuff and Azure services
Chris Klug@ZeroKoll
http://[email protected]
Who am I?
I
”We need some help to build a morescalable solution than what we got”
- client
x 500.000
The application
Teachers Students Admin Gov AuthN
& Data
Challenge 1:
Authentication
Teachers
Students
Admin
Gov AuthN
?
Gov 2
Gov 3
Gov 4
Teachers
Students
Admin
Gov AuthNSTS
WS-Fe
dera
tion
Cust
om
Pro
toco
l
Challenge 2:
Data storage
admin.xyz.com teacher.xyz.com student.xyz.com
SQL
Ehhh…no…
admin teacher student
Master Shard 1 Shard 2 Shard n
Sub challenge 1:
Cross-shard queries
teacher
ShardsAzure Search
SQL vs Storage
admin teacher student
Master Shard Blob Storage
Search
admin teacher student
Master Shard Shard Master
Search
= +
Service Bus Worker Roles
teacher
1. M
ake C
han
ge
5. Transform Data
to JSON
Challenge 3:
The curveball
”You know how we said we wanted to host the solution in Azure…well…”
- client
”Our own private cloud is being built aswe speak, and it uses Azure Pack, so we’re all good!”
- client
Look ma, two ducks!!!
admin teacher student
Master Shard Shard Master
Clien
t’s
Data
cen
ter
Azu
re
+
Azure Pack
Worker Roles ≠ Microsoft Azure
Worker Roles
admin teacher student
Master Shard Shard Master
Clien
t’s
Data
cen
ter
Azu
re
+
Challenge 4:
Application structure
SQL
NHibernate
Domain
MVC Web Api
HTML, CSS, JS (AngularJS)
Blob StorageMVC Web Api
HTML, CSS, JS (AngularJS)
Unicorns
Sub challenge 1:
Bootstrapping the SPA
// In header of SPA HTML page
var app = {};
app.configuration = {
myServiceProviderConfig: {
value:’key’
}
};
// In module registration JavaScript file
angular.module(’myModule’,[’myOtherModule’])
.provider(’myService’, function() {
// implementation
})
.config([’myServiceProvider ’,function(myServiceProvider) {
myServiceProvider.configure(app.configuration.myServiceProviderConfig);
}]);
Sub challenge 2:
Handling SAS for storage
angular.module(’appModule’,[])
.service(’http’, [’$http’, function($http) {
// ”override” implementation to add and refresh SAS to requests
return {
get: function(path) {
var sas = getSas(); // cached or refreshed from server
var url = _baseUrl + path + ’?’ + sas;
return $http.get(url);
}
// more functions
};
}]);
angular.module(’clientModule’,[])
.service(’courseRepo’, [’http’, function(http)
{
return {
getCourseById: function(id) {
return http.get(’/course/’ + id);
}
// more functions
};
}]);
Challenge 5:
Front-end build pipeline
LESS CSS Bundle Minify
JS Test Bundle Minify
”That can be done using a custombuild task in our TFS build pipeline!”
- me
Sub challenge 1:
Development vs Production
Development
• Individual
JavaScript
files
• LESS +
less.js
UAT (Test)
• Bundled &
minified
JavaScripts
• Bundled &
minified
CSS
Production
• Bundled &
minified
JavaScripts
from CDN
• Bundled &
minified
CSS from
CDN
public static void RegisterBundles(BundleCollection bundles)
{
var scripts = new ScriptBundle("~/scripts", ResolveCdnPath("/scripts.min.js"));
scripts.IncludeDirectory("/scripts", "*.js");
bundles.Add(scripts);
var styles = new Bundle(”~/styles” , ResolveCdnPath("/styles.min.css"));
styles.IncludeDirectory("/styles"), "*.less");
bundles.Add(styles);
}
protected string ResolveCdnPath(string path)
{
if (!settings.UseCdn) return path;
return string.Format(”{0}{1}?v={2}", settings.CdnBaseUrl, path, settings.CdnFileVersion);
}
Bonus Challenge:
“The Overlay”
Youtube.comMySite.se
Homework.nu
Sub challenge 1:
Http vs Https
Sub challenge 2:
Cookies over Http
Sub challenge 3:
Hosting
Did we overdo it?
”It's not how far you go, it's how go you far”