content top
קול התור נשמע בארצנו: השימוש ב-Queue של Azure (והוצאת קיטור)

קול התור נשמע בארצנו: השימוש ב-Queue של Azure (והוצאת קיטור)

מה בתוכניתנו?

ל-Azure יש אובייקט בשם Queue שלכאורה יכול היה להיות תחליף ל-Service Broker שב-On Premise.

Queue הוא אובייקט שסרוויס אחד מכניס לתוכו מידע, ואחר שולף על פי סדר ההכנסה (FIFO); כל זאת במסגרת עיבוד אסינכרוני. לו לא היו מספקים לנו Queues מן המוכן, היינו יכולים לאלתר בקלות פתרון עם טבלאות; אך אם מקבלים אובייקט עם הפונקציונליות המבוקשת בתוכו – נשתמש בו בשעת הצורך.
גדולתו של Service Broker בעיני היא ביכולת לכלול בהגדרת ה-Queue פרוצדורה שקוראת ממנו, ואזי כלערך שמוכנס ל-Queue יוזם אוטומטית הפעלה של הפרוצדורה שתטפל בו. קצת דומה ל-Trigger על טבלה, אך עם היתרון בכך שההפעלה של הפרוצדורה היא אסינכרונית, ולכן עדכון התור אינו תלוי בהצלחת הרצת הפרוצדורה או במשך הריצה.
מה מציע לנו Azure? ניצור Queue, נגדיר Function Apps שתופעל משיתעדכן ה-Queue ויעדכן טבלה ב-SQL Database (גם ב-Azure), וכמובן נדאג לקוד שישלח ערכים ל-Queue.

יצירת Queue ב-Azure

בפורטל ניצור Storage Account:

image

image

כפי שניתן לקרות, פינקתי את עצמי ב-Storage Account על שמי,
בחרתי ב-Subscription וב-Resource Group מן המוכן,
ובשאר סמכתי על המלצת המערכת.
לוקח לו כמה שניות להיווצר, ולבסוף הוא מתווסף לרשימת ה-Storage Account.
כעת ניצור Queue בתוך ה-Storage Account (וגם הוא ישא את שמי ולא לשווא):

image

כעת נוסיף הודעת Hello world ידידותית לתור:

image

כעת ניתן לראות את ההודעה ממתינה בסבלנות לתורה,
וכל עוד לא נאמר אחרת – זמנה קצוב: 7 ימים או עד שישלפו אותה, המוקדם מבין השניים.

שליפת ההודעה מה-Queue

ניצור כעת Function Apps שתהווה Trigger שיופעל בכל פעם שהודעה תיכנס ל-Queue (וגם תטפל רטרואקטיבית בכל מה שכבר שם).
נפתח דף חדש בדפדפן (את הקודם נשמור למעקב לראות מה עלה בגורל ה-message), ונתחבר שוב לפורטל:

image

ויוצרים פונקציה חדשה:

image

במפתיע או שלא – נקרא לפונקציה על שם גיבור הפוסט,
נבחר ב-Subscription וב-Resource Group מן המוכן,
וב-Stirage שיצרנו קודם לכן:

image

מכיוון שבמהלך יצירת ה-Function App המערכת מחזירה אותנו למסך הכניסה לפורטל, ניתן למצוא אותה (לאחר שסיים להיווצר) דרך אופציית החיפוש בראש העמוד:

image

השם Function Apps קצת מבלבל כי מתחתיו יכולות להיות מספר פונקציות.
מכיוון שהאובייקט חדש – אין עדיין, ואנחנו ניצור את הפונקציה הראשונה:

image

אפשרויות רבות והבחירה קשה, ןאנחנו נבחור ב-#Queue Trigger – C:

image

את בחירת השם השארתי הפעם למערכת, אבל מי שרוצה – שיבחר כאוות נפשו,
ה-Queue name הוא זה שיצרנו קודם,
ה-Storage_account_connection הוא זה שיצרנו קודם (מימין לו מופיעה אופציית New שמאפשרת לבחור במתאים, אלא שבצליום המסך הזה היא מוסתרת),
ולחיצה על show value תחזיר את המחרוזת הארוכה הזו שנשמור בצד לשימוש עתידי.
נאשר ונקבל את הפונקצייה מוכנה לשימוש:
image

לפני שנשמור נציץ בדף עם ה-Queue לראות שההודעה עדיין שם,
נחזור ונשמור (Save) ואו אז הפונקציה אמורה לפעול אוטומטית ולכתוב ללוג את הערך שנקרא מה-Queue.
כדי לראות את הלוג יש להרחיב אותו למטה מימין.
כפי שניתן לראות – הערך Hello world נקרא.
אם נחזור לדף של ה-Queue ונרפרש אותו – ההודעה כבר לא תהיה שם.
אם נוסיף ל-Queue הודעה חדשה – היא תטופל כבר אוטומטית על ידי הפונקציה שזה עתה כתבנו (בשלב זה “תטופל” פירושו שההודעה תיקרא ותיכתב ללוג, אך בהמשך ננסה לעשות משהו יותר משמעותי).
במסך ה-Monitor נוכל לראות את לוג הריצות וסטטיסטיקות לגבי ההצלחות והכשלונות,
ובמסך ה-Integrate נראה את שם הפרמטר עם תוכן ההודעה שהפונקציה מקבלת מה-Queue (זה הפרמטר שמופיע בפונקציה עצמה):

image

כמו כן – יש שם אופציות נוספות לפונקציונליות של הפונקציה.

שימוש בפונקציה להרצת קוד ב-SQL Database

נחליף את הקוד הקודם במשהו קצת יותר מפונפן, שמריץ פקודת Insert לטבלה ב-SQL Azure (אפשר באותו אופן להריץ פרוצדורה):

#r "System.Data"

using System;

using System.Configuration;

using System.Data.SqlClient;

public static void Run(string myQueueItem, TraceWriter log)

{

    var str = "Server=tcp:teddicq7nm.database.windows.net,1433;Initial Catalog=GeriReshefDB;Persist Security Info=False;User ID=Ana;Password=p@$$w0rD_p@$$w0rD;MultipleActiveResultSets=True;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;";

    using (SqlConnection conn=new SqlConnection(str))

    {

        conn.Open();

        var sqlStr = $"Insert Into T_Log (Txt) Values ('"+myQueueItem+"')";

        using(SqlCommand cmd=new SqlCommand(sqlStr, conn))

        {

            var rows = cmd.ExecuteNonQuery();

        }

    }

}

לנוסיף ערך חדש ל-Queue בדף שלו,

נחזור לדף של הפונקציה ונוודא שיש חיווי שהיא רצה,

ואז ניגש לטבלה ב-SQL Database ונוודא שנכנסה שורה חדשה עם ערך ההודעה מה-Queue.

סיכום ביניים

יצרנו Queue ופונקצית טריגר ששולפת אוטומטית כל הודעה שנכנסת ל-Queue ומכניסה אותה לטבלה ב-SQL Database.

כאן אפשר לשאול- מה הועילו חכמים בתקנתם? במקום להכניס ל-Queue נכניס ישר לטבלה וחסל; ובכלל – מה רבותא בלהכניס ערכים גרך הפורטל?

כוונת המשורר היא אחרת: יש תהליך שרץ במקום כלשהו, ושאנחנו רוצים שיבצע משימה מסויימת באופן אסינכרוני. צשימה שיכולה להימשך זמן רב.

הפתרון: התהליך ישלח הודעה ל-Queue, והפונקצייה תבצע את המשימה מבלי להפריע לתהליך להמשיך ולהתקדם במקביל. הכנסת ההודעה מה-Queue לטבלה נועדה להמחיש פעולה המתבצעת אסינכרונית.

מהו אם כן אותו תהליך שמכניס ערכים ל-Queue?

הכנסת ערכים ל-Queue בעזרת Python

קודם כל – נוסיף ל-Python את הספריות הנחוצות לעבודה עם Azure בכלל ועם Queues בפרט.

יש להתקין בעזרת pip בחלון ה-cmd (רצוי מאוד בהרשאות אדמיניסטרטור):

pip install azure

pip install azure.storage

pip install storage

pip install azure-storage

אם המערכת אינה מוצאת משום מה את pip – יש למצוא אותו ולהריץ כל אחת מהפקודות עם הנתיב המלא שלו (ואולי גם לציין את הסיומת exe).

גילוי נאות: התבחבשתי המון עם זה עד שזה עבד, אז יכול להיות שאחת הפקודות מיותרת, אבל כדי להיות בטוח – אני מציין שהרצתי את ארבעתן ואז הקוד של ה-Python עבד.

וכעת לקוד ה-Ptython:

import azure

from azure.storage.queue import QueueService

MyService=QueueService(account_name='geristorageaccount', account_key='j+2S66m+WjsVHGx9xx0y3aKl5RuOhUiGu0rkEt/QDFwk67KRmCj3rz2HxUJFpNkPsNUkB8nm+3aHIkvVpnNpGw==')

MyService.encode_function=azure.storage.queue.models.QueueMessageFormat.text_base64encode

MyService.put_message('geriqueue', u"Hello Python")

את הקוד הארוך שבשורה השלישית יש להחליף בקוד ששמרנו כשהגדרנו את הפונקציה, ומי שלא שמר – ימצא אותו במסך ה-Integrate ב-Show value.

להריץ, לקוות לטוב, ולוודא בטבלה שהערך נכנס.

מה יעשה מי שהפייתון אינו זמין עבורו?

אפשר להוריד ולהתקין, ומי שהתקין SQL2017 – הוא כולל כבר התקנה של פייתון.

כעת יש להריץ בשורת הפקודה (או בחלון ה-Cmd רצוי בתור administrator) את 4 פקודות ה-pip הנ”ל שיתקינו תמיכה במודולים הרלוונטיים ב-Azure,

ואז אפשר להפעיל את הפייתון בעזרת הפקודה Python במסך ה-Cmd. אם המערכת אינה מוצאת את זה – יש להפעיל עם הנתיב המלא (ולהוסיף “מרכאות” משני הצדדים – בעיקר אם יש רווחים ב-Path), ואז הקידומת במסך תשתנה ל-<<<

image

לשם יש להעתיק את פקודות הפייתון (כעקרון אפשר את כולן ביחד).

סיכום

אפתח בכך שבפוסט הזה הושקעה המון עבודה: לא בכתיבה עצמה, אלא בהתגברות על כל המכשולים הטכניים, העדר תיעוד, תיעוד לא מספק וכו’. מקווה שעם הפוסט הזה – תיחסך הטירחה ממי שינסה בעצמו (בהנחה שהוא יגיע אליו במהלך שיטוטיו באינטרנט..).

בנוסף – קשה לתפור מזה משהו שימוש: במערכות On Premise ניתן להסתדר עם Service Broker ולחסוך את כל הפירוטכניקה, ב-SQL Azure שאינו תומך ב-Service Broker לא ניתן לעדכן Queues – וזה קצת מגוחך שכדי לעדכן Queue ב-Azure יש לצאת מ-Azure; ולבסוף – בקרוב מיקרוסופט צפוייה להציג טכנולוגיה חדשה בשם Managed Instances שתסגור את הפער בין SQL Azure ל-On Premise, ואז (אם וכאשר) – אולי יהיה לנו Sevice Broker שייתר את כל זה..

לסיכום, אינני רואה במה שהוצג כאן “הצעת הגשה”: אני אינני מתכוון לממש את זה בסביבת production. יחד עם זאת, לכל אחד מהרכיבים עשוי להימצא שימוש מועיל: פייתון, Queue + טריגר וכו’.


כתיבת תגובה

האימייל לא יוצג באתר. (*) שדות חובה מסומנים

20 − seven =