windows_azure_-_multitenant

advertisement
1
Windows Azure
Multi-tenant applicatie
Bouwen van een multi-tenant applicatie in de praktijk
Edo van Asseldonk
Ordina Microsoft Solutions
Agenda
• Introductie / Architectuur
• URL strategie / Tenant id
• Data opslag (SQL Azure, Table Storage)
• Maatwerk (UI / Business Logica)
• Cache
• Access Control Service
3
Multitenancy
Definitie
4
Multitenancy
Definitie
…single instance of software serving multiple clients (tenants)…
…een enkele softwareinstantie die meerdere klanten bedient…
5
Multitenancy
Definitie
6
Multitenancy
Definitie
7
Multitenancy
Definitie
Iedere tenant heeft:
• eigen data
• eigen opmaak
• eigen business logic
• gemeenschappelijke codebase
• gemeenschappelijk datamodel
8
Architectuur
Overview
Casus / Demo
9
Architectuur
Overview
10
Table Storage
ACS
Webrole
SQL Azure
Architectuur
Overview
11
Table Storage
ACS
Webrole
SQL Azure
Architectuur
Overview
Eisen:
• Tenantapplicatie bereikbaar via eigen url
• Eén database schema
• Eigen stijl per tenant
• Self service
• Share everything
12
URL Strategie / Tenant id
URL Strategie / Tenant id
Opties
14
Optie 1: Tenant bepalen a.d.h.v. ingelogde gebruiker
http://www.MyMultitenantApp.nl/Home
Geen referentie naar naam van tenant
URL Strategie / Tenant id
Opties
https://www.chatter.com/nl/
15
URL Strategie / Tenant id
Opties
https://eu1.salesforce.com/home/home.jsp
16
URL Strategie / Tenant id
Opties
17
Optie 2: TenantId in URL
http://www.MyTenantApp.nl/Home?tenantId=17
http://www.MyTenantApp.nl/17/Home
http://www.MyTenantApp.nl/A219F47cd-898B/Home
http://www.MyTenantApp.nl/WazugNL/Home
URL Strategie / Tenant id
Opties
Optie 3: Tenant bepalen a.d.h.v. URL
http://tenant1.MyTenantApp.nl/Home
http://tenant2.MyTenantApp.nl/Home
18
URL Strategie / Tenant id
Opties
Optie 3: Tenant bepalen a.d.h.v. URL
http://tenant1.MyTenantApp.nl/Home
http://tenant2.MyTenantApp.nl/Home
http://www.customdomain.nl/
-> verwijst naar http://tenant2.MyTenantApp.nl
19
URL Strategie / Tenant id
Opties
http://gaming.stackexchange.com/
20
URL Strategie / Tenant id
Opties
http://programmers.stackexchange.com/
21
URL Strategie / Tenant id
Opties
http://www.stackoverflow.com/
22
URL Strategie
In Windows Azure
[MyMultitenantApp].cloudapp.net
23
URL Strategie
In Windows Azure
[MyMultitenantApp].cloudapp.net
[Tenant].cloudapp.net
[Tenant].[MyMultitenantApp].cloudapp.net
24
URL Strategie
In Windows Azure
[MyMultitenantApp].cloudapp.net
Domain name: MyMultitenantApp.nl
25
URL Strategie
In Windows Azure
[MyMultitenantApp].cloudapp.net
Domain name: MyMultitenantApp.nl
URLs:
http://tenant1.MyMultitenantApp.nl
http://tenant2.MyMultitenantApp.nl
http://www.customdomain.nl
26
Data
Database
Database
Introductie
Alle tenants in dezelfde database
Twee issues:
• Limiet aan databasegrootte
• Limiet aan verwerkingscapaciteit (CPU, I/O etc.)
28
Database
Introductie
Oplossing:
• Database splitsen
29
Database
Introductie
Oplossing:
• Database splitsen -> SQL Azure Federations
30
Database
Introductie
Database
Introductie
Database
Introductie
Database
Introductie
Database
Introductie
Database
Introductie
Database
Introductie
Database
Introductie
Database
Introductie
Database
Introductie
Database
Introductie
Database
Introductie
Database
Introductie
Database
Introductie
SQL Azure Federations
Root database
Root DB
Root
Table1
Root
Table2
Root
Table…
45
SQL Azure Federations
Create federation
Root DB
Root
Table1
Root
Table2
Root
Table…
46
Member DB
SQL Azure Federations
Create tables
Root DB
Root
Table1
Root
Table2
Root
Table…
47
Member DB
Member
Table2
Member
Table1
Member
Table…
SQL Azure Federations
Split federation member
Root DB
Root
Table1
Root
Table2
Root
Table…
48
Member DB
Member
Table1
Member
Table2
Member
Table…
SQL Azure Federations
Split federation member
Root DB
Root
Table1
Root
Table2
Root
Table…
49
Member DB
Member
Table1
Member
Table2
Member
Table…
SQL Azure Federations
Split federation member
50
Member DB
Member
Table1
Root DB
Root
Table1
Root
Table2
Root
Table…
Member DB
Member
Table1
Member
Table2
Member
Table…
Member
Table2
Member
Table…
Member DB
Member
Table1
Member
Table2
Member
Table…
SQL Azure Federations
Split federation member
51
Member DB
Member
Table1
Root DB
Root
Table1
Member
Table2
Member
Table…
Root
Table2
Root
Table…
Member DB
Member
Table1
Member
Table2
Member
Table…
SQL Azure Federations
Voordelen
• DB Size van max 150 GB -> 75 TB
• CPU Cores en I/O verveelvoudigd
• Real-time
• Geen downtime
52
SQL Azure Federations
Voordelen
• DB Size van max 150 GB -> 75 TB
• CPU Cores en I/O verveelvoudigd
• Real-time
• Geen downtime
53
SQL Azure Federations
Voordelen
• DB Size van max 150 GB -> 75 TB
• CPU Cores en I/O verveelvoudigd
• Real-time
• Geen downtime
54
SQL Azure Federations
Voordelen
• DB Size van max 150 GB -> 75 TB
• CPU Cores en I/O verveelvoudigd
• Real-time
• Geen downtime
55
SQL Azure Federations
Kosten
56
Sinds halverwege februari 2012 prijsverlaging.
Tot 78% goedkoper.
Hoe meer tenants per member database, hoe goedkoper.
Eén database
Meerdere databases
FORMAAT
KOSTEN
FORMAAT
KOSTEN
10 GB
$45,95 p/m
10 x 1 GB
10 x $9.99 = $99,90 p/m
SQL Azure Federations
Kosten
57
Sinds halverwege februari 2012 prijsverlaging.
Tot 78% goedkoper.
Hoe meer tenants per member database, hoe goedkoper.
Eén database
Meerdere databases
FORMAAT
KOSTEN
FORMAAT
KOSTEN
10 GB
$45,95 p/m
10 x 1 GB
10 x $9.99 = $99,90 p/m
50 GB
$125,88 p/m
10 x 5 GB
$259,80 p/m
SQL Azure Federations
Kosten
58
Sinds halverwege februari 2012 prijsverlaging.
Tot 78% goedkoper.
Hoe meer tenants per member database, hoe goedkoper.
Eén database
Meerdere databases
FORMAAT
KOSTEN
FORMAAT
KOSTEN
10 GB
$45,95 p/m
10 x 1 GB
10 x $9.99 = $99,90 p/m
50 GB
$125,88 p/m
10 x 5 GB
$259,80 p/m
50 GB
$125,88 p/m
50 x 1 GB
$499,50 p/m
SQL Azure Federations
Kosten
59
Sinds halverwege februari 2012 prijsverlaging.
Tot 78% goedkoper.
Hoe meer tenants per member database, hoe goedkoper.
Eén database
Meerdere databases
FORMAAT
KOSTEN
FORMAAT
KOSTEN
10 GB
$45,95 p/m
10 x 1 GB
10 x $9.99 = $99,90 p/m
50 GB
$125,88 p/m
10 x 5 GB
$259,80 p/m
50 GB
$125,88 p/m
50 x 1 GB
$499,50 p/m
150 GB
$225,78 p/m
150 x 1 GB
$1498,50 p/m
SQL Azure Federations
Samenwerking met Entity Framework
var
query
= from o in _myDatabaseContext.Orders
string
federationCmdText
=
where o.TenantId
= id
"USE FEDERATION
tenant_federation
(tenantId = [id])
select o;
WITH FILTERING=ON, RESET";
((IObjectContextAdapter)myDatabaseContext).ObjectContext.Connection.Open();
_databaseContext.Database.ExecuteSqlCommand(federationCmdText);
60
SQL Azure Federations
Geen Federations in SQL Server 2008R2
string federationCmdText =
"USE FEDERATION tenant_federation (tenantId = [id])
WITH FILTERING=ON, RESET";
((IObjectContextAdapter)myDatabaseContext).ObjectContext.Connection.Open();
_databaseContext.Database.ExecuteSqlCommand(federationCmdText);
var query = from o in _myDatabaseContext.Orders
where o.TenantId = id
select o;
61
SQL Azure Federations
Geen where-clause nodig in gefilterde verbinding
string federationCmdText =
"USE FEDERATION tenant_federation (tenantId = [id])
WITH FILTERING=ON, RESET";
((IObjectContextAdapter)myDatabaseContext).ObjectContext.Connection.Open();
_databaseContext.Database.ExecuteSqlCommand(federationCmdText);
var query = from o in _myDatabaseContext.Orders
where o.TenantId = id
select o;
62
SQL Azure Federations
Entity Framework: geen support parallelle queries
63
Architectuur
Overview - > Table Storage
64
Table Storage
ACS
Webrole
SQL Azure
Table storage
Meten en Afrekenen
Afrekenen op basis van verbruik
(aantal page requests, aantal objecten etc.)
Verbruik inzichtelijk maken voor tenants
Statcounter.com is niet geschikt voor multitenancy
65
Maatwerk
Maatwerk
Maatwerk per tenant op twee gebieden:
• User Interface
• Business Logic
67
Maatwerk
User Interface
Tenant-logo
<div id="header">
<a href="/" class="logo" style="background: url(@ViewBag.Logo) no-repeat;">
68
Maatwerk
User Interface
Tenant-logo
<div id="header">
<a href="/" class="logo" style="background: url(@ViewBag.Logo) no-repeat;">
Niet doen op deze manier:
Kleuren
Fonts
Posities van html-elementen
Etc.
69
Maatwerk
User Interface - Themes
70
Maatwerk
User Interface - Themes
71
Maatwerk
User Interface - Themes
72
public class ThemesViewEngine : BuildManagerViewEngine
{
private readonly string _themeName;
public ThemesViewEngine(string themeName)
{
_themeName = themeName;
}
protected override IView CreateView(
ControllerContext controllerContext,
string viewPath,
string masterPath)
{
masterPath =
string.Format("~/Themes/{0}/_Layout.cshtml", _themeName);
return new RazorView(controllerContext, viewPath, masterPath, …);
}
Maatwerk
User Interface - Themes
73
public class ThemesViewEngine : BuildManagerViewEngine
{
private readonly string _themeName;
public ThemesViewEngine(string themeName)
{
_themeName = themeName;
}
protected override IView CreateView(
ControllerContext controllerContext,
string viewPath,
string masterPath)
{
masterPath =
string.Format("~/Themes/{0}/_Layout.cshtml", _themeName);
return new RazorView(controllerContext, viewPath, masterPath, …);
}
Maatwerk
User Interface - Themes
74
public class ThemesViewEngine : BuildManagerViewEngine
{
private readonly string _themeName;
public ThemesViewEngine(string themeName)
{
_themeName = themeName;
}
protected override IView CreateView(
ControllerContext controllerContext,
string viewPath,
string masterPath)
{
masterPath =
string.Format("~/Themes/{0}/_Layout.cshtml", _themeName);
return new RazorView(controllerContext, viewPath, masterPath, …);
}
Maatwerk
User Interface - Themes
75
public class ThemesViewEngine : BuildManagerViewEngine
{
private readonly string _themeName;
public ThemesViewEngine(string themeName)
{
_themeName = themeName;
}
protected override IView CreateView(
ControllerContext controllerContext,
string viewPath,
string masterPath)
{
masterPath =
string.Format("~/Themes/{0}/_Layout.cshtml", _themeName);
return new RazorView(controllerContext, viewPath, masterPath, …);
}
Maatwerk
User Interface - Themes
76
public class UseThemesViewEngine : ActionFilterAttribute
{
public ITenantSettings Settings { get; set; }
public override void OnActionExecuting(
ActionExecutingContext context)
{
ViewEngines.Engines.Clear();
var engine = new ThemesViewEngine(Settings.ThemeName);
ViewEngines.Engines.Add(engine));
}
}
Maatwerk
User Interface - Themes
77
public class UseThemesViewEngine : ActionFilterAttribute
{
public ITenantSettings Settings { get; set; }
public override void OnActionExecuting(…)
{
ViewEngines.Engines.Clear();
var engine = new ThemesViewEngine(Settings.ThemeName);
ViewEngines.Engines.Add(engine));
}
}
Maatwerk
User Interface - Themes
Public class HomeController : Controller
{
[UseThemesViewEngine]
public ActionResult Index()
{
}
}
78
Maatwerk
User Interface - Themes
79
public class UseThemesViewEngine : ActionFilterAttribute
{
public ITenantSettings Settings { get; set; }
public override void OnActionExecuting(
ActionExecutingContext context)
{
ViewEngines.Engines.Clear();
var engine = new ThemesViewEngine(Settings.ThemeName);
ViewEngines.Engines.Add(engine));
}
}
Maatwerk
Maatwerk per tenant op twee gebieden:
• User Interface
• Business Logic
80
Maatwerk
Business Logic
81
Probleem
• Tenant settings moeten continue doorgegeven worden
• If-statements en switch-statements door alle code verweven
Maatwerk
Business Logic
var data =
Foo.Bar(TenantSettings)
MVC Controller
82
TenantSettings
If(settings.IsGoldPartner)
…
else
…
Business Logic layer
Maatwerk
Business Logic
var data =
Foo.Bar(TenantSettings)
MVC Controller
83
TenantSettings
If(settings.IsGoldPartner)
…
else
…
Business Logic layer
Maatwerk
Business Logic
var data =
BLL.GetData(TenantId)
MVC Controller
84
TenantId
return
DA.GetData(TenantId)
Business Logic layer
TenantId
from t in table
where tenantid == TenantId
TenantId
select t
Data Access
select * from table
where tenantid = TenantId
Database
Maatwerk
Business Logic
var data =
BLL.GetData(TenantId)
MVC Controller
85
TenantId
return
DA.GetData(TenantId)
Business Logic layer
TenantId
from t in table
where tenantid == TenantId
TenantId
select t
Data Access
select * from table
where tenantid = TenantId
Database
Maatwerk
Business Logic
public class BusinessLogic
{
public void DoeIets(string messageText)
{
var message = CreateMessage(messageText);
var tenantSettings = TenantSettingsHelper.GetSettings();
if(tenantSettings.UseSpamFilter)
{
if(tenantSettings.SpamFilterType == Fast)
{
spamfilter = new FastSpamfilter().Execute(message);
}
else if(TenantSettings.SpamFilterType == Slow)
{
spamfilter = new SlowSpamfilter().Execute(message);
}
}
SaveMessage(message);
}
86
Maatwerk
Business Logic
IoC container (autofac):
builder.Register(c => NewSpamfilter())
.As<ISpamfilter>;
private Ispamfilter NewSpamfilter()
{
if(!TenantSettings.UseSpamFilter)
return new NoSpamfilter();
if(TenantSettings.SpamFilterType == Fast)
return new FastSpamfilter();
else if(TenantSettings.SpamFilterType == Slow)
return new SlowSpamfilter();
87
Maatwerk
Business Logic
public class BusinessLogic
{
ISpamfilter _spamfilter;
public Messenger(ISpamfilter spamfilter)
{
_spamfilter = spamfilter
}
public void DoeIets(string messageText)
{
var message = CreateMessage(messageText);
_spamfilter.Execute(message);
SaveMessage(message);
}
88
Cache
89
App Fabric Cache doet de basics
Wissen van totale cache niet mogelijk
Cache
Geen persistentie
Geen inzicht in bytes per tenant
Versienummer in cachekey:
Bijvoorbeeld [tenantId]_[objecttype]_[versienr]_[objectId]
2ED669F2-9EBC-4248-8BE2-56CDFDA89B75_employee_v1.1_924F32EA-7793-46C1-986E-69FF0857F39C
2ED669F2-9EBC-4248-8BE2-56CDFDA89B75_employee_v1.2_924F32EA-7793-46C1-986E-69FF0857F39C
Cache
•
•
•
•
App Fabric Cache doet de basics, maar niet meer dan dat.
Wissen van totale cache niet mogelijk.
Geen persistentie.
Geen inzicht in bytes per tenant.
Versienummer in cachekey:
Bijvoorbeeld [tenantId]_[objecttype]_[versienr]_[objectId]
90
Access Control Service
Access Control
91
Access Control Service
Intro
92
Iedere tenant -> Relying Party Application in ACS
Management Service (beschikbaar als Odata Service)
Geen gebruikcijfers
Access Control Service
AudienceMode
Na inloggen stuurt ACS een token naar de website.
Check (url in token == AllowedAudienceUri)
Uitzetten!
<microsoft.identityModel>
<service>
<audienceUris mode="Never">
93
Contact
Bereikbaar voor vragen
Edo van Asseldonk
Email: [email protected]
Twitter: @edovanasseldonk
Blog: http://edo-van-asseldonk.blogspot.com
94
95
www.ordina.nl
Download