Database Connection Pool

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

আবার যেহেতু প্রত্যেকটা রিকোয়েস্টের জন্য একটাই কানেকশন ইউজ করছি, রিকোয়েস্টগুলোকে আগের রিকোয়েস্টটি শেষ হওয়ার জন্য ওয়েট করা লাগছে। তাই আমার অ্যাপ্লিকেশনের পারফরম্যান্সও খারাপ হচ্ছে।

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

কানেকশন পুলিং কীঃ

এককথায় বললে, কানেকশন পুল হচ্ছে কানেকশনের ক্যাশ, যেটা অ্যাপ্লিকেশনে বারবার ইউজ করা যায়। কানেকশনের একটা কন্টেইনার, যেটা থেকে কানেকশন নিয়ে আমি অ্যাপ্লিকেশনে ইউজ করব, কাজ শেষে আবার রেখে দিব।

যেহেতু এইক্ষেত্রে আমাকে বারবার কানেকশন Open/Close করা লাগছে না, যার কারণে পুল থেকে কানেকশন নিতে ও ফিরিয়ে দিতে তুলনামূলক কম সময় লাগে।

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

এখন তাহলে বেসিক একটা কানেকশন পুলের কোড লিখি। অ্যাপ্লিকেশন শুরুর সাথে সাথেই n টা কানেকশন নিয়ে একটা লিস্টে রাখি।

public void createConnections(int n) {
    try {
        MAX_CONNECTION = n;
        Class.forName("com.mysql.jdbc.Driver");
        for(int i = 0;i<n; i++) {
            Connection connection = DriverManager.getConnection(
                    "jdbc:mysql://localhost:3306/testDB","root","1234");
            connections.add(connection);
        }
    } catch (Exception ex) {
        ex.printStackTrace();
    }
}

এখানে connections একটি অ্যারেলিস্ট, যার ডেফিনিশান এমনঃ

private ArrayList<Connection> connections = new ArrayList<>();

MAX_CONNECTION একটি ইন্টিজার।

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

public Optional<Connection> getConnectionFromPool() {
    Connection connection = null;
    synchronized (this) {
        if (connections.size() > 0) {
            connection = connections.get(connections.size() - 1);
            connections.remove(connection);
        }
    }
    return Optional.ofNullable(connection);
}

কানেকশন দিয়ে কাজ শেষ করে আবার পুলে ব্যাক করার কোডটিও দেয়া হল। যে কানেকশনটা ইউজ করছিলাম, সে কানেকশনটাই আবার ফিরিয়ে দিলাম। কানেকশনটা লিস্টে আবার এড করে নিলাম।

public boolean giveConnectionBackToConnectionPool(Connection connection) {
    synchronized (this) {
        if (connections.size() < MAX_CONNECTION) {
            connections.add(connection);
            return true;
        }
    }
    return false;
}

পুরো কোডটি গিটের রিপোতে দেয়া আছে। তোমরা ডায়নামিক কানেকশন পুলটি ইমপ্লিমেন্টের ট্রাই করতে পার।

জাভার জন্য বেশ কিছু কানেকশন পুল ফ্রেমওয়ার্ক আছে। সেগুলোর মধ্যে অন্যতমঃ

  • Apache Common DBCP
  • HikariCP
  • C3PO
  • BoneCP
  • Tomcat JDBC CP

Spring Boot 1.x এ Tomcat JDBC Connection Pool ডিফল্ট ছিল। Spring Boot 2.x এ Hikari CP ডিফল্ট ইউজড হয়। Hikari CP টাই এখন বেশি পপুলার। কারণ অন্যগুলোর তুলনায় এটি ফাস্ট, হাইলি অপ্টিমাইজড ও লাইটওয়েট।

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s