কম্পিউটার টিউটোরিয়াল

Unicorn কে Nginx-এ কানেক্ট করা: রুবিতে ইউনিক্স সকেটের প্র্যাক্টিক্যাল গাইড

রুবি অ্যাপ্লিকেশন সার্ভারগুলো সাধারণত nginx-এর মত একটি ওয়েব সার্ভারের সাথে একসাথে ব্যবহার করা হয়। যখন একজন ইউজার আপনার রেলস অ্যাপ থেকে একটি পেজ রিকোয়েস্ট করে, nginx রিকোয়েস্টটি অ্যাপ্লিকেশন সার্ভারের কাছে ডেলিগেট করে। কিন্তু এটি একদম কীভাবে কাজ করে? Nginx কীভাবে Unicorn-এর সাথে কথা বলে?

সবচেয়ে ইফিশিয়েন্ট অপশনগুলোতে একটি হলো ইউনিক্স সকেট ব্যবহার করা। চলুন দেখি সেগুলো কীভাবে কাজ করে! এই পোস্টে আমরা সকেটের বেসিকস থেকে শুরু করব এবং শেষ করব আমাদের নিজস্ব একটি সিম্পল অ্যাপ্লিকেশন সার্ভার তৈরি করে যা nginx দ্বারা প্রক্সিড হয়।

Unicorn কে Nginx-এ কানেক্ট করা: রুবিতে ইউনিক্স সকেটের প্র্যাক্টিক্যাল গাইড সকেট প্রোগ্রামগুলোকে একে অপর সাথে কথা বলতে দেয় যেন সেগুলো ফাইলে রাইট বা রিড করছে। এই উদাহরণে, Unicorn সকেটটি তৈরি করে এবং কানেকশনের জন্য মনিটর করে। Nginx তারপর সকেটে কানেক্ট করে এবং Unicorn-এর সাথে কথা বলে।

ইউনিক্স সকেট কী?

ইউনিক্স সকেট এক প্রোগ্রামকে অন্যটির সাথে কথা বলতে দেয় একটি উপায়ে যা ফাইল հետ কাজ করার সাথে সাদৃশ্য রেখে। এগুলো IPC, বা ইন্টার-প্রসেস কমিউনিকেশনের একটি টাইপ।

একটি প্রোগ্রাম সকেটের মাধ্যমে অ্যাক্সেসযোগ্য হওয়ার জন্য, প্রথমে একটি সকেট তৈরি করে এবং এটিকে ডিস্কে "সেভ" করে, ঠিক ফাইলের মত। এটি সকেটটি মনিটর করে ইনকামিং কানেকশনের জন্য। যখন এটি একটি কানেকশন পায়, এটি স্ট্যান্ডার্ড IO মেথড ব্যবহার করে ডেটা রিড এবং রাইট করে।

রুবি আপনাকে ইউনিক্স সকেটের সাথে কাজ করার জন্য যা কিছু দরকার সেটি প্রদান করে কয়েকটি ক্লাস দিয়ে:

  • UNIXServer - এটি সকেট তৈরি করে, ডিস্কে সেভ করে, এবং আপনাকে নতুন কানেকশনের জন্য মনিটর করতে দেয়।

  • UNIXSocket - এক্সিস্টিং সকেট IO-এর জন্য ওপেন করে।

নোট: অন্য ধরনের সকেটও রয়েছে। সবচেয়ে নটেবল TCP সকেট। কিন্তু এই পোস্ট শুধু ইউনিক্স সকেটের সাথে ডিল করে। আপনি কীভাবে পার্থক্য করবেন? ইউনিক্স সকেটের ফাইল নেম রয়েছে।

সबচেয়ে সিম্পল সকেট

আমরা দুটি ছোট প্রোগ্রাম দেখব।

প্রথমটি হলো "সার্ভার"। এটি সিম্পলি UnixServer ক্লাসের একটি ইনস্ট্যান্স তৈরি করে, তারপর server.accept ব্যবহার করে একটি কানেকশনের জন্য অপেক্ষা করে। যখন এটি একটি কানেকশন পায়, এটি একটি গ ریটিং এক্সচেঞ্জ করে।

এটি লক্ষ্য করুন যে accept এবং readline মেথড দুটোই প্রোগ্রাম এক্সিকিউশন ব্লক করে যতক্ষণ না সেগুলো যা অপেক্ষা করছে সেটি পায়।

require "socket" server = UNIXServer.new('/tmp/simple.sock') puts "==== Waiting for connection" socket = server.accept puts "==== Got Request:" puts socket.readline puts "==== Sending Response" socket.write("I read you loud and clear, good buddy!") socket.close 

তাহলে আমাদের একটি সার্ভার আছে। এখন আমাদের দরকার শুধু একটি ক্লায়েন্ট।

নিচের উদাহরণে, আমরা আমাদের সার্ভার দ্বারা তৈরি সকেটটি ওপেন করি। তারপর নরমাল IO মেথড ব্যবহার করে একটি গ রীটিং সেন্ড এবং রিসিভ করি।

require "socket" socket = UNIXSocket.new('/tmp/simple.sock') puts "==== Sending" socket.write("Hello server, can you hear me?\n") puts "==== Getting Response" puts socket.readline socket.close 

ডেমোন্স্ট্রেট করার জন্য, আমাদের প্রথমে সার্ভারটি রান করতে হবে। তারপর ক্লায়েন্টটি রান করব। নিচে রেজাল্ট দেখুন:

Unicorn কে Nginx-এ কানেক্ট করা: রুবিতে ইউনিক্স সকেটের প্র্যাক্টিক্যাল গাইড একটি সিম্পল UNIX সকেট ক্লায়েন্ট/সার্ভার ইন্টারঅ্যাকশনের উদাহরণ। ক্লায়েন্ট বামে। সার্ভার ডানে।

nginx-এর সাথে ইন্টারফেস করা

এখন যেহেতু আমরা জানি কীভাবে একটি unix socket "server" তৈরি করতে হয়, আমরা সহজেই nginx-এর সাথে ইন্টারফেস করতে পারি।

আমার কথা বিশ্বাস করছেন না? চলুন একটি কুইক প্রুফ-অফ-কনসেপ্ট করি। আমি উপরের কোডটি অ্যাডাপ্ট করব যাতে এটি সকেট থেকে যা পায় সেটি প্রিন্ট আউট করে।

require "socket" # সকেট তৈরি করুন এবং ফাইল সিস্টেমে "save" করুন server = UNIXServer.new('/tmp/socktest.sock') # একটি কানেকশন (nginx দ্বারা) এর জন্য অপেক্ষা করুন socket = server.accept # সকেট থেকে সবকিছু পড়ুন while line = socket.readline puts line.inspect end socket.close 

এখন যদি আমি nginx কনফিগার করি রিকোয়েস্টগুলো /tmp/socktest.sock সকেটে ফরোয়ার্ড করার জন্য, আমি দেখতে পাব nginx কী ডেটা পাঠাচ্ছে। (চিন্তা করবেন না, কনফিগারেশন একটু পরে ডিসকাস করব)

যখন আমি একটি ওয়েব রিকোয়েস্ট করি, nginx নিচের ডেটা আমার ছোট সার্ভারের কাছে পাঠায়:

Unicorn কে Nginx-এ কানেক্ট করা: রুবিতে ইউনিক্স সকেটের প্র্যাক্টিক্যাল গাইড

খুব কুল! এটি শুধু একটি নরমাল HTTP রিকোয়েস্ট কিছু একস্ট্রা হেডারের সাথে। এখন আমরা একটি রিয়েল অ্যাপ সার্ভার বানাতে প্রস্তুত। কিন্তু প্রথমে, nginx কনফিগারেশন ডিসকাস করি।

Nginx ইনস্টল এবং কনফিগার করা

আপনার ডেভেলপমেন্ট মেশিনে যদি ইতিমধ্যে nginx ইনস্টল না থাকে, একটু সময় নিন এবং এখনই করুন। OSX-এ homebrew দিয়ে এটি খুব সহজ:

brew install nginx 

এখন আমাদের nginx কনফিগার করতে হবে যাতে এটি localhost:2048-এ রিকোয়েস্ট ফরোয়ার্ড করে একটি আপস্ট্রিম সার্ভারের কাছে একটি সকেট নামযুক্ত /tmp/socktest.sock দিয়ে। সেই নাম কিছু স্পেশাল নয়। এটাকে শুধু আমাদের ওয়েব সার্ভার দ্বারা ব্যবহৃত সকেটের নামের সাথে ম‍্যাচ করতে হবে।

আপনি এই কনফিগারেশন /tmp/nginx.conf-এ সেভ করতে পারেন এবং তারপর nginx -c /tmp/nginx.conf কমান্ড দিয়ে nginx রান করুন সেটি লোড করার জন্য।

# Run nginx as a normal console program, not as a daemon daemon off; # Log errors to stdout error_log /dev/stdout info; events {} # Boilerplate http { # Print the access log to stdout access_log /dev/stdout; # Tell nginx that there's an external server called @app living at our socket upstream app { server unix:/tmp/socktest.sock fail_timeout=0; } server { # Accept connections on localhost:2048 listen 2048; server_name localhost; # Application root root /tmp; # If a path doesn't exist on disk, forward the request to @app try_files $uri/index.html $uri @app; # Set some configuration options on requests forwarded to @app location @app { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; proxy_pass https://app; } } } 

এই কনফিগারেশন nginx কে একটি নরমাল টার্মিনাল অ্যাপের মত রান করাতে বাধ্য করে, ডেমন کے মত নয়। এটি সকল লগ stdout-এ লিখে। যখন আপনি nginx রান করবেন তা কিছু এরকম দেখাবে:

Unicorn কে Nginx-এ কানেক্ট করা: রুবিতে ইউনিক্স সকেটের প্র্যাক্টিক্যাল গাইড Nginx নন-ডেমন মোডে রান করছে।

একটি DIY অ্যাপ্লিকেশন সার্ভার

এখন যেহেতু আমরা দেখেছি nginx কীভাবে আমাদের প্রোগ্রামের সাথে কানেক্ট করে, একটি সিম্পল অ্যাপ্লিকেশন সার্ভার বানানো খুব সহজ ব্যাপার। যখন nginx একটি রিকোয়েস্ট আমাদের সকেটে ফরোয়ার্ড করে, সেটি একটি স্ট্যান্ডার্ড HTTP রিকোয়েস্ট। একটু টিংকার করার পর আমি বুঝতে পেরলাম যে যদি সকেট একটি বৈধ HTTP রেসপন্স রিটার্ন করে, তবে ব্রাউজারে সেটি ডিসপ্লে হবে।

নিচের অ্যাপ্লিকেশন যেকোনো রিকোয়েস্ট নেয় এবং একটি টাইমস্ট্যাম্প ডিসপ্লে করে।

require "socket" # Connection creates the socket and accepts new connections class Connection attr_accessor :path def initialize(path:) @path = path File.unlink(path) if File.exists?(path) end def server @server ||= UNIXServer.new(@path) end def on_request socket = server.accept yield(socket) socket.close end end # AppServer logs incoming requests and renders a view in response class AppServer attr_reader :connection attr_reader :view def initialize(connection:, view:) @connection = connection @view = view end def run while true connection.on_request do |socket| while (line = socket.readline) != "\r\n" puts line end socket.write(view.render) end end end end # TimeView simply provides the HTTP response class TimeView def render %[HTTP/1.1 200 OK The current timestamp is: #{ Time.now.to_i } ] end end AppServer.new(connection: Connection.new(path: '/tmp/socktest.sock'), view: TimeView.new).run 

এখন যদি আমি nginx এবং আমার স্ক্রিপ্ট দুটো ফায়ার আপ করি, আমি localhost:2048-এ যেতে পারি। রিকোয়েস্টগুলো আমার অ্যাপে পাঠায়। এবং রেসপন্স ব্রাউজার tarafından রেন্ডার হয়। প্রিটি কুল!

Unicorn কে Nginx-এ কানেক্ট করা: রুবিতে ইউনিক্স সকেটের প্র্যাক্টিক্যাল গাইড HTTP রিকোয়েস্টগুলো আমাদের সিম্পল অ্যাপ সার্ভার দ্বারা STDOUT-এ লগ হচ্ছে

এবং এখানে আমাদের পরিশ্রমের গৌরবময় ফল। নिहারুন! একটি টাইমস্ট্যাম্প!

Unicorn কে Nginx-এ কানেক্ট করা: রুবিতে ইউনিক্স সকেটের প্র্যাক্টিক্যাল গাইড সার্ভার একটি টাইমস্ট্যাম্প রিটার্ন করে যা ব্রাউজারে ডিসপ্লে হয়


  1. রুবিতে এনভায়রনমেন্ট ভেরিয়েবল মাস্টার করুন: একটি প্র্যাকটিক্যাল গাইড

  2. রুবি ম্যাট্রিক্স বুঝতে: ডেফিনিশন, অ্যাপ্লিকেশন এবং কীভাবে তৈরি করবেন

  3. রুবি Struct ও OpenStruct: দক্ষ ভ্যালু অবজেক্টস

  4. রুবি নেটওয়ার্ক প্রোগ্রামিং: সকেট দিয়ে কাস্টম ক্লায়েন্ট ও সার্ভার বানান