কেস স্টাডি - স্ট্রিম কংগ্রেসে রিয়েল-টাইম আপডেট

লুইগি মন্টানেজ
লুইগি মন্টানেজ

ভূমিকা

WebSockets এবং EventSource এর মাধ্যমে, HTML5 ডেভেলপারদের এমন ওয়েব অ্যাপ তৈরি করতে সক্ষম করে যা একটি সার্ভারের সাথে রিয়েল টাইমে যোগাযোগ করে। স্ট্রিম কংগ্রেস ( Chrome ওয়েব স্টোরে উপলব্ধ) মার্কিন যুক্তরাষ্ট্র কংগ্রেসের কাজকর্ম সম্পর্কে লাইভ আপডেট প্রদান করে। এটি হাউস এবং সেনেট উভয়ের ফ্লোর আপডেট, প্রাসঙ্গিক সংবাদ আপডেট, কংগ্রেস সদস্যদের টুইট এবং অন্যান্য সামাজিক মিডিয়া আপডেটগুলি স্ট্রিম করে। অ্যাপটিকে সারাদিন খোলা রাখা হবে কারণ এটি কংগ্রেসের ব্যবসাকে ক্যাপচার করে।

WebSockets দিয়ে শুরু

WebSockets স্পেকটি যা সক্ষম করে তার জন্য বেশ কিছুটা মনোযোগ পেয়েছে: ব্রাউজার এবং সার্ভারের মধ্যে একটি স্থিতিশীল, দ্বি-দিকনির্দেশক TCP সকেট । TCP সকেটে কোন তথ্য বিন্যাস আরোপিত নেই; বিকাশকারী একটি মেসেজিং প্রোটোকল সংজ্ঞায়িত করতে স্বাধীন। অনুশীলনে, JSON অবজেক্টগুলিকে স্ট্রিং হিসাবে পাস করা সবচেয়ে সুবিধাজনক। লাইভ আপডেট শোনার জন্য ক্লায়েন্ট-সাইড জাভাস্ক্রিপ্ট কোড পরিষ্কার এবং সহজ:

var liveSocket = new WebSocket("ws://streamcongress.com:8080/live");

liveSocket.onmessage = function (payload) {
  addToStream(JSON.parse(payload.data).reverse());
};

WebSockets-এর জন্য ব্রাউজার সমর্থন সহজবোধ্য হলেও, সার্ভার-সাইড সমর্থন এখনও গঠনমূলক পর্যায়ে রয়েছে। Node.js-এ Socket.IO সবচেয়ে পরিপক্ক এবং শক্তিশালী সার্ভার-সাইড সমাধান প্রদান করে। একটি ইভেন্ট-চালিত সার্ভার যেমন Node.js WebSockets-এর জন্য উপযুক্ত। বিকল্প বাস্তবায়নের জন্য, পাইথন বিকাশকারীরা টুইস্টেড এবং টর্নেডো ব্যবহার করতে পারে, যখন রুবি ডেভেলপারদের কাছে ইভেন্টমেশিন রয়েছে।

ক্র্যাম্প প্রবর্তন

ক্র্যাম্প হল একটি অ্যাসিঙ্ক্রোনাস রুবি ওয়েব ফ্রেমওয়ার্ক যা ইভেন্টমেশিনের উপরে চলে। এটি লিখেছেন রুবি অন রেল কোর টিমের সদস্য প্রতীক নায়েক । রিয়েল-টাইম ওয়েব অ্যাপগুলির জন্য একটি ডোমেন নির্দিষ্ট ভাষা (ডিএসএল) প্রদান করা, ক্র্যাম্প রুবি ওয়েব ডেভেলপারদের জন্য একটি আদর্শ পছন্দ। যারা রুবি অন রেলে কন্ট্রোলার লেখার সাথে পরিচিত তারা ক্র্যাম্পের শৈলীকে চিনতে পারবে:

require "rubygems"
require "bundler"
Bundler.require
require 'cramp'
require 'http_router'
require 'active_support/json'
require 'thin'

Cramp::Websocket.backend = :thin

class LiveSocket < Cramp::Websocket
periodic_timer :check_activities, :every => 15

def check_activities
    @latest_activity ||= nil
    new_activities = find_activities_since(@latest_activity)
    @latest_activity = new_activities.first unless new_activities.empty?
    render new_activities.to_json
end
end

routes = HttpRouter.new do
add('/live').to(LiveSocket)
end
run routes

যেহেতু ক্র্যাম্প নন-ব্লকিং ইভেন্টমেশিনের উপরে বসেছে, তাই মনে রাখতে বেশ কয়েকটি বিবেচনা রয়েছে:

  • নন-ব্লকিং ডাটাবেস ড্রাইভার অবশ্যই ব্যবহার করা উচিত, যেমন MySQLPlus এবং em-mongo
  • ইভেন্ট-চালিত ওয়েব সার্ভার ব্যবহার করতে হবে। সমর্থন পাতলা এবং রংধনু জন্য নির্মিত হয়.
  • ক্র্যাম্প অ্যাপটি অবশ্যই প্রধান রেল অ্যাপ থেকে আলাদাভাবে চালানো উচিত যা স্ট্রিম কংগ্রেসকে ক্ষমতা দেয়, পুনরায় চালু করা হয় এবং স্বাধীনভাবে পর্যবেক্ষণ করা হয়।

বর্তমান সীমাবদ্ধতা

WebSockets 8 ডিসেম্বর, 2010-এ একটি ধাক্কা খেয়েছিল যখন একটি নিরাপত্তা দুর্বলতা প্রচার করা হয়েছিল। ফায়ারফক্স এবং অপেরা উভয়ই ওয়েবসকেটের জন্য ব্রাউজার সমর্থন সরিয়ে দিয়েছে। যদিও কোনো বিশুদ্ধ জাভাস্ক্রিপ্ট পলিফিল বিদ্যমান নেই, সেখানে একটি ফ্ল্যাশ ফলব্যাক রয়েছে যা ব্যাপকভাবে গৃহীত হয়েছে। যাইহোক, ফ্ল্যাশের উপর নির্ভর করা আদর্শ থেকে অনেক দূরে। যদিও ক্রোম এবং সাফারি ওয়েবসকেটগুলিকে সমর্থন করে চলেছে, এটি স্পষ্ট হয়ে গেছে যে ফ্ল্যাশের উপর নির্ভর না করে সমস্ত আধুনিক ব্রাউজারকে সমর্থন করার জন্য, ওয়েবসকেটগুলিকে প্রতিস্থাপন করতে হবে৷

AJAX পোলিং-এ রোল ব্যাক করা হচ্ছে

WebSockets থেকে সরে গিয়ে "পুরানো-বিদ্যালয়" AJAX পোলিংয়ে ফিরে যাওয়ার সিদ্ধান্ত নেওয়া হয়েছিল৷ একটি ডিস্ক এবং নেটওয়ার্ক I/O দৃষ্টিকোণ থেকে অনেক কম দক্ষ হলেও, AJAX পোলিং স্ট্রিম কংগ্রেসের প্রযুক্তিগত বাস্তবায়নকে সরল করেছে। সবচেয়ে উল্লেখযোগ্যভাবে, একটি পৃথক ক্র্যাম্প অ্যাপের প্রয়োজনীয়তা বাদ দেওয়া হয়েছিল। AJAX এন্ডপয়েন্ট পরিবর্তে Rails অ্যাপ দ্বারা প্রদান করা হয়েছে। jQuery AJAX পোলিং সমর্থন করার জন্য ক্লায়েন্ট-সাইড কোড পরিবর্তন করা হয়েছে:

var fillStream = function(mostRecentActivity) {
  $.getJSON(requestURL, function(data) {
    addToStream(data.reverse());

    setTimeout(function() {
      fillStream(recentActivities.last());
    }, 15000);
  });
};

AJAX polling, though, is not without its downsides. Relying on the HTTP request/response cycle means that the server sees constant load even when there aren't any new updates. And of course, AJAX polling doesn't take advantage of what HTML5 has to offer.

## EventSource: The right tool for the job

Up to this point, a key factor was ignored about the nature of Stream Congress: the app only needs to stream updates one way, from server to client - downstream. It didn't need to be real-time, upstream client-to-server communication. 

In this sense, WebSockets is overkill for Stream Congress. Server-to-client communication is so common that it's been given a general term: push. In fact, many existing solutions for WebSockets, from the hosted [PusherApp](http://pusherapp.com) to the Rails library [Socky](https://github.com/socky), optimize for push and don't support client-to-server communication at all.

Enter EventSource, also called Server-Sent Events. The specification compares favorably to WebSockets in the context to server to client push:

- A similar, simple JavaScript API on the browser side.
- The open connection is HTTP-based, not dropping to the low level of TCP.
- Automatic reconnection when the connection is closed.

### Going Back to Cramp

In recent months, Cramp has added support for EventSource. The code is very similar to the WebSockets implementation:

```ruby
class LiveEvents < Cramp::Action
self.transport = :sse

periodic_timer :latest, :every => 15

def latest
@latest_activity ||= nil
new_activities = find_activities_since(@latest_activity)
@latest_activity = new_activities.first unless new_activities.empty?
render new_activities.to_json
end
end

routes = HttpRouter.new do
add('/').to(LiveEvents)
end
run routes

ইভেন্টসোর্সের সাথে মনে রাখতে একটি উল্লেখযোগ্য সমস্যা হল ক্রস-ডোমেন সংযোগ অনুমোদিত নয়৷ এর মানে হল যে Cramp অ্যাপটিকে অবশ্যই একই streamcongress.com ডোমেইন থেকে প্রধান Rails অ্যাপ হিসেবে পরিবেশন করতে হবে। এটি ওয়েব সার্ভারে প্রক্সি করার মাধ্যমে সম্পন্ন করা যেতে পারে। ক্র্যাম্প অ্যাপটি থিন দ্বারা চালিত এবং পোর্ট 8000-এ চলমান বলে ধরে নিই, অ্যাপাচি কনফিগারেশনটি এরকম দেখাচ্ছে:

LoadModule  proxy_module             /usr/lib/apache2/modules/mod_proxy.so
LoadModule  proxy_http_module        /usr/lib/apache2/modules/mod_proxy_http.so
LoadModule  proxy_balancer_module    /usr/lib/apache2/modules/mod_proxy_balancer.so

<VirtualHost *:80>
  ServerName streamcongress.com
  DocumentRoot /projects/streamcongress/www/current/public
  RailsEnv production
  RackEnv production

  <Directory /projects/streamcongress/www/current/public>
    Order allow,deny
    Allow from all
    Options -MultiViews
  </Directory>

  <Proxy balancer://thin>
    BalancerMember http://localhost:8000
  </Proxy>

  ProxyPass /live balancer://thin/
  ProxyPassReverse /live balancer://thin/
  ProxyPreserveHost on
</VirtualHost>

এই কনফিগারেশনটি streamcongress.com/live এ একটি ইভেন্টসোর্স এন্ডপয়েন্ট সেট করে।

স্থিতিশীল পলিফিল

WebSockets এর উপর ইভেন্টসোর্সের সবচেয়ে উল্লেখযোগ্য সুবিধা হল যে ফলব্যাক সম্পূর্ণ জাভাস্ক্রিপ্ট-ভিত্তিক, ফ্ল্যাশের উপর কোন নির্ভরতা ছাড়াই। রেমি শার্পের পলিফিল এমন ব্রাউজারগুলিতে লং-পোলিং প্রয়োগ করে যা ইভেন্টসোর্সকে নেটিভভাবে সমর্থন করে না। সুতরাং, ইভেন্টসোর্স জাভাস্ক্রিপ্ট সক্ষম সহ সমস্ত আধুনিক ব্রাউজারে কাজ করে।

উপসংহার

HTML5 অনেক নতুন এবং উত্তেজনাপূর্ণ ওয়েব বিকাশের সম্ভাবনার দরজা খুলে দেয়। WebSockets এবং EventSource এর সাথে, ওয়েব ডেভেলপারদের এখন রিয়েল-টাইম ওয়েব অ্যাপ্লিকেশানগুলি সক্ষম করার জন্য পরিষ্কার, সু-সংজ্ঞায়িত মান রয়েছে৷ কিন্তু সব ব্যবহারকারী আধুনিক ব্রাউজার চালায় না। এই প্রযুক্তিগুলি বাস্তবায়নের জন্য বেছে নেওয়ার সময় অবশ্যই ভাল অবনতি বিবেচনা করা উচিত। এবং WebSockets এবং ইভেন্টসোর্সের জন্য সার্ভার সাইডে টুলিং এখনও প্রাথমিক পর্যায়ে আছে। রিয়েল-টাইম HTML5 অ্যাপ তৈরি করার সময় এই বিষয়গুলো মাথায় রাখা গুরুত্বপূর্ণ।