Unix domain socket和memcached
Posted on 2009-10-15 06:12 dennis 閱讀(5391) 評論(0) 編輯 收藏 所屬分類: java 、unix網絡編程 unix域協議并不是一個實際的協議族,而是在單個主機上執行客戶/服務器通信的一種方法,是IPC的方法之一,特定于*nix平臺。使用unix domain socket有三個好處:
1)在同一主機上,unix domain socket比一般的tcp socket快上一倍,性能因素這是一個主要原因。
2)unix domain socket可以在同一主機的不同進程之間傳遞文件描述符
3)較新的unix domain socket實現把客戶的ID和組ID提供給服務器,可以讓服務器作安全檢查。
memcached的FAQ中也提到為了安全驗證,可以考慮讓memcached監聽unix domain socket。Memcached支持這一點,可以通過-s選項指定unix domain socket的路徑名,注意,為了可移植性,盡量使用絕對路徑,因為Posix標準聲稱給unix domain socket綁定相對路徑將導致不可預計的后果,我在linux的測試是可以使用相對路徑。假設我將memcached綁定到/home/dennis/memcached,可以這樣啟動memcached:
memcached -s /home/dennis/memcached
端口呢?沒有端口了,/home/dennis/memcached這個文件你可以理解成FIFO的管道,unix domain socket的server/client通過這個管道通訊。
libmemcached支持通過unix domain socket來訪問memcached,基于libmemcached實現的client應該都可以使用這一功能。目前來看,java平臺由于不支持平臺相關的unix domain socket,因此無法享受memcached的這一特性。
不過有一個開源項目通過jni支持實現了unix domain socket,這個項目稱為juds。核心類就三個,使用非常簡單。下載文件后,解壓縮,make & make install即可。注意,Makefile中寫死了JAVA_HOME,手工修改即可。看一個例子,經典的Time server:
通過UnixDomainSocketServer創建server,指定類型為SOCK_STREAM,juds也支持UDP類型。client的使用如下:
最后一個例子,通過juds訪問memcached的unix domain socket,簡單的version協議調用:
Text received: "VERSION 1.4.1"
1)在同一主機上,unix domain socket比一般的tcp socket快上一倍,性能因素這是一個主要原因。
2)unix domain socket可以在同一主機的不同進程之間傳遞文件描述符
3)較新的unix domain socket實現把客戶的ID和組ID提供給服務器,可以讓服務器作安全檢查。
memcached的FAQ中也提到為了安全驗證,可以考慮讓memcached監聽unix domain socket。Memcached支持這一點,可以通過-s選項指定unix domain socket的路徑名,注意,為了可移植性,盡量使用絕對路徑,因為Posix標準聲稱給unix domain socket綁定相對路徑將導致不可預計的后果,我在linux的測試是可以使用相對路徑。假設我將memcached綁定到/home/dennis/memcached,可以這樣啟動memcached:
memcached -s /home/dennis/memcached
端口呢?沒有端口了,/home/dennis/memcached這個文件你可以理解成FIFO的管道,unix domain socket的server/client通過這個管道通訊。
libmemcached支持通過unix domain socket來訪問memcached,基于libmemcached實現的client應該都可以使用這一功能。目前來看,java平臺由于不支持平臺相關的unix domain socket,因此無法享受memcached的這一特性。
不過有一個開源項目通過jni支持實現了unix domain socket,這個項目稱為juds。核心類就三個,使用非常簡單。下載文件后,解壓縮,make & make install即可。注意,Makefile中寫死了JAVA_HOME,手工修改即可。看一個例子,經典的Time server:
package com.google.code.juds.test;
import java.io.IOException;
import com.google.code.juds.*;
import java.io.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
public class TimeServer {
public static void main(String[] args) {
try {
UnixDomainSocketServer server = new UnixDomainSocketServer(
"/home/dennis/time", UnixDomainSocket.SOCK_STREAM);
OutputStream output = server.getOutputStream();
Date date = new Date();
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
output.write(dateFormat.format(date).getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
}
import java.io.IOException;
import com.google.code.juds.*;
import java.io.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
public class TimeServer {
public static void main(String[] args) {
try {
UnixDomainSocketServer server = new UnixDomainSocketServer(
"/home/dennis/time", UnixDomainSocket.SOCK_STREAM);
OutputStream output = server.getOutputStream();
Date date = new Date();
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
output.write(dateFormat.format(date).getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
}
通過UnixDomainSocketServer創建server,指定類型為SOCK_STREAM,juds也支持UDP類型。client的使用如下:
byte[] b = new byte[128];
UnixDomainSocketClient socket = new UnixDomainSocketClient("/home/dennis/time",
UnixDomainSocket.SOCK_STREAM);
InputStream in = socket.getInputStream();
in.read(b);
System.out.println("Text received: \"" + new String(b) + "\"");
socket.close();
顯然,juds還只支持阻塞IO,考慮可進一步使用select、poll來擴展實現非阻塞IO。UnixDomainSocketClient socket = new UnixDomainSocketClient("/home/dennis/time",
UnixDomainSocket.SOCK_STREAM);
InputStream in = socket.getInputStream();
in.read(b);
System.out.println("Text received: \"" + new String(b) + "\"");
socket.close();
最后一個例子,通過juds訪問memcached的unix domain socket,簡單的version協議調用:
byte[] b = new byte[128];
UnixDomainSocketClient socket = new UnixDomainSocketClient("/home/dennis/memcached",
UnixDomainSocket.SOCK_STREAM);
OutputStream out = socket.getOutputStream();
String text = "version\r\n";
out.write(text.getBytes());
InputStream in = socket.getInputStream();
in.read(b);
System.out.println("Text received: \"" + new String(b) + "\"");
socket.close();
輸出UnixDomainSocketClient socket = new UnixDomainSocketClient("/home/dennis/memcached",
UnixDomainSocket.SOCK_STREAM);
OutputStream out = socket.getOutputStream();
String text = "version\r\n";
out.write(text.getBytes());
InputStream in = socket.getInputStream();
in.read(b);
System.out.println("Text received: \"" + new String(b) + "\"");
socket.close();
Text received: "VERSION 1.4.1"