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

সাবডোমেন ব্যবহার করে নিরাপদ মাল্টি-টেন্যান্ট রুবি অন রেলস অ্যাপ তৈরি করুন

মাল্টি-টেন্যান্সির সংজ্ঞা অনুযায়ী, যখন একটি অ্যাপ একাধিক টেন্যান্টের সেবা দেয়, তখন এর মানে হল কিছু ব্যবহারকারী গ্রুপ সফটওয়্যার ইনস্ট্যান্সে সাধারণ অ্যাক্সেস শেয়ার করে। মাল্টি-টেন্যান্সি সমর্থনকারী একটি অ্যাপের চমৎকার উদাহরণ হল জিরা প্ল্যাটফর্ম, যেখানে প্রতিটি কোম্পানির সাবডোমেন থাকে সফটওয়্যারটি অ্যাক্সেস করার জন্য, উদাহরণস্বরূপ mycompany.atlassian.net।

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

এই আর্টিকেল পড়ার পর আপনি সক্ষম হবেন:

  • বিভিন্ন ধরনের মাল্টি-টেন্যান্ট অ্যাপ নিয়ে আলোচনা করা এবং নির্দিষ্ট পদ্ধতি কখন সঠিক পছন্দ সেটি বলা,
  • একাধিক টেন্যান্টের জন্য সমর্থনসহ রুবি অন রেলস অ্যাপ্লিকেশন তৈরি করা, এবং
  • রুবি অন রেলস অ্যাপ্লিকেশনের ভিতরে আপনার গ্রাহকদের জন্য কাস্টম সাবডোমেন ব্যবহার করা।

এই আর্টিকেল অনুসরণ করার এবং এর সর্বোত্তম সুবিধা পाने 위해서는 রেলস সম্পর্কে মূল জ্ঞান প্রয়োজন।

তত্ত্বে মাল্টি-টেন্যান্সি

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

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

ডেটাবেস-রো লেভেল

আপনার অ্যাপ্লিকেশনে একাধিক ডেটাবেস ব্যবহার না চাইলে, আপনি একটি কেনদ्रीय ডেটাবেসে কাজ করার পদ্ধতি বেছে নিতে পারেন। ডেটাবেসের প্রতিটি টেবিলে tenant_id কলাম থাকে যা অ্যাপ্লিকেশনের ভিতরে প্রতিটি কোয়ারীতে ব্যবহৃত হয় নির্দিষ্ট টেন্যান্টেরgehör্য ডেটা বের করার জন্য।

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

স্কিমা লেভেল

আপনি এখনও একটি কেনদ्रीय ডেটাবেস রাখতে পারেন কিন্তু প্রতিটি টেন্যান্টের জন্য আলাদা টেবিল এবং স্কিমা সহ। ডেটাবেস-রো লেভেল পদ্ধতির বিপরীতে, টেন্যান্টের মধ্যে সুইচ করার সময় আপনাকে কোয়ারি পরিবর্তন করার বদলে টেবিলগুলোর সার্চ পাথ পরিবর্তন করতে হবে। পোস্টগ্রেএসকিউএলে আপনি search_path সেট স্টেটমেন্ট ব্যবহার করতে পারেন, এবং মাইএসকيوএলে use স্টেটমেন্ট ব্যবহার করে স্কিমা সুইচ করতে পারেন।

এই পদ্ধতি বেছে নেওয়ার আগে নিশ্চিত হন যে আপনার ডিবি সার্ভারে উপরে উল্লিখিত স্টেটমেন্টগুলো ব্যবহার করা সম্ভব। এছাড়া মনে রাখুন যে নতুন টেন্যান্ট যোগ করা তুলনামূলকভাবে ধীর কারণ আপনাকে নতুন স্কিমা তৈরি করতে হবে এবং ডেটাবেসে টেবিল তৈরি করতে হবে।

ডেটাবেস লেভেল

যদি আপনি প্রতিবার নতুন টেন্যান্ট যোগ করার সময় নতুন ডেটাবেসের খরচ বাহন করতে পারেন, তবে এই পদ্ধতি আপনার জন্য সঠিক হতে পারে। আলোচিত সব আর্কিটেকচারের মধ্যে নতুন টেন্যান্ট যোগ করার ক্ষেত্রে এটি সবচেয়ে ধীর পদ্ধতি।

ডেটা লিক হওয়ার সম্ভাবনা এখানে সবচেয়ে কম কারণ অন্য টেন্যান্টে সুইচ করার জন্য আপনাকে ডেটাবেসের সাথে নতুন সংযোগ স্থাপন করতে হয়। আপনি যদি চান তবে প্রতিটি ব্যবহারকারী গ্রুপের ডেটাবেস কাঠামো সহজে পরিবর্তন করতে পারেন।

অ্যাপ্লিকেশন স্কেলেটন তৈরি করা

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

লেখা написার 시점에서 রুবির সর্বশেষ ভার্সন ২.৭.২ এবং রুবি অন রেলস জেমের ৬.১ RC১। নিশ্চিত হন যে আপনার সিস্টেমে রুবির সঠিক ভার্সন ইনস্টল করা আছে এবং ফ্রেমওয়ার্কের সঠিক ভার্সন ইনস্টল করার চেষ্টা করুন:

gem install rails -v 6.1.0.rc1

এখন নিচের কমান্ড দিয়ে প্রজেক্ট ফাইলগুলো জেনারেট করুন:

rails _6.1.0.rc1_ new tenantapp -d=mysql

প্রজেক্ট ডিরেক্টরিতে প্রবেশ করুন, সার্ভার চালু করুন এবং স্বাগত স্ক্রিন দেখতে পাচ্ছেন কিনা চেক করুন যাতে আমরা এগিয়ে যেতে পারি:

cd tenantapp/ rails s

এক ডেটাবেস সহ মাল্টি-টেন্যান্ট রেলস অ্যাপ্লিকেশন

এখন কোডিং শুরু করা যাক। এই অংশে আমি আপনাকে দেখাব কিভাবে আপনার রেলস অ্যাপ্লিকেশনে মাল্টি-টেন্যান্সি বাস্তবায়ন করা যায়। আমি এক ডেটাবেস এবং এক স্কিমা वाली পদ্ধতি ব্যবহার করব।

পরিকল্পনা নিম্নরূপ:

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

টেস্ট ডেটা প্রস্তুত করা

ধরুন আমরা একটি ব্লগ প্ল্যাটফর্ম তৈরি করছি যেখানে ব্যবহারকারীরা একাধিক লেখকের প্রকাশিত আর্টিকেল দেখতে পারবে।

প্রথমে লেখক মডেল তৈরি করব যা লেখকের ডেটা সংরক্ষণ করবে:

rails g scaffold author slug:string name:string description:string rake db:create rake db:migrate

এখন https://localhost:3000/authors ঠিকানায় যান এবং কিছু লেখক যোগ করুন যাতে পরে তাদের আর্টিকেলে অ্যাসাইন করা যায়।

পরবর্তী ধাপ হল আর্টিকেল তৈরি করা:

rails g scaffold article title:string content:text rake db:migrate

মাল্টি-টেন্যান্সি সমর্থন যোগ করা

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

ডেটাবেসে সঠিক মাইগ্রেশন তৈরি করা

rails g migration AddTenantIdToArticle tenant_id:integer rake db:migrate

উপরের মাইগ্রেশন আমাদের Article মডেলে নতুন কলাম যোগ করবে। এই কলামটি কোনো কোয়ারিতে ব্যবহার হবে বর্তমান টেন্যান্টের জন্য নির্ধারিত ডেটা মাত্র বের করার জন্য।

আর্টিকেলকে টেন্যান্টের সাথে সংযুক্ত করা

এই ধাপে আমি কোড আপডেট করব যাতে প্রদত্ত লেখককে আর্টিকেলের সাথে অ্যাসাইন করা যায় এবং পরে শুধু নির্বাচিত লেখকের জন্য আর্টিকেল রেন্ডার করা যায়। app/controllers/articles_controller.rb খুলুন এবং নিচের পরিবর্তনগুলো যোগ করুন:

class ArticlesController < ApplicationController before_action :set_article, only: [:show, :edit, :update, :destroy] before_action :set_authors, only: [:edit, :update, :new, :create] # ... private # শুধু বিশ্বস্ত প্যারামিটারগুলোর তালিকা অনুমতি দেওয়া। def article_params params.require(:article).permit(:title, :content, :tenant_id) end def set_authors @authors = Author.all end end

আমাদের ভিউতে এখন @authors ভেরিয়েবল ব্যবহার করা যাবে যেটিতে আমাদের অ্যাপে যোগ করা লেখকদের কালেকশন থাকে। এখন সিলেক্ট ফিল্ড যোগ করুন যেটিতে লেখকদের নাম থাকবে এবং সঠিক tenant_id অ্যাসাইন করবে। app/views/articles/_form.html.erb খুলুন এবং নিচের সেকশন যোগ করুন:

<div className="field"> <%= form.label :author %> <%= form.select :tenant_id, options_from_collection_for_select(@authors, 'id', 'name', article.tenant_id), include_blank: true %> </div>

এগিয়ে যান এবং কিছু লেখক তৈরি করুন তারপর কিছু আর্টিকেল তৈরি করুন যাতে পরে নির্দিষ্ট লেখকের জন্য মাত্র আর্টিকেল রেন্ডার করা যায়।

কাস্টম সাবডোমেনের জন্য সমর্থন যোগ করা

আমরা Джон ডো নামে লেখক তৈরি করেছি এবং স্লাগ মান সেট করেছি johndoe। আমাদের লক্ষ্য হল https://johndoe.localhost:3000/ ঠিকানায় গিয়ে শুধু Джон ডোstwa সম্পর্কিত ডেটা দেখা।

সাবডোমেন কনফিগারেশন

আমরা টেন্যান্ট সেট হলে আর্টিকেল পরিচালনা এবং ভিজিট করতে চাই। এটা অর্জন করা যায় config/routes.rb ফাইল আপডেট করে এবং আর্টিকেল রিসোর্সের ডেফিনিশন কনস্ট্রেইন্টস ব্লকে র‍্যাপ করে:

Rails.application.routes.draw do constraints subdomain: /.*/ do resources :articles end resources :authors end

ডিফল্টলি রেলস টপ-লেভেল ডোমেনের দৈর্ঘ্য ১ সেট করে, কিন্তু আমরা লোকালহোস্ট ব্যবহার করতে চাই তাই এই সেটিং ০ করতে হবে। এটা করা যায় config/environments/development.rb ফাইলে নিচের লাইন যোগ করে:

config.action_dispatch.tld_length = 0

মাল্টি-টেন্যান্সির সাথে সাবডোমেন কাজ করানো

এখন যেকোনো লেখককে আর্টিকেলে অ্যাসাইন করা সম্ভব। কিন্তু সাবডোমেন ব্যবহৃত হলে এটা সম্ভব হওয়া উচিত নয়। আমাদের ArticlesController এর আচরণ পরিবর্তন করতে হবে, এবং সব লেখক সেট করার বদলে সাবডোমেন দ্বারা অনুরোধ করা লেখক সেট করতে হবে:

 class ArticlesController < ApplicationController before_action :set_author before_action :set_article, only: [:show, :edit, :update, :destroy] # GET /articles # GET /articles.json def index @articles = Article.where(tenant_id: @author.id) end # ... private def set_article @article = Article.find_by!(id: params[:id], tenant_id: @author.id) end # ... def set_author @author = Author.find_by!(slug: request.subdomain) end end

আমি কন্ট্রোলারে কিছু পরিবর্তন করেছি:

  • set_authors মেথডের বদলে set_author মেথড ডিফাইন করেছি, যেটি সাবডোমেনের মাধ্যমে অনুরোধ করা লেখক সেট করে। এই মেথডকে before_filter-এ set_article কল করার আগে কল করা জরুরি। আর্টিকেল সেট করার চেষ্টা করার আগে লেখক অ্যাসাইন করা থাকতে হবে।
  • set_article মেথড আপডেট করেছি যাতে প্রদত্ত আইডি এবং অ্যাসাইন করা লেখক সহ আর্টিকেল খোঁজা যায়। আমরা টমের তৈরি করা আর্টিকেল রেন্ডার করব না যখন আমাদের বর্তমান টেন্যান্ট জন।
  • ইন্ডেক্স একশন আপডেট করেছি যাতে শুধু আমাদের বর্তমান টেন্যান্টের জন্য অ্যাসাইন করা আর্টিকেলগুলো সিলেক্ট করা যায়।

যখন আপনি মাল্টি-টেন্যান্ট অ্যাপে কাজ করবেন এবং এক ডেটাবেস ও এক স্কিমা ব্যবহার করবেন, তখন আপনাকে সবসময় মনে রাখতে হবে যে যেকোনো কোয়ারী tenant_id কলাম দ্বারা স্কোপ করা হয়েছে; অন্যথায় আপনি অনুরোধ করা টেন্যান্টের জন্য অ্যাসাইন না করা ডেটা প্রদান করবেন।

কন্ট্রোলার আপডেট হয়েছে, তাই পরবর্তী ধাপ হল ফর্ম ভিউ আপডেট করা। app/views/articles/_form.html.erb ফাইল খুলুন এবং আগের সেকশনটি সিম্পল হিডেন ফিল্ড দিয়ে রিপ্লেস করুন:

<%= form.hidden_field :tenant_id, value: @author.id %>

এই পরিবর্তনের আগে, ব্যবহারকারী ফর্ম ব্যবহার করে আর্টিকেলের লেখক সিলেক্ট করতে পারত। এখন ব্যবহারকারী ওয়েবসাইট ঠিকানায় দেওয়া সাবডোমেন ব্যবহার করে সব অ্যাকশনের জন্য লেখক বেছে নিতে পারে।

এখন আমরা তৈরি করা কোড টেস্ট করতে পারি। একটি নতুন লেখক তৈরি করুন, উদাহরণস্বরূপ জন ডো নাম এবং স্লাগ johndoe। https://johndoe.localhost:3000/articles/new ঠিকানায় যান এবং একটি নতুন আর্টিকেল যোগ করুন। নতুন আর্টিকেল যোগ করার পর, আপনি তা লিস্টে দেখতে পারবেন https://johndoe.localhost:3000/articles ঠিকানায়।

অভিনন্দন! আপনি কোন এক মাল্টি-টেন্যান্ট অ্যাপ তৈরি করেছেন যেখানে প্রতিটি লেখকের নিজস্ব সাবডোমেন আছে।

আরও উন্নতি

এখন আপনি অ্যাপ্লিকেশনের কোড নতুন ফিচার যোগ করে প্রসারিত করতে পারেন। আমাদের ব্লগ প্ল্যাটফর্ম খুব সহজ; হয়তো এখন কমেন্ট সেকশন যোগ করার সময়? আপনি কোন ফাংশনালিটি যোগ করুন, মনে রাখবেন নতুন মডেলে tenant_id কলাম যোগ করতে হবে এবং রিসোর্স কোয়ারি করার সময় এটি ব্যবহার করতে হবে।

আপনি একটি স্পেশাল স্কোপ তৈরি করে কনসার্নে র‍্যাপ করতে পারেন:

module Tenantable extend ActiveSupport::Concern included do scope :for_author, -> (author) { where(tenant_id: author.id) } end end

তারপর টেন্যান্টের ডেটা ধারণকারী প্রতিটি মডেলে এটি ব্যবহার করুন:

class Article < ApplicationRecord include Tenantable end author = Author.find(1) Article.for_author(author)

উপরের পদ্ধতিতে, tenant_id কলাম রিনেম করা বা টেন্যান্ট-সম্পর্কিত ডেটা কোয়ারি করার সময় আরও শর্ত যোগ করা প্রয়োজন হলে আপনাকে শুধু এক জায়গা আপডেট করতে হবে।

একাধিক ডেটাবেস সহ মাল্টি-টেন্যান্ট রেলস অ্যাপ্লিকেশন

পূর্বের প্যারাগ্রাফে, আমরা একটি রেলস অ্যাপ্লিকেশন তৈরি করেছি যা এক ডেটাবেস এবং এক স্কিমায় একাধিক টেন্যান্ট সমর্থন করে। এই পদ্ধতির সবচেয়ে বড় অসুবিধা হল ডেটা লিকের উচ্চ সম্ভাবনা।

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

পরিকল্পনা নিম্নরূপ:

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

টেস্ট ডেটা প্রস্তুত করা

ধরুন আমরা একটি ব্লগ প্ল্যাটফর্ম তৈরি করছি যেখানে ব্যবহারকারীরা একাধিক লেখকের প্রকাশিত আর্টিকেল দেখতে পারবে। প্রতিটি লেখকের একটি ডেডিকেটেড ডেটাবেস থাকবে।

Author মডেল দিয়ে শুরু করুন স্ক্যাফোল্ডেড ফিচারসহ যা নতুন লেখক দেখতে এবং তৈরি করতে সাহায্য করবে:

rails g scaffold author slug:string name:string description:string rake db:create rake db:migrate

এখন https://localhost:3000/authors ভিজিট করুন এবং দেখুন রেলস কী জেনারেট করেছে।

নতুন লেখক যোগ করা

আমি জন ডো নামে একটি নতুন লেখক তৈরি করেছি এবং স্লাগ johndoe। স্লাগ মান পরে ব্যবহার করা হবে সাবডোমেন ব্যবহার করে কোন লেখকের তথ্য প্রদর্শন করা উচিত সেটি ডিটেক্ট করার জন্য।

যেহেতু প্রতিটি লেখকের আলাদা ডেটাবেস থাকবে, আমাদের জনের জন্য ম্যানুয়ালি নতুন ডেটাবেস যোগ করতে হবে। config/database.yml খুলুন এবং নিচের পরিবর্তনগুলো যোগ করুন:

development: primary: <<: *default database: tenantapp_development primary_johndoe: <<: *default database: tenantapp_johndoe_development migrations_paths: db/tenants_migrations

আমরা আমাদের টেন্যান্টদের দ্বারা ব্যবহৃত মাইগ্রেশনগুলোর জন্য আলাদা একটি ডিরেক্টরি ব্যবহার করব। সেগুলো কেনদ्रीय ডেটাবেসে দরকার নেই। এখন জনের জন্য ডেটাবেস তৈরি করতে পারেন ডিফল্ট কমান্ড ব্যবহার করে:

rake db:create

আর্টিকেল যোগ করা

এখন Article মডেল স্ক্যাফোল্ড করুন কন্ট্রোলার এবং ভিউসহ:

rails g scaffold article title:string content:text --database primary_johndoe

আমি --database প্যারাম পাস করেছি যাতে রেলস বুঝতে পারে যে মাইগ্রেশন ডিফল্ট db/migrations ডিরেক্টরিতে না যাবে যা প্রাইমারি ডেটাবেস দ্বারা ব্যবহৃত হয়। এখন মাইগ্রেট কমান্ড চালান:

rake db:migrate

এখন আমাদের দুটি স্কিমা আছে: db/schema.rb এবং db/primary_johndoe_schema.rb। আপনি যদি টেন্যান্টদের জন্য ভিন্ন টেবিল তৈরি করতে চান, তবে আপনি config/database.yml ফাইলে প্রদত্ত টেন্যান্টের জন্য ইউনিক migrations_path মান সেট করে তা অর্জন করতে পারেন। এই আর্টিকেলে, আমরা সব টেন্যান্টের জন্য একই টেবিল চাই, তাই মাইগ্রেশন পাথ একই থাকবে।

মাল্টি-টেন্যান্সি সমর্থন যোগ করা

যে অ্যাপ্লিকেশনে এক ডেটাবেসে মাল্টি-টেন্যান্সি সমর্থন করা হয়, সেখানে প্রদত্ত টেন্যান্টের ডেটা পেতে হলে শুধু ডেটাবেস কোয়ারি আপডেট করতে হয় সঠিক tenant_id মান দিয়ে। আমাদের কেসে, প্রতিটি টেন্যান্টের নিজস্ব ডেটাবেস আছে, তাই আমাদের ডেটাবেসের মধ্যে সুইচ করতে হবে।

রেলস ৬.১ হরিজেন্টাল শার্ডিং-এর জন্য বিল্ট-ইন সমর্থন নিয়ে আসে। শার্ড হল একটি হরিজেন্টাল ডেটা পার্টিশন যেটি মোট ডেটাসেটের একটি সাবসেট ধারণ করে। আমরা সব লেখকের আর্টিকেল এক টেবিলে এক ডেটাবেসে রাখতে পারতাম, কিন্তু শার্ডিং 덕분에 আমরা ডেটাকে একই কাঠামোवाले একাধিক টেবিলে বিভক্ত করতে পারি কিন্তু আলাদা আলাদা ডেটাবেসে।

আমাদের শার্ডগুলো ডিফাইন করি সমস্ত মডেলের পেরেন্ট ক্লাসে। সেগুলো app/models/application_record.rb এর অধীনে সংরক্ষিত:

ActiveRecord::Base.connected_to(role: :reading, shard: :johndoe) do Article.all # জনের তৈরি করা সব আর্টিকেল পান end

connected_to ব্লকে আমাদের কল র‍্যাপ না করলে ডিফল্ট শার্ড ব্যবহার হবে। আগে বড়তে দেওয়ার আগে, আমাদের এক আরও পরিবর্তন আনতে হবে। যেহেতু সব শার্ড একই ডেটা কাঠামো শেয়ার করে, আমরা app/models/primary_johndoe_record.rb মডেল ডিলিট করতে পারি যা আর্টিকেল স্ক্যাফোল্ড করার সময় অটোমেটিকভাবে তৈরি হয়েছিল।

আমাদের app/models/article.rb মডেল এডিট করতে হবে এবং পেরেন্ট ক্লাস PrimaryJohndoeRecord থেকে ApplicationRecord এ পরিবর্তন করতে হবে:

class Article < ApplicationRecord end

আরও টেন্যান্ট যোগ করা

বর্তমানে আমাদের ডেটাবেসে শুধু একজন লেখক আছে। আমাদের টেন্যান্টদের (ডেটাবেস) মধ্যে সুইচ করার ফাংশনালিটি টেস্ট করতে, আমাদের একজন আর লেখক যোগ করতে হবে। https://localhost:3000/authors/new ঠিকানায় যান এবং একটি নতুন লেখক যোগ করুন। আমি টিম ডো নামে লেখক যোগ করেছি এবং স্লাগ timdoe।

নতুন লেখকের রেকর্ড আছে, তাই আমাদের একটি নতুন ডেটাবেস ডিফাইন করতে হবে:

development: primary: <<: *default database: tenantapp_development primary_johndoe: <<: *default database: tenantapp_johndoe_development migrations_paths: db/tenants_migrations primary_timdoe: <<: *default database: tenantapp_timdoe_development migrations_paths: db/tenants_migrations

এখন নতুন ডেটাবেস তৈরি করুন এবং মাইগ্রেশন চালান:

rake db:create rake db:migrate

শেষ ধাপ হল ApplicationRecord মডেল আপডেট করা এবং একটি নতুন শার্ড ডিফাইন করা:

class ApplicationRecord < ActiveRecord::Base self.abstract_class = true connects_to shards: { default: { writing: :primary, reading: :primary }, johndoe: { writing: :primary_johndoe, reading: :primary_johndoe }, timdoe: { writing: :primary_timdoe, reading: :primary_timdoe }, } end

এখন আপনি প্রতিটি লেখকের জন্য আর্টিকেল তৈরি করতে পারেন:

ActiveRecord::Base.connected_to(role: :writing, shard: :johndoe) do Article.create!(title: 'Article from John', content: 'content') end ActiveRecord::Base.connected_to(role: :writing, shard: :timdoe) do Article.create!(title: 'Article from Tim', content: 'content') end

কাস্টম সাবডোমেনের জন্য সমর্থন যোগ করা

আমরা এখনও প্রদত্ত লেখকের আর্টিকেল লিস্ট ভিজিট করতে পারছি না কারণ আমরা জানি না কখন জনের আর্টিকেল দেখাব এবং কখন টিমের। আমরা কাস্টম সাবডোমেন বাস্তবায়ন করে এই সমস্যাটি সমাধান করব। https://johndoe.localhost:3000/articles ভিজিট করলে জনের আর্টিকেল দেখাবে, এবং https://timedoe.localhost:3000/articles ভিজিট করলে টিমের আর্টিকেল দেখাবে।

সাবডোমেন কনফিগারেশন

আমরা টেন্যান্ট সেট হলে আর্টিকেল পরিচালনা এবং ভিজিট করতে চাই। এটা অর্জন করা যায় config/routes.rb ফাইল আপডেট করে এবং আর্টিকেল রিসোর্সের ডেফিনিশন কনস্ট্রেইন্টস ব্লকে র‍্যাপ করে:

Rails.application.routes.draw do constraints subdomain: /.*/ do resources :articles end resources :authors end

ডিফল্টলি রেলস টপ-লেভেল ডোমেনের দৈর্ঘ্য ১ সেট করে, কিন্তু আমরা লোকালহোস্ট ব্যবহার করতে চাই তাই এই সেটিং ০ করতে হবে। এটা করা যায় config/environments/development.rb ফাইলে নিচের লাইন যোগ করে:

config.action_dispatch.tld_length = 0

মাল্টি-টেন্যান্সির সাথে সাবডোমেন কাজ করানো

বর্তমান টেন্যান্টের জন্য ডেটাবেস পড়াকে স্ট্যান্ডার্ডাইজ করতে, আমি Tenantable নামের একটি কন্ট্রোলার কনসার্ন তৈরি করব। এটি read_with_tenant মেথড প্রদান করে, যেটি একটি ব্লক গ্রহণ করে এবং অনুরোধ করা টেন্যান্টের কনটেক্সটে এটি এক্সিকিউট করে:

module Tenantable extend ActiveSupport::Concern private def read_with_tenant(&block) author = Author.find_by!(slug: request.subdomain) ActiveRecord::Base.connected_to(role: :reading, shard: author.slug.to_sym) do block.call end end end

এই ফাইলটি app/controllers/concerns/tenantable.rb নামে সংরক্ষণ করুন এবং ArticlesController-এ ইনক্লুড করুন:

class ArticlesController < ApplicationController include Tenantable before_action :set_article, only: [:show, :edit, :update, :destroy] def index read_with_tenant do @articles = Article.all end end # ... end

এখন আপনি https://johndoe.localhost:3000/articles বা https://timdoe.localhost:3000/articles ভিজিট করতে পারেন, এবং আপনি লিস্টে ভিন্ন আর্টিকেল দেখবেন।

আপনি যদি ফর্ম ব্যবহার করে নতুন আর্টিকেল তৈরি করতে চান, তবে আপনাকে write_with_tenant নামে একটি নতুন মেথড ডিফাইন করতে হবে এবং Tenantable কনসার্ন এবং ArticlesController-এর মেথডগুলো ভাবে আপডেট করতে হবে।

আরও উন্নতি

উপরে উপস্থাপিত পদ্ধতি শুধু একটি সিম্পল র‍্যাপার মেথড যেটি কোড ব্লক এক্সিকিউট করে প্রদত্ত ডেটাবেস সংযোগের কনটেক্সটে। এটাকে আরও ইউনিভার্সাল बनाने के জন্য, আপনি একটি মিডলওয়্যার তৈরি করতে পারেন যা সাবডোমেন পার্স করবে এবং যেকোনো কোড এক্সিকিউট করার আগে সংযোগ স্থাপন করবে:

ActiveRecord::Base.establish_connection(:primary_timdoe)

চূড়ান্ত সমাধান আপনার প্রয়োজন এবং নির্দিষ্ট টেন্যান্টের জন্য অ্যাসাইন করা ডেটা ব্যবহার করার জায়গার সংখ্যার উপর নির্ভর করে।

সারসংক্ষেপ

অভিনন্দন, আপনি মাল্টি-টেন্যান্ট রেলস অ্যাপ্লিকেশনের দুটি ভার্সন তৈরি করেছেন এবং আধুনিক ওয়েব অ্যাপ্লিকেশনে একাধিক টেন্যান্টের সাথে মোকাবিলার বিভিন্ন উপায় সম্পর্কে জ্ঞান অর্জন করেছেন।

দ্রুত সারসংক্ষেপ করি আমরা এই আর্টিকেলে কী শিখেছি:

  • ওয়েব অ্যাপ্লিকেশনে তিনটি প্রধান মাল্টি-টেন্যান্সি লেভেল আছে - ডেটাবেস-রো, স্কিমা, এবং ডেটাবেস লেভেল।
  • প্রতিটি পদ্ধতির নিজস্ব সুবিধা এবং অসুবিধা আছে, এবং আপনার পছন্দ হার্ডওয়্যার সম্ভাবনা এবং টেন্যান্ট তথ্যের আলাদা করার লেভেলের উপর নির্ভর করে।
  • রুবি অন রেলস ফ্রেমওয়ার্কের মধ্যে কোনো এক্সটার্নাল লাইব্রেরি ছাড়া সব মাল্টি-টেন্যান্সি লেভেল বাস্তবায়ন করা সম্ভব।
  • রুবি অন রেলস কাস্টম সাবডোমেন বাক্সের বাইরে থেকে সমর্থন করে, তাই এটি মাল্টি-টেন্যান্ট অ্যাপ্লিকেশনের জন্য একदम পर्फেক্ট অডিশন যেখানে প্রতিটি টেন্যান্টের নিজস্ব সাবডোমেন অ্যাসাইন করা থাকতে পারে।

আশা করি আপনি এই আর্টিকেল পড়ে উপভোগ করেছেন এবং মাল্টি-টেন্যান্ট রুবি অন রেলস অ্যাপ্লিকেশন বিল্ড করেছেন।

P.S. আপনি যদি রুবি ম্যজিক পোস্টগুলো প্রেস থেকে বের होते সাথে সাথে পড়তে চান, আমাদের রুবি ম্যজিক নিউজলেটার সাবস্ক্রাইব করুন এবং কখনো একটি পোস্টও মিস করবেন না!


  1. Vue, Vuex, এবং Rails দিয়ে ফুল-স্ট্যাক ডেভেলপমেন্ট মাস্টার করুন: একটি স্কেলেবল পদ্ধতি

  2. রিঅ্যাক্ট অন রেইলস: সিমলেস ফুল-স্ট্যাক অ্যাপ গড়ে তোলা

  3. Angular এবং Rails 5 ইন্টিগ্রেশন: একটি স্মুথ ফুল-স্ট্যাক পদ্ধতি

  4. পাওয়ারফুল রুবি CLI টুল বিল্ড করুন: একটি স্টেপ-বাই-স্টেপ গাইড