קטגוריה: redis

ניסויים בתורי הודעות

יש מערכת שאחרי load test הבנתי כי אני חייב לבזר את המערכות שבה. אז התחלתי לבצע מחקר על סוגים שונים של message queue בשביל לבזר את המערכת. עשיתי ניסויים עם המון מערכות שונות, כולל התייעצות עם אנשים שממשים כבר מערכות המשתמשות בהם, והגעתי להבנה כי כנראה ש RabbitMQ מתאים לצרכים שלי.

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

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

למשל אני עשיתי 2 הגדרות בלבד לRabbit להתאים למכונת הפיתוח החלשה שלי, והגעתי ללמעלה מ7 מליון בקשות בשניה אחת, עד שרוחב הפס נחנק, אבל ה load היה על 0.02 לאורך זמן רב. כלומר לא הגעתי ל load שהם דיברו עליו. אבל יכולתי לבדוק לאורך זמן, רק כאשר ירדתי בערך ל5 מליון בקשות בשניה, ואז הרוחב פס כבר לא נחנק לי.

מצד שני, כתבתי את המערכת שלי בגו, ויותר מזה, מי שמדווח ובנוסף מי שמקבל את העבודה לא היו על אותה המכונה, אלא בכלל על הדסקטופ שלי בו זמנית, והload במכונה שלי, לא היה יותר מאחוז (כשהמכונה שלי עוד עשתה הרבה דברים נוספים).

יותר מזה, בתיעוד של Rabbit, כתוב שאפשר להגביל את ה load על המכונה, במידה ועוברים כמות מסויימת של שימוש במשאבים, היא מפסיקה לקבל עבודות, דבר שגם לא הוסבר אם נכנס לבדיקה שלהם, אך אני בכלל לא הגדרתי אותו.

כך שלי חסר מאוד מידע איך ומה בוצע בפוסט, אבל אני לא מצליח לשחזר את מה שהם כן מזכירים.
העניין הוא, שאני לא בוטח ברדיס לפעולות ה mq שאני צריך, כי אני צריך מחסנית יציבה של worker..
אם חלילה וחס הוא נפל, אסור שהמידע יאבד, ויותר מזה, במידה ואני צריך להוסיף workers, אני צריך מצב של ביזור המידע, בלי שworker אחד ידרוך על השני, ואני מקבל את זה בצורה טבעית ב Rabbit, (ועוד מספר סוגים של MQ שבדקתי), אבל רדיס מעולם לא תוכנן לזה. הוא נמצא בזיכרון, אני כמובן שיכול להכריח אותו לכתוב לדיסק (איטי מאוד, אבל זה מה שקורה עם persistence queue בRabbit), אבל בשביל לעשות תורים בגישה של Round Robin, ובכן, בלי לכתוב משהו ב lua, אני לא מכיר תמיכה לזה ברדיס, למרות שאשמח לגלות שיש.

ככול שאני עובד כרגע (אמנם עדיין בפיתוח) עם MQ, ככה אני אוהב יותר את הרעיון של השימוש ב Rabbit.
במערכת שאני בונה, יש לי מערכת חיצונית שהיא של ספק אחר שמדברת עם HorentQ, דרך הפרוטוקול שנקרא STOMP (בניגוד לRabbit שברירת המחדל שלו היא AMQP אך תומך גם ב STOMP), והיתרונות של מערכת כזו שהיא robust מאוד, מאפשרת להתמודד עם בעיות שונות, כדוגמת קריסת מערכת, ניתוק התקשורת, התנהלות של load balance של מספר שרתים וכיוב'…

כך שלדעתי, אחרי הרבה ניסויים, אני חושב שRabbit זו הגישה המתאימה לי, ובמידה ולא, תמיד אפשר לעבור בלי להחליף קוד 🙂

 

 

כשיש לך פטיש אוויר ביד …

לפני מספר חודשים עשיתי פרוייקט עם מישהו שהעסק שלו הוא פיתוח מערכות על wordpress.
הייתי צריך לבנות לו מערכת מבוססת טלפוניה לעסק שלו, עם ממשק ניהול למספר דברים, משהו כמו 3 מסכי ניהול, ובנוסף מספר ניתובים לשמור ולמשוך מידע.

כאשר אותו בחור הבין שבחרתי בסינטרה ולא ב wp, הוא לא הצליח להבין מדוע לא לבחור ב wp, היות ולדעתו ניתן לעשות עימה הכל.
ניסיתי להסביר לו כי מדובר בoverkill עצבני, כלומר לקחת פטיש אוויר לעשות חור בקיר לתלות תמונה, כאשר מסמר פשוט עם פטיש קל מספיק, הוא עדיין לא הבין את הבעיה, הרי אפשר לעשות אתרים ממש גדולים עם wp, אז מדוע אי אפשר לקחת אותו בשביל משהו פשוט ?

ובכן, עצם העניין שהכלי תוכנן ליצור אתרים ממש גדולים, הוא אינו יעיל או מותאם לדברים קטנים. הוא תופס יותר מידי משאבים לזה, אשר לא צריכים להתקיים כאשר מדובר במשהו קטן.
כאשר צריך ליצור גמישות רבה מאוד, לפעמים האנרגיה שתדרש בwp תהיה גבוהה יותר מאשר ליצור אותה מאפס, רק בגלל שמערכת cms במקור אינה זקוקה לזה, אז לא תוכננה בחשיבה הזו, בעוד שחשיבה מראש על מימוש מסויים, תיצור תשתית טובה יותר.

שימוש בסינטרה מאפשר לי לקחת פריימוורק כדוגמת foundation או bootstrap כ css ובנוסף לשלב את ember/angular או סתם את jquery/dojo בהתאם לצורך.

עבור מסדי נתונים, אני גם מקבל גמישות, כך שאם חלילה וחס אני נאלץ לגעת ב MySQL/MariaDB (לרוב להתחבר למסד נתונים קיים) אין בעיה (לפחות ההתחברות, עם הגועל זה משהו אחר), ואם אני בר מזל ויכול לבחור מסד נתונים, אז אבחר ב PostgreSQL , ואם יש צורך אז אבחר בכלל במונגו או אולי בכלל בRedis ?

אם אני צריך, אז אוסיף למשל סוג של job queue בהתאם לצורך הספציפי והרשימה לעבודה עוד ארוכה…

כל אלו אינם קיימים בwp, היות ובתור cms הוא נועד לגישה מאוד מדוייקת שמתאימה ל cms, אבל לא אפליקצייה.

אבל כנראה גם הפעם מאסלו צדק, וכשיש  לך פטיש ביד, הכל נראה לך מסמר …

IPC באמצעות Redis ורובי

Redis הוא מסד נתונים אשר אינו מבוסס SQL וכתבתי עליו רבות כאן בעבר.

לאחרונה נדרשתי לפרק מערכת שלי למספר תתי מערכות, ולהעביר מידע בניהם. כמובן שיש הרבה מאוד דרכים לעשות זאת, כדוגמת Message Queue ‏(RabitMQ, ZeroMQ וכו'), עבודה עם PIPES ביוניקס, עבודה בתצורת client server ועוד הרבה מאוד דרכים כיד הדמיון והמערכת הטובה לכם. אני החלטתי ללכת על Redis.

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

דבר נוסף, הוא שהמערכות שלי כתובות ברובי, ורק מה שצריך לקבל כאירוע לא נכתב, וRedis גם ככה כבר מותקן, ואני כבר מכיר אותו, ויש לי מעט מאוד זמן לכתוב את השינויים.

לRedis יש מספר דרכים לשלוח ולקבל אירועים, אבל אני הולך לדבר כאן על Publish ו PSubscribe. האחרון מאפשר להאזין להודעות באמצעות תבנית חיפוש (עם כוכביות), במקום שם מלא ומדוייק שאחיו Subscribe מספק.

לשם כך צריך לפחות 2 פרוססים שונים, האחד שולח הודעות, והשני מקבל.

שליחת הודעות מאוד פשוטה:

require 'rubygems'
require 'redis'

redis = Redis.new(:host => 'localhost')

10.times do |i|
  redis.publish("number_#{i + 1}", Marshal.dump({:number => i}))
  sleep( (i + 1) / 10.0)
end

התחברתי לRedis, והתחלתי לרוץ על כל המספרים מ0 ועד 9.
יצרתי מפתח שההתחלה שלו הוא number_‎ ולאחר מכן המספר. המבנה חשוב מאוד בשביל להצליח להאזין לאירוע.
לאחר מכן, יצרתי תצורה בינארית עבור Ruby Hash ושלחתי אותה כמידע שאני זקוק לו לשימוש.
כאשר הפעולה מסתיימת, אני נח כמות של מילישניות לפי המספר, החישוב לדעתי די ברור כאן.

הפרוסס השני צריך להקשיב לאירוע:

require 'rubygems'
require 'redis
redis = Redis.new(:host => 'localhost')

redis.psubscribe('number_*') do |on|
  on.pmessage do |pattern, event, message|
    puts "pattern: #{pattern}, event: #{event}, message: #{Marshal.load(message)}"
  end
end

כאן אנחנו מקשיבים לפעולות אשר נשלחות עם סוגי publish השונים.
יש האזנה לאירועים באמצעות תבנית (pattern) ומכאן המקדם בעצם של הפקודה (p).
הפקודה בעצם מכניסה אותנו לתוך בלוק אשר דרכו אפשר להאזין למגוון סוגים של אירועים.
כן האירוע שצריך הוא pmessage לו אני מאזין, וכאשר הוא מתרחש, הקוד בתוכו מורץ.
אני משחזר כאן את המידע הבינארי חזרה למחלקות של רובי, ובכך העברתי מידע סיריאלי לחלוטין של רובי.
חשוב להבין כי זוהי פעולה שהיא blocking, ולכן כאשר מריצים אותה, אין המשך כלפי מטה לקוד.

התוצר כאן יהיה בסגנון הבא:

pattern: number_*, event: number_1, message: {:number=>0}
pattern: number_*, event: number_2, message: {:number=>1}
pattern: number_*, event: number_3, message: {:number=>2}
pattern: number_*, event: number_4, message: {:number=>3}
pattern: number_*, event: number_5, message: {:number=>4}
pattern: number_*, event: number_6, message: {:number=>5}
pattern: number_*, event: number_7, message: {:number=>6}
pattern: number_*, event: number_8, message: {:number=>7}
pattern: number_*, event: number_9, message: {:number=>8}
pattern: number_*, event: number_10, message: {:number=>9}

ה gem הראשון שלי

באוגוסט 2012 כתבתי על ספרייה שאני עובד בשם redis_session. משום מה, התגובה היחידה שקיבלתי בפרטי, היתה כי אין לי מספיק בדיקות (ולא על כך שהיא לא מתועדת למשל).

לאחרונה חזרתי אליה, ושיפצרתי אותה יותר, ואף יצרתי לה מערכת בדיקות אוטומטיות עם rspec ואפילו הוספתי תעוד של rdoc (שוקל להמיר ל yard), ובין חמישי לשישי פרסמתי את ה gem שלי לראשונה להורדה באמצעות מנהל החבילות של רובי.

אני חייב לציין שזה היה פשוט מידי לעשות את המהלך. הרשמה לrubygems, הורדת ה gemcutter מרובי gem, יצירת ה gem ואז ביצוע push עם הדוא"ל והסיסמה של rubygems וזהו 🙂

אני יודע שסטטיסטיקה חשובה לכם, אז נכון לכתיבת הפוסט היו 40 הורדות של ה gem פחות מ24 שעות לאחר הפרסום שלו, שלדעתי לפחות זה מדהים 🙂

תובנות השוק מהרצאה שהעברתי

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

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

לאחר מכן, העברתי הרצאה על No(t only) SQL. בהרצאה העברתי הסבר מה זה בגדול אומר, איך מבינים בכלל מתי, ואיך הוא מתאים לנושא, התמקדתי בMongoDB ובRedis. שני מסדי נתונים אשר אני משתמש בהם.

הדגמתי להם לפי צורות העבודה שלהם, כיצד הם יכולים לשפר להם את הביצועים, למנוע בעיות עומסים שונים וכו'

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

ניסיתי להסביר לו כי העולם הטכנולוגי, מחוץ לעולם המיקרוסופט, הוא עולם מאוד דינאמי אשר משתנה מהר מידי בשביל באמת להצליח ללמד אותך משהו במכללה. לפחות משהו אשר יהיה נכון גם שנה לאחר מכן, ולכן נהוג לקרוא מידע ולחקור לבד – וזו פעולה שכבעל מקצוע מאוד נחוצה. בנוסף גם הזכרתי לו כי התפקיד של מתכנת זה לא להיות code monkey ורק לכתוב קוד כל היום, אלא תפקיד של המתכנת  הוא לספק מענה לצרכים שונים, והדרך לכך היא להכיר כמה שיותר כלים, וצורות עבודה.

אפילו הסברתי לו כי לא בכדי מרבית התעשייה אינה עובדת בתפיסת העולם של מיקרוסופט, אלא גישה דינאמית וכלים לגמרי שונים. ויותר מזה, כל עולם ה "cloud", אינו זהה אחד לשני, אלא לכל ארגון יש דרישות שונות והדרישות האלו משתנות מידי בשביל לבחור בתבנית הקבועה.

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

או כפי שאברהם מאסלו אמר פעם – כאשר יש בידך פטיש, הכל נראה לך מסמר
אתה פשוט לא מסוגל להבין כי לפעמים יש שימוש גם למברג, שפכטל וכו' …

Redis Session for Ruby

I'ved created a standalone session system based on Redis database.
This session system was not build only for web in mind, but also for non web based systems.
I for example, use it with Asterisk based programs that I'm writing to clients.

The session lib supports at the moment only few features:

  1. Connect to Unix sockets
  2. Connect to TCP sockets, and changing the port number if needed
  3. Expiring all keys
  4. Expiring specific keys
  5. Changing expiry of a specific key
  6. Checking expiry of a specific key
  7. Saving and restoring Ruby based structures such as hashes, arrays, boolean etc…
  8. Removing keys
  9. Prefix that will be automatically added to each key name (in saving and restoring)

The usage of the system is very simple:

The current version (0.1.3), does not contain yet any documentation. However it will be added in next version.
The library itself is under the MIT license, and can be downloaded here.

You can create your own gem file. I hope that by the next version, it will be created automatically.

* You must have active Javascript support for wordpress.com and github to view the source code.

Redis – From client to execution

העברתי בפרל מונגרס הרצאה על לקוח הרדיס שאני יוצר.

שעה לפני התחלת ההרצאה, קיבלתי בדיוק דוא"ל מבחור מיוון שהודה לי מקרב לב על הלקוח שעוזר לו מאוד. שזה בפני עצמו היה ממש כיף לקבל.

את ההרצאה לא תוכלו לקבל ברשת, אבל את השקפים המטורפים שלי כן:

CentOS Packages

I find myself once in a while with a need for software package that does not exists for CentOS (or at least not the version I need them to be), so I find myself maintaining some spec files (and sometimes even more) of the required software.

I started adding such packages to GitHub, in order also to help others if they also find themselves with such a need.

At the moment I have 2 packages:

In the feature I might add additional packages, and also merge them into one big tree

You are more then welcome to fork me at Github 🙂

חבילות ל CentOS

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

התחלתי לשים חבילות כאלו בgithub אצלי, במטרה גם לעזור לאחרים לקבל מענה הולם במידת הצורך.

כרגע יש 2 חבילות:

בעתיד אוסיף עוד חבילות במידת הצורך, ואולי אמזג את זה לעץ אחד.

כרגע אתם מוזמנים כמובן לעשות לי Fork בGitHub 🙂

My roadmap for open source projects

All work and no play, makes IK a bad open source dev.

Recently I was required to stop the work on my Redis client due to lack of time. But I still going to finish the client, but it will take more time then what I thought it would.

But it made me think, what exactly are the things I wish to develop and contribute for open source projects.

So after the Redis client work, I wish to work on the following projects (some will be mine):

  • Contributing to Adhearsion
  • Creating web framework to fpWeb (It's just a CGI framework, not a whole web framework)
  • Working on a library I wanted to start in 2010 for VoIP
  • Continue working on Redis client when needed

I have no time frame limit for this, but that's the open source stuff I wish to work on when I'll have more time.