Download de presentatie
De presentatie wordt gedownload. Even geduld aub
GepubliceerdBruno Verbeke Laatst gewijzigd meer dan 9 jaar geleden
1
Windows Azure Multi-tenant applicatie Bouwen van een multi-tenant applicatie in de praktijk 1
2
Edo van Asseldonk Ordina Microsoft Solutions
3
3 Agenda Introductie / Architectuur URL strategie / Tenant id Data opslag (SQL Azure, Table Storage) Maatwerk (UI / Business Logica) Cache Access Control Service
4
4 Multitenancy Definitie
5
5 …single instance of software serving multiple clients (tenants)… …een enkele softwareinstantie die meerdere klanten bedient…
6
6 Multitenancy Definitie
7
7
8
8 Iedere tenant heeft: eigen data eigen opmaak eigen business logic gemeenschappelijke codebase gemeenschappelijk datamodel Iedere tenant heeft: eigen data eigen opmaak eigen business logic gemeenschappelijke codebase gemeenschappelijk datamodel
9
9 Architectuur Overview Casus / Demo
10
10 Architectuur Overview Webrole SQL Azure Table Storage ACS
11
11 Architectuur Overview Webrole SQL Azure Table Storage ACS
12
12 Architectuur Overview Eisen: Tenantapplicatie bereikbaar via eigen url Eén database schema Eigen stijl per tenant Self service Share everything
13
URL Strategie / Tenant id
14
14 URL Strategie / Tenant id Opties Optie 1: Tenant bepalen a.d.h.v. ingelogde gebruiker http://www.MyMultitenantApp.nl/Home Geen referentie naar naam van tenant
15
15 URL Strategie / Tenant id Opties https://www.chatter.com/nl/
16
16 URL Strategie / Tenant id Opties https://eu1.salesforce.com/home/home.jsp
17
17 URL Strategie / Tenant id Opties 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
18
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
19
19 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
20
20 URL Strategie / Tenant id Opties http://gaming.stackexchange.com/
21
21 URL Strategie / Tenant id Opties http://programmers.stackexchange.com/
22
22 URL Strategie / Tenant id Opties http://www.stackoverflow.com/
23
23 URL Strategie In Windows Azure [MyMultitenantApp].cloudapp.net
24
24 URL Strategie In Windows Azure [MyMultitenantApp].cloudapp.net [Tenant].cloudapp.net [Tenant].[MyMultitenantApp].cloudapp.net
25
25 URL Strategie In Windows Azure [MyMultitenantApp].cloudapp.net Domain name: MyMultitenantApp.nl
26
26 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
27
Data Database
28
28 Database Introductie Alle tenants in dezelfde database Twee issues: Limiet aan databasegrootte Limiet aan verwerkingscapaciteit (CPU, I/O etc.)
29
29 Database Introductie Oplossing: Database splitsen
30
30 Database Introductie Oplossing: Database splitsen -> SQL Azure Federations
31
Database Introductie
45
45 SQL Azure Federations Root database Root DB Root Table1 Root Table2 Root Table…
46
46 SQL Azure Federations Create federation Member DBRoot DB Root Table1 Root Table2 Root Table…
47
47 SQL Azure Federations Create tables Member DBRoot DB Root Table1 Root Table2 Root Table… Member Table1 Member Table2 Member Table…
48
48 SQL Azure Federations Split federation member Member DB Root DB Root Table1 Root Table2 Root Table… Member Table1 Member Table2 Member Table…
49
49 SQL Azure Federations Split federation member Member DB Root DB Root Table1 Root Table2 Root Table… Member Table1 Member Table2 Member Table…
50
50 SQL Azure Federations Split federation member Member DB Root DB Root Table1 Root Table2 Root Table… Member Table1 Member Table2 Member Table… Member DB Member Table1 Member Table2 Member Table… Member DB Member Table1 Member Table2 Member Table…
51
51 SQL Azure Federations Split federation member Root DB Root Table1 Root Table2 Root Table… Member DB Member Table1 Member Table2 Member Table… Member DB Member Table1 Member Table2 Member Table…
52
52 SQL Azure Federations Voordelen DB Size van max 150 GB -> 75 TB CPU Cores en I/O verveelvoudigd Real-time Geen downtime
53
53 SQL Azure Federations Voordelen DB Size van max 150 GB -> 75 TB CPU Cores en I/O verveelvoudigd Real-time Geen downtime
54
54 SQL Azure Federations Voordelen DB Size van max 150 GB -> 75 TB CPU Cores en I/O verveelvoudigd Real-time Geen downtime
55
55 SQL Azure Federations Voordelen DB Size van max 150 GB -> 75 TB CPU Cores en I/O verveelvoudigd Real-time Geen downtime
56
56 SQL Azure Federations Kosten Sinds halverwege februari 2012 prijsverlaging. Tot 78% goedkoper. Hoe meer tenants per member database, hoe goedkoper. Eén databaseMeerdere databases FORMAATKOSTENFORMAATKOSTEN 10 GB$45,95 p/m10 x 1 GB10 x $9.99 = $99,90 p/m
57
57 SQL Azure Federations Kosten Sinds halverwege februari 2012 prijsverlaging. Tot 78% goedkoper. Hoe meer tenants per member database, hoe goedkoper. Eén databaseMeerdere databases FORMAATKOSTENFORMAATKOSTEN 10 GB$45,95 p/m10 x 1 GB10 x $9.99 = $99,90 p/m 50 GB$125,88 p/m10 x 5 GB$259,80 p/m
58
58 SQL Azure Federations Kosten Sinds halverwege februari 2012 prijsverlaging. Tot 78% goedkoper. Hoe meer tenants per member database, hoe goedkoper. Eén databaseMeerdere databases FORMAATKOSTENFORMAATKOSTEN 10 GB$45,95 p/m10 x 1 GB10 x $9.99 = $99,90 p/m 50 GB$125,88 p/m10 x 5 GB$259,80 p/m 50 GB$125,88 p/m50 x 1 GB$499,50 p/m
59
59 SQL Azure Federations Kosten Sinds halverwege februari 2012 prijsverlaging. Tot 78% goedkoper. Hoe meer tenants per member database, hoe goedkoper. Eén databaseMeerdere databases FORMAATKOSTENFORMAATKOSTEN 10 GB$45,95 p/m10 x 1 GB10 x $9.99 = $99,90 p/m 50 GB$125,88 p/m10 x 5 GB$259,80 p/m 50 GB$125,88 p/m50 x 1 GB$499,50 p/m 150 GB$225,78 p/m150 x 1 GB$1498,50 p/m
60
60 SQL Azure Federations Samenwerking met Entity Framework 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
61 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;
62
62 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;
63
63 SQL Azure Federations Entity Framework: geen support parallelle queries
64
64 Architectuur Overview - > Table Storage Webrole SQL Azure Table Storage ACS
65
65 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
66
Maatwerk
67
67 Maatwerk Maatwerk per tenant op twee gebieden: User Interface Business Logic
68
68 Maatwerk User Interface Tenant-logo
69
69 Maatwerk User Interface Tenant-logo Niet doen op deze manier: Kleuren Fonts Posities van html-elementen Etc.
70
70 Maatwerk User Interface - Themes
71
71 Maatwerk User Interface - Themes
72
72 Maatwerk User Interface - Themes 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, …); }
73
73 Maatwerk User Interface - Themes 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, …); }
74
74 Maatwerk User Interface - Themes 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, …); }
75
75 Maatwerk User Interface - Themes 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, …); }
76
76 Maatwerk User Interface - Themes 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)); }
77
77 Maatwerk User Interface - Themes 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)); }
78
78 Maatwerk User Interface - Themes Public class HomeController : Controller { [UseThemesViewEngine] public ActionResult Index() { }
79
79 Maatwerk User Interface - Themes 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)); }
80
80 Maatwerk Maatwerk per tenant op twee gebieden: User Interface Business Logic
81
81 Maatwerk Business Logic Probleem Tenant settings moeten continue doorgegeven worden If-statements en switch-statements door alle code verweven
82
82 Maatwerk Business Logic var data = Foo.Bar(TenantSettings) If(settings.IsGoldPartner) … else … TenantSettings Business Logic layer MVC Controller
83
83 Maatwerk Business Logic var data = Foo.Bar(TenantSettings) If(settings.IsGoldPartner) … else … TenantSettings Business Logic layer MVC Controller
84
84 Maatwerk Business Logic var data = BLL.GetData(TenantId) return DA.GetData(TenantId) from t in table where tenantid == TenantId select t select * from table where tenantid = TenantId TenantId Business Logic layer MVC Controller Data Access Database
85
85 Maatwerk Business Logic var data = BLL.GetData(TenantId) return DA.GetData(TenantId) from t in table where tenantid == TenantId select t select * from table where tenantid = TenantId TenantId Business Logic layer MVC Controller Data Access Database
86
86 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); }
87
87 Maatwerk Business Logic IoC container (autofac): builder.Register(c => NewSpamfilter()).As ; private Ispamfilter NewSpamfilter() { if(!TenantSettings.UseSpamFilter) return new NoSpamfilter(); if(TenantSettings.SpamFilterType == Fast) return new FastSpamfilter(); else if(TenantSettings.SpamFilterType == Slow) return new SlowSpamfilter();
88
88 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); }
89
89 Cache App Fabric Cache doet de basics Wissen van totale cache niet mogelijk 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
90
90 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]
91
91 Access Control Service Access Control
92
92 Access Control Service Intro Iedere tenant -> Relying Party Application in ACS Management Service (beschikbaar als Odata Service) Geen gebruikcijfers
93
93 Access Control Service AudienceMode Na inloggen stuurt ACS een token naar de website. Check (url in token == AllowedAudienceUri) Uitzetten!
94
94 Contact Bereikbaar voor vragen Edo van Asseldonk Email: edo.van.asseldonk@ordina.nl Twitter: @edovanasseldonk Blog: http://edo-van-asseldonk.blogspot.com
95
95 www.ordina.nl
Verwante presentaties
© 2024 SlidePlayer.nl Inc.
All rights reserved.