目前在公司内部使用zookeeper的地方越來越多,應用大多喜歡自己部署一套zk叢集來使用。考慮到zk的高可用,并且一套zk叢集至少3台機器, 那麼每個應用,尤其是一些非核心應用都自己去部署一套的話,對資源使用率很低。另外,随着zk容災的提出,單套zk叢集使用的機器量會更大,運維人員開始 對這個情況擔憂,強烈希望能夠合并zk叢集。
zk叢集合并使用本身并沒有太大的難度,問題在于應用方是否願意大家共用一套zk叢集,這其中一個顯而易見的問題就是權限:如果我的資料被别人動了怎麼辦?
在公司不少牛人的幫助下,暫時得到兩個權限方案,同時也希望大家提出自己的看法,共同進步。個人建議采用zookeeper acl的權限控制方式。
這種方案将zookeeper的acl和digest授權認證模式相結合。具體操作流程如下:
整個權限控制流程的代碼測試:
<code>package org.i0itec.zkclient;</code> import java.util.arraylist; import java.util.list; import org.apache.zookeeper.watchedevent; import org.apache.zookeeper.watcher; import org.apache.zookeeper.zoodefs.ids; import org.apache.zookeeper.data.acl; /** description: zookeepre acl權限控制 測試 @author nileader / [email protected] @date feb 2, 2012 */ public class demoauth implements watcher { final static string server_list = “127.0.0.1:4711”; final static string path = “/yinshi_auth_test”; final static string path_del = “/yinshi_auth_test/will_be_del”; final static string authentication_type = “digest”; final static string correctauthentication = “taokeeper:true”; final static string badauthentication = “taokeeper:errorcode”; static zkclient zkclient = null; public static void main( string[] args ) throws exception { list< acl > acls = new arraylist< acl >( 1 ); for ( acl ids_acl : ids.creator_all_acl ) { acls.add( ids_acl ); } try { zkclient = new zkclient( server_list, 50000); zkclient.addauthinfo( authentication_type, correctauthentication.getbytes() ); } catch ( exception e ) { // todo auto-generated catch block e.printstacktrace(); zkclient.createpersistent( path, acls, “init content” ); system.out.println( “使用授權key:” + correctauthentication + “建立節點:” + path + “, 初始内容是: init content” ); zkclient.createpersistent( path_del, acls, “待删節點” ); system.out.println( “使用授權key:” + correctauthentication + “建立節點:” + path_del + “, 初始内容是: init content” ); // 擷取資料 getdatabynoauthentication(); getdatabybadauthentication(); getdatabycorrectauthentication(); // 更新資料 updatedatabynoauthentication(); updatedatabybadauthentication(); updatedatabycorrectauthentication(); //删除資料 deletenodebybadauthentication(); deletenodebynoauthentication(); deletenodebycorrectauthentication(); deleteparent(); zkclient.close(); /* 擷取資料:采用錯誤的密碼 / static void getdatabybadauthentication() { string prefix = “[使用錯誤的授權資訊]”; system.out.println( prefix + “擷取資料:” + path ); zkclient.addauthinfo( authentication_type, badauthentication.getbytes() ); system.out.println( prefix + “成功擷取資料:” + zkclient.readdata( path ) ); system.err.println( prefix + “擷取資料失敗,原因:” + e.getmessage() ); /* 擷取資料:不采用密碼 / static void getdatabynoauthentication() { string prefix = “[不使用任何授權資訊]”; /* 采用正确的密碼 / static void getdatabycorrectauthentication() { string prefix = “[使用正确的授權資訊]”; system.out.println( prefix + “擷取資料失敗,原因:” + e.getmessage() ); 更新資料:不采用密碼 static void updatedatabynoauthentication() { system.out.println( prefix + “更新資料: “ + path ); if( zkclient.exists( path ) ){ zkclient.writedata( path, prefix ); system.out.println( prefix + “更新成功” ); system.err.println( prefix + “更新失敗,原因是:” + e.getmessage() ); 更新資料:采用錯誤的密碼 static void updatedatabybadauthentication() { system.out.println( prefix + “更新資料:” + path ); 更新資料:采用正确的密碼 static void updatedatabycorrectauthentication() { 不使用密碼 删除節點 static void deletenodebynoauthentication() throws exception { system.out.println( prefix + “删除節點:” + path_del ); if( zkclient.exists( path_del ) ){ zkclient.delete( path_del ); system.out.println( prefix + “删除成功” ); system.err.println( prefix + “删除失敗,原因是:” + e.getmessage() ); 采用錯誤的密碼删除節點 static void deletenodebybadauthentication() throws exception { 使用正确的密碼删除節點 static void deletenodebycorrectauthentication() throws exception { system.out.println( prefix + “删除失敗,原因是:” + e.getmessage() ); static void deleteparent() throws exception { zkclient.delete( path ); @override public void process( watchedevent event ) { // todo auto-generated method stub `
這個方案大緻是這樣:
1. a系統上有一份ip和appname對應的資料本地。
2. 将這份資料在zk伺服器上緩存一份,并定時進行緩存更新。
3. 每次用戶端對伺服器發起請求的時候,擷取用戶端ip進行查詢,判斷是否有對應appname的權限。限制指定ip隻能操作指定 /appname znode。
4. 其它容災措施。
個人比較兩個方案:
1.方案一較方案二,使用者的掌控性大,無論線上,日常,測試都可以由應用開發人員自己決定開啟/關閉權限。 (方案一的優勢)
2.方案二較方案一,易用性強,使用者的使用和無權限基本一緻。 (方案二的優勢)
3.方案一較方案二更為純潔。因為我覺得zk本來就應該是一個底層元件,讓他來依賴其它上層的另一個系統?權限的控制精度取決于系統a上資訊的準确性。 (方案一的優勢)
另外附上 方案一 有權限和無權限對比壓測tps情況
測試條件:三台zk伺服器:8核 jdk 1.6.0-06 四台zk用戶端機器:5核 jdk1.6.0-21
測試場景:800個釋出者,對應800個path,每個path 3個訂閱者,共2400個訂閱者。釋出者釋出資料,通知訂閱者。
結論:權限控制對zk的tps有一定的影響,但是還是保持在較高的水準(1.3w+),如圖(點選檢視大圖):