কম্পিউটার

ইউনিকর্ন কীভাবে এনজিনক্সের সাথে কথা বলে - রুবিতে ইউনিক্স সকেটগুলির একটি ভূমিকা

রুবি অ্যাপ্লিকেশন সার্ভারগুলি সাধারণত nginx এর মতো একটি ওয়েব সার্ভারের সাথে একসাথে ব্যবহৃত হয়। যখন ব্যবহারকারী আপনার Rails অ্যাপ থেকে একটি পৃষ্ঠার অনুরোধ করে, nginx অ্যাপ্লিকেশন সার্ভারে অনুরোধটি অর্পণ করে। কিন্তু ঠিক কিভাবে কাজ করে? কিভাবে nginx ইউনিকর্নের সাথে কথা বলে?

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

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

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

ইউনিক্স সকেটগুলি একটি প্রোগ্রামকে অন্যটির সাথে এমনভাবে কথা বলতে দেয় যা ফাইলগুলির সাথে কাজ করার মতো। এগুলি এক ধরনের আইপিসি, বা আন্তঃপ্রক্রিয়া যোগাযোগ।

একটি সকেটের মাধ্যমে অ্যাক্সেসযোগ্য হতে, আপনার প্রোগ্রামটি প্রথমে একটি সকেট তৈরি করে এবং এটিকে একটি ফাইলের মতো ডিস্কে "সংরক্ষণ" করে। এটি ইনকামিং সংযোগের জন্য সকেট নিরীক্ষণ করে। যখন এটি একটি পায়, এটি ডেটা পড়তে এবং লিখতে স্ট্যান্ডার্ড IO পদ্ধতি ব্যবহার করে।

রুবি কয়েকটি ক্লাসের মাধ্যমে ইউনিক্স সকেটের সাথে কাজ করার জন্য আপনার প্রয়োজনীয় সবকিছু সরবরাহ করে:

  • UNIX*সার্ভার *- এটি সকেট তৈরি করে, ডিস্কে সংরক্ষণ করে এবং নতুন সংযোগের জন্য আপনাকে এটি নিরীক্ষণ করতে দেয়।

  • UNIX*সকেট * - 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

প্রদর্শন করতে, আমাদের প্রথমে সার্ভার চালাতে হবে। তারপর আমরা ক্লায়েন্ট চালাই। আপনি নীচের ফলাফল দেখতে পারেন:

ইউনিকর্ন কীভাবে এনজিনক্সের সাথে কথা বলে - রুবিতে ইউনিক্স সকেটগুলির একটি ভূমিকা একটি সাধারণ ইউনিক্স সকেট ক্লায়েন্ট/সার্ভার ইন্টারঅ্যাকশনের উদাহরণ। ক্লায়েন্ট বাম দিকে। সার্ভারটি ডানদিকে রয়েছে৷

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

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

বিশ্বাস করবেন না? আসুন ধারণার একটি দ্রুত প্রমাণ করি। আমি উপরের কোডটিকে মানিয়ে নিতে যাচ্ছি যাতে এটি সকেট থেকে প্রাপ্ত সমস্ত কিছু মুদ্রণ করে।

require "socket"

# Create the socket and "save it" to the file system
server = UNIXServer.new('/tmp/socktest.sock')

# Wait until for a connection (by nginx)
socket = server.accept

# Read everything from the socket
while line = socket.readline
  puts line.inspect
end

socket.close

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

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

ইউনিকর্ন কীভাবে এনজিনক্সের সাথে কথা বলে - রুবিতে ইউনিক্স সকেটগুলির একটি ভূমিকা

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

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

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

brew install nginx

এখন আমাদের স্থানীয় হোস্ট:2048-এ অনুরোধ ফরওয়ার্ড করার জন্য nginx কনফিগার করতে হবে /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 চালান তখন এটি দেখতে এরকম কিছু হওয়া উচিত:

ইউনিকর্ন কীভাবে এনজিনক্সের সাথে কথা বলে - রুবিতে ইউনিক্স সকেটগুলির একটি ভূমিকা 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 ফায়ার করি, আমি লোকালহোস্টে যেতে পারি:2048। আমার অ্যাপে অনুরোধ পাঠানো হয়। এবং প্রতিক্রিয়া ব্রাউজার দ্বারা রেন্ডার করা হয়. বেশ সুন্দর!

ইউনিকর্ন কীভাবে এনজিনক্সের সাথে কথা বলে - রুবিতে ইউনিক্স সকেটগুলির একটি ভূমিকা HTTP অনুরোধগুলি আমাদের সাধারণ অ্যাপ সার্ভার দ্বারা STDOUT এ লগ করা হয়

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

ইউনিকর্ন কীভাবে এনজিনক্সের সাথে কথা বলে - রুবিতে ইউনিক্স সকেটগুলির একটি ভূমিকা সার্ভার একটি টাইমস্ট্যাম্প প্রদান করে যা ব্রাউজারে প্রদর্শিত হয়


  1. রুবিতে পরিবেশের ভেরিয়েবলগুলি কীভাবে ব্যবহার করবেন

  2. একটি ম্যাট্রিক্স কি এবং রুবিতে এটি কীভাবে ব্যবহার করবেন?

  3. রুবিতে স্ট্রাকট এবং ওপেনস্ট্রাক্ট কীভাবে ব্যবহার করবেন

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