برمجة

تشغيل التطبيقات متعددة الآجراء على ال SQL Azure Elastic Scale للتطبيقات التي تعمل على بيئات غير ال .NET

By حسام الكرد

June 08, 2015

أعلنت شركة مايكروسوفت عن نظامها الجديد في ال SQL Azure والذي يسمح للمطورين بناء أنظمة موزعة عبر الكلاود وكذلك تطبيقات SaaS الخدماتية. يمكنك معرفة المزيد من المعلومات عبر الرابط التالي

  https://azure.microsoft.com/en-gb/documentation/articles/sql-database-elastic-scale-documentation-map/

ولسوء الحظ, لا يوجد الآن حل جاهز من المكتبات لتطبيقات التي تعمل على بيئة غير ال .NET, بالإضافة إلى ذلك فإن التطبيقات التي كانت تعمل على نظام ال federation الخاص بعملية تقسيم التطبيقات, هذه التطبيقات لن تعمل في تاريخ سبتمبر ٢٠١٥, حيث أن التطبيقات التي تعمل بنظام الآجراء بلغات مثل PHP لن يكون لها القابلية لإستخدام elastic scale بشكل مباشر.

هذا سبب كتابة التدوينة لتقديم حل يساعد على الرحيل إلى نظام ال SaaS بنظام مايكروسوفت الجديد SqlAzure Elastic Scale بدون إستخدام مكتبات ال .NET.

بداية كل ما عليك فعله هو متابعة الفيديو التعليمي من مايكروسوفت بالفكرة العامة للهجرة من نظام ال Fedration  إلى ال Elastic Scale

من الناحية التقنية, لن نقوم بمناقشة كيفية إضافة شارد ومدير شارد بشكل عميق, وهذا يعني أنه لديك مدير للشاردز وشارد متوفر وموجود. هذه التدوينة تخبرك كيف تشغل وتحور التطبيق ليكون متعدد الآجراء, هناك تدوينة أخرى بشأن فتح أجراء جدد وإنشاء شارد جديد.

كيفية فلترة البيانات في كل من إستعلامات SELECT, Update, Delete على حسب آجير معين بإستخدام (Row Level Security )

خاصية Row Level Security والتي يمكن من خلالها فلترة إستعلامات قاعدة البيانات حسب رقم أجير محدد متوفرة فقط على خادم SQL SERVER V12 وهذا يعني أنه ينبغي عليك التأكد من تحديث خادم قاعدة البيانات الخاص بك على ال Azure إذا ما أردت إستخدام الخاصية.

لإضافة الخاصية تحتاج لإنشاء هيكلية خاصة وتفعيلها, مثل الكود في الأسفل

[box type=”shadow” ]CREATE SCHEMA rls — separate schema to organize RLS objects GO

CREATE FUNCTION rls.fn_tenantAccessPredicate(@TenantId int) RETURNS TABLE WITH SCHEMABINDING AS RETURN SELECT 1 AS fn_accessResult

WHERE DATABASE_PRINCIPAL_ID() = DATABASE_PRINCIPAL_ID(‘dbo’) — the user in your application’s connection string (dbo is only for demo purposes!)

AND CONVERT(int, CONVERT(varbinary(4), CONTEXT_INFO())) = @TenantId — @TenantId (int) is 4 bytes GO [/box]

بمجرد تنفيذ الكود بالأعلى نكون قد أنشأنا Security Level, نحتاج لفترة الجداول بحيث يمكننا تطبيق ال row level على كل جدول مثال في الأسفل

[box type=”shadow” ]

CREATE SECURITY POLICY rls.tenantAccessPolicy

ADD FILTER PREDICATE rls.fn_tenantAccessPredicate(TenantId) ON dbo.Blogs

ADD FILTER PREDICATE rls.fn_tenantAccessPredicate(TenantId) ON dbo.Posts GO [/box]

Further we need to set the Default value for the Tenant ID in order to be prompted in the query executions, the default value will be

[box type=”shadow” ]CONVERT(int, CONVERT(varbinary(4), CONTEXT_INFO()))[/box]

توجيه الآجير إلى الشارد المناسب

بعد فلترة البيانات على حسب الأجير, نحتاج لتوجيه الآجير إلى الشارد المناسب, حيث أن التطبيق يمكن أن يحوي مجموعة من الشاردز وكل شارد يحوي مجموعة آجراء. يمكن أن يعمل نظام الآجراء للتطبيق بمدى محدد مثال من 0 إلى 200 لشارد١ و 200 إلى 400 للشارد٢ وهكذا, في هذه الحالة كل ماعليك هو تعريف الآجير يقع في آي مدى, يمكن تطبيق الكود في الأسفل بإضافة دالة في قاعدة بيانات مدير الشارد للحصول على الأجير المناسب

[box type=”shadow” ]

[highlight]

CREATE FUNCTION [dbo].[getTenantConnectionInfoByTID] (@TenantId int) RETURNS TABLE AS RETURN 

( SELECT sg.[DatabaseName] ,smsg.[Name] AS ‘shardMapManagerName’

FROM [__ShardManagement].[ShardMappingsGlobal] smg, [__ShardManagement].[ShardsGlobal] sg, [__ShardManagement].[ShardMapsGlobal] smsg

WHERE smg.[ShardMapId] = smsg.[ShardMapId] AND

smg.[ShardMapId] = sg.[ShardMapId] AND

sg.[ShardId] = smg.[ShardId] AND

@TenantId >= (CONVERT(int, CONVERT(VARBINARY(4), [MinValue])) +2147483648)  AND

@TenantId < (CONVERT(int, CONVERT(VARBINARY(4), [MaxValue])) +2147483648)

)

[/highlight]

[/box]

في حال كان التطبيق لا يعمل بنظام المدى, بمعنى هناك آجراء مختلفين مسجلين في شارد مختلفة يمكن تطبيق الكود في الأسفل في مدير الشارد بدلا من الكود في الأعلى

[box type=”shadow” ]

[highlight]

CREATE FUNCTION [dbo].[getTenantConnectionInfoByTID] (@TenantId int) RETURNS TABLE AS RETURN 

( SELECT sg.[DatabaseName] ,smsg.[Name] AS ‘shardMapManagerName’

FROM [__ShardManagement].[ShardMappingsGlobal] smg, [__ShardManagement].[ShardsGlobal] sg, [__ShardManagement].[ShardMapsGlobal] smsg

WHERE smg.[ShardMapId] = smsg.[ShardMapId] AND

smg.[ShardMapId] = sg.[ShardMapId] AND

sg.[ShardId] = smg.[ShardId] AND

@TenantId = (CONVERT(int, CONVERT(VARBINARY(4), [MinValue])) +2147483648) )

[/highlight]

[/box]

إضافة stored procedure بحيث يتم تمرير فيها رقم الأجير وتقوم بتثبيت رقم الأجير لجميع العمليات

[box type=”shadow” ]CREATE PROCEDURE sp_setContextInfoAsAppUserId(@TenantId int) AS SET CONTEXT_INFO @TenantId; GO[/box]

[divider]

الأن قمنا بتجهيز كل شيء, كل ما عليك هو فلترة التطبيق حسب آجير معين. لنضع كل شيء معا, أولا عليك الإتصال بقاعدة بيانات مدير الشارد حيث ستقوم بدورها بتحديد أين يقع الأجير في أي شارد بإستخدام الدالة  .getTenantConnectionInfoByTID(your tenant id here) التي قومنا بتعريفها

 والأن بعد ما حددنا مكان الأجير نقوم بالإتصال بقاعدة البيانات للشارد ومن ثم نقوم بفلترة البيانات حسب رقم الأجير داخل الشارد من خلال إستخدام الدالة التالية

[box type=”shadow” ];’EXEC sp_setContextInfoAsAppUserId ‘your tenant id here[/box]

الأن تطبيقك مفلتر حسب التينتنت, حيث يمكن

select, insert, delete, update على حسب التينيت

أتمنى أن تكون التدوينة قدمت لكم الفائدة, وأنا مستعد لأي أسئلة

دمتم بود, إلى تدوينة أخرى