[學習積累]memcached客戶端和鏈接池

前陣子在網上找了個demo學了一下memcached的簡單使用.java

今天回顧了一下,我想:鏈接池不是應該算是服務端管理的東西麼,Client應該是客戶端管理的東西,怎麼能放在同一個class裏邊呢?因而把demo改了改,代碼以下:web

服務端:
緩存

package studyMemcached;

import com.danga.MemCached.SockIOPool;

public class MemServer {

    private static SockIOPool pool;
    public static void main(String[] args) {
        initPool();
        
    }

    private static void destroyPool() {
        SockIOPool.getInstance("SP").shutDown();
    }

    private static void initPool() {
        String[] addr = { "127.0.0.1:11211" };
        Integer[] weights = { 3 };
        pool = SockIOPool.getInstance("SP");
        pool.setServers(addr);
        pool.setWeights(weights);
        pool.setInitConn(4);
        pool.setMinConn(4);
        pool.setMaintSleep(30);
        pool.setMaxConn(200);
        pool.setMaxIdle(1000 * 30 * 30 * 6);
        pool.setMaintSleep(30);
        pool.setNagle(false);
        pool.setSocketTO(30);
        pool.setSocketConnectTO(0);
        pool.initialize();
    }

}

客戶端:memcached

package studyMemcached;

import java.util.Date;

import com.danga.MemCached.MemCachedClient;

public class PutToCache {
    public static void main(String[] args) {
        MemCachedClient client = new MemCachedClient("SP" );
        
        client.setCompressEnable(true);
        client.setCompressThreshold(1000 * 1024);

        // 將數據放入緩存
        
        client.set("test2", "test2");

        // 將數據放入緩存,並設置失效時間
        Date date = new Date(2000000);
        client.set("test1", "test1", date);
        client.add("kkk", "kkkkk");
        // 刪除緩存數據
        // client.delete("test1");

        // 獲取緩存數據
        String str = (String) client.get("test1");
        String str2 = (String) client.get("test2");
        System.out.println(str);
        System.out.println(str2);
        System.out.println((String)client.get("kkk"));
    }
}

先運行服務端,發現立刻程序就結束了;感受有點兒不對勁;線程

而後運行客戶端,果真什麼也沒存進去,什麼也沒取到;日誌

日誌裏出現這樣的提示:Attempting to get SockIO from uninitialized pool!code

想了想,多是鏈接池初始化之後又立刻被銷燬了;server

因而把服務端改爲以下這樣:對象

package studyMemcached;

import java.util.Scanner;

import com.danga.MemCached.SockIOPool;

public class MemServer {

    private static SockIOPool pool;
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        initPool();
        while(!sc.nextLine().equals("exit")) {
            
        }
        sc.close();
        destroyPool();
    }

    private static void destroyPool() {
        SockIOPool.getInstance("SP").shutDown();
    }

    private static void initPool() {
        String[] addr = { "127.0.0.1:11211" };
        Integer[] weights = { 3 };
        pool = SockIOPool.getInstance("SP");
        pool.setServers(addr);
        pool.setWeights(weights);
        pool.setInitConn(4);
        pool.setMinConn(4);
        pool.setMaintSleep(30);
        pool.setMaxConn(200);
        pool.setMaxIdle(1000 * 30 * 30 * 6);
        pool.setMaintSleep(30);
        pool.setNagle(false);
        pool.setSocketTO(30);
        pool.setSocketConnectTO(0);
        pool.initialize();
    }

}

讓服務端卡在那裏等待輸入,而後運行客戶端,這樣會不會就能夠從鏈接池獲取到鏈接了呢?blog

...

...

果真仍是不行;

依然提示:Attempting to get SockIO from uninitialized pool!

難道這兩部分代碼必定要放在同一個類文件中麼?這是什麼鬼邏輯;

回頭查看公司項目裏memcached部分的代碼,也是把鏈接池和建立Client實例的邏輯分開在兩個類文件裏的,沒有任何問題;

想來想去,作了個僞分開,把Client做爲服務端的一個靜態變量,和線程池一塊兒初始化,而後在另外一個類裏調用這個Client進行存取,這個天然是能夠的;


後來又想到,公司的項目是web項目,是部署在web容器裏的,會不會由於Client和線程池對象都在同一個classloader或context裏,因此才能夠互相找到呢?

可是這個無法驗證啊,還得寫一個web版的demo,太費勁了,,,

因而,寫了這樣同樣東西:Together類,有兩個field,一個Client,一個Server分別是持有緩存Client和鏈接池對象的獨立的類;在初始化Together對象的時候,分別將client和Pool在各自的構造方法中初始化,而後在Together對象中調用Client裏的緩存Client進行存取;

代碼以下:

Together:

package studyMemcached;

public class Together {

    private MemC client;
    private MemS server;

    public Together() {
        client = new MemC();
        server = new MemS();
    }

    public static void main(String[] args) {
        String mistery = "xxx";
        Together t = new Together();
        t.client.set("mis", mistery);
        System.out.println(t.client.get("mis"));

    }

}

Server端:

package studyMemcached;

import com.danga.MemCached.SockIOPool;

public class MemS {

    private SockIOPool pool;

    public MemS() {
        String[] addr = { "127.0.0.1:11211" };
        Integer[] weights = { 3 };
        pool = SockIOPool.getInstance("SP");
        pool.setServers(addr);
        pool.setWeights(weights);
        pool.setInitConn(4);
        pool.setMinConn(4);
        pool.setMaintSleep(30);
        pool.setMaxConn(200);
        pool.setMaxIdle(1000 * 30 * 30 * 6);
        pool.setMaintSleep(30);
        pool.setNagle(false);
        pool.setSocketTO(30);
        pool.setSocketConnectTO(0);
        pool.initialize();

    }

}

Client端:

package studyMemcached;

import java.util.Date;

import com.danga.MemCached.MemCachedClient;

public class MemC {
    public MemCachedClient client;

    public MemC() {
        client = new MemCachedClient("SP");
        client.setCompressEnable(true);
        client.setCompressThreshold(64 * 1024);
    }
    
    public void set(String key, String value) {
        client.set(key, value, new Date(2000000));
    }
    
    public String get(String key) {
        return (String) client.get(key);
    }
}

這樣一來,MemCachedClient和SockIOPool就分開了,只是在實例化的時候兩個實例處在同一個classloader裏;

這樣調用,發現能夠進行數據的存取了;

看來互相找不到是一種相似不在同一個會話環境的問題;

我在網上百度了一天,也沒發現有人吧Client和Pool的初始化分開寫的demo,能找到的demo總共就倆,都是寫在一塊兒的;

可能這個pool不算是服務端吧,或者Client不算是客戶端;

公司的項目裏是把Client做爲一個單例,用的時候getInstance來取得後進行數據的保存和查找的;

雖然問題算是解決了,但仍是比較迷糊;

但願有懂的大神幫忙指點指點;

相關文章
相關標籤/搜索