成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

distributeTemplate分布式配置,上下文的同步維護

移動開發 Android 分布式
我們實現分布式 也是按照 這樣一步一步來的,首先是公用的資源對象,第一個必須的公用資源 對象是配置,這配置交給用戶外部填寫 手動配置 并能維持同步 更新 所以需要一個配置對象 維護在內存里面,需要事件驅動監聽配置文件的變化情況

我們實現分布式 也是按照 這樣一步一步來的,首先是公用的資源對象,***個必須的公用資源 對象是配置,這配置交給用戶外部填寫 手動配置 并能維持同步 更新 所以需要一個配置對象 維護在內存里面,需要事件驅動監聽配置文件的變化情況

ok下面來 看看代碼是怎么做的 ,首先 配置 有多重配置方式 ini conf prop xml 各種方式本質上 我們分布式就是要各臺主機 自己所在的節點 都能知道我在網絡上情況,或者所可以找到像zookeeper 只要知道或者找到了 才能進行以后的通訊同步

我們為了能夠以后支持多重配置 ,所以先把配置定義為一個接口

  1. public interface IConfig { 
  2.     public static final String DEFAULTFILE="distribute.conf"
  3. /** 
  4.  *  
  5.  * 從文件讀取配置初始化 
  6.  * @param file 
  7.  * 添加(修改)人:zhuyuping 
  8.  */ 
  9. public void readConfigFormFile(String file); 
  10. /** 
  11.  * 從用戶提供的json字符串中初始化 
  12.  * @param json 
  13.  * 添加(修改)人:zhuyuping 
  14.  */ 
  15. public void readConfigFormString(String json); 
  16. /** 
  17.  * 獲得系統內存中維護的內存表 
  18.  *  
  19.  * 添加(修改)人:zhuyuping 
  20.  */ 
  21. public Table<InetSocketAddress, String, Object> getConfig(); 
  22. /** 
  23.  * 攝入context上下文 
  24.  * @param context 
  25.  * 添加(修改)人:zhuyuping 
  26.  */ 
  27. public void setContext(Context context); 
  28. /** 
  29.  * 獲得上下文context 
  30.  * @return 
  31.  * 添加(修改)人:zhuyuping 
  32.  */ 
  33. public Context getContext(); 
  34. public BiMap<String, InetSocketAddress> getAlias(); 

主要 是3個方法 ,一個是讀配置文件到內存對象中,擰一個就是內存對象寫到文件中,對于分布式還需要一個同步 

有時候 我們可能需要歷史版本 能夠容錯還原 所以可能需要一個版本號 記錄當前版本,然后保持有可能多個節點上配置文件更改后,發送請求時候能夠保持順序的更新,這后面我會處理 加入一個分布式先進先出的隊列的,這里暫時未加 后面 加了會補上的,還有上下文context 對象,有人會說 你為什么需要上下文對象去保存變量啊,好多框架 都有上下文這個對象,也許是攔截器模式 也許是門面模式 等等其他模式,但是 這里我都不是,其實上下文只是為了本地節點的各個功能代碼段之間的一個橋梁,有句話叫做 兩情若是久長時 又豈在朝朝暮暮 我們有鵲橋,他就是上下文最重要的本質 就是維護本地節點上下文貫穿 如果上下文 里面保存著門面 那么他就有門面的功能 便于用戶隨時獲取門面對象 進行操作,ok我們來看看 context是怎么定義的

  1. /** 
  2.  *  
  3.  *       
  4.  *      
  5.  * @author zhuyuping        
  6.  * @version 1.0      
  7.  * @created 2014-7-9  
  8.  * @function:上下文接口  他只是存儲用戶上面類所有過程中的變量不是config配置而且分布式中不會同步的只會在單點上有效 切記  、、后期如果想支持xml 配置或者其他配置 可以添加策略模式  
  9.  */ 
  10. public interface Context { 
  11.   
  12.     public final static String defaultConfig="distribute.conf";//默認配置名 
  13.       
  14.     public void putValue(String key,Object value); 
  15.       
  16.     public Object getValue(String key); 
  17.       
  18.     public void setCurrHost(String host,int port); 
  19.       
  20.     public InetSocketAddress getCurrHost(); 
  21.     /** 
  22.      * 獲得默認配置文件 
  23.      * @return 
  24.      * 添加(修改)人:zhuyuping 
  25.      */ 
  26.     public String getDefaultFc(); 
  27. //  /** 
  28. //   * 設置默認屬性文件的名稱 
  29. //   * @param pfile 
  30. //   * 添加(修改)人:zhuyuping 
  31. //   */ 
  32. //  public void setDefaultFc(String pfile); 
  33. //  /** 
  34. //   * 注入template 門面 便于后面直接通過上下文來使用  如果要整合spring ApplicationContextAware 
  35. //   * @param distributedTemplate 
  36. //   * 添加(修改)人:zhuyuping 
  37. //   */ 
  38. //  public void setTemplate(DistributedOperations distributedTemplate); 
  39. //  
  40. //  public DistributedOperations getTemplate(); 
  41.       
  42.       

這里其實 就是一個map 保存屬性key value 而常用的就取出作為一個方法了

這個context 因為后面我們給用戶一個繼承的 這樣便于 用戶實現自己的上下文 或交給其他框架上下文 以及整合所以我們實現了一個抽象的 默認實現

  1. /** 
  2.  *  
  3.  *       
  4.  *      
  5.  * @author zhuyuping        
  6.  * @version 1.0      
  7.  * @created 2014-7-9 下午5:58:37  
  8.  * @function:抽象的上下文 主要是 管理context的資源 還有就是提供用戶自定義 整合spring使用該類 //這里后期需整合策略 實現 
  9.  */ 
  10. public abstract class AbstractContext implements Context{ 
  11.     //?也可以使用LocalThread 也可以 
  12.     private Map<String,Object> context=Maps.newConcurrentMap(); 
  13.       
  14.     private InetSocketAddress currHost;//當前主機 比如192.168.0.1 8888 
  15.       
  16.     private String dfConfig;//默認讀取的配置文件 當用戶 提供就修改 沒有提供就默認  
  17.       
  18.       
  19.     public AbstractContext(String dfConfig) { 
  20.         super(); 
  21.           
  22.         this.dfConfig = dfConfig; 
  23.         //當前classes 下的文件 
  24.         //currentPort 
  25.         this.currHost=new InetSocketAddress(ConfigFactory.load(dfConfig).getString("client.currentHost"),ConfigFactory.load(dfConfig).getInt("client.currentPort")); 
  26.     } 
  27.   
  28.       
  29.       
  30.     @Override 
  31.     public InetSocketAddress getCurrHost() { 
  32.           
  33.         return currHost; 
  34.     } 
  35.   
  36.       
  37.   
  38.     @Override 
  39.     public void setCurrHost(String host,int port) { 
  40.           
  41.         this.currHost=new InetSocketAddress(host, port); 
  42.           
  43.     } 
  44.   
  45.   
  46.   
  47.     @Override 
  48.     public String getDefaultFc() { 
  49.           
  50.         return dfConfig!=null?dfConfig:defaultConfig; 
  51.     } 
  52.   
  53.   
  54.   
  55.     public AbstractContext() { 
  56.         super(); 
  57.         this.dfConfig=defaultConfig; 
  58.   
  59.         this.currHost=new InetSocketAddress(ConfigFactory.load(defaultConfig).getString("client.currentHost"),ConfigFactory.load(defaultConfig).getInt("client.currentPort")); 
  60.           
  61.     } 
  62.   
  63.   
  64.   
  65.     @Override 
  66.     public void putValue(String key, Object value) { 
  67.           
  68.         context.put(key, value); 
  69.           
  70.     } 
  71.   
  72.     @Override 
  73.     public Object getValue(String key) { 
  74.         return context.get(key); 
  75.     } 
  76.       
  77.       
  78.       

ok 很簡單的 維護者

然后回到剛才的配置 ,首先 我們配置文件 需要從文件讀取 到配置對象中 ,這是為了用戶更改 或者初始化時候 吧配置文件初始化到配置內存對象中 然后這個內存對象將會在同步 配置文件 更改 網絡通訊時候用到,在對于全局的所有節點的淪陷時候 單純的context只維護本節點橋梁信息的 已經不夠用了 因為他不會同步的,這就是為什么需要他的原因,我這里采用的配置文件時conf 也就是configLoad方式,后面我會逐步添加更多的支持方式 無非是xml 等讀取問題,這并不重要 思想才是重要的

 

  1. /** 
  2.  *  
  3.  *       
  4.  *      
  5.  * @author zhuyuping        
  6.  * @version 1.0      
  7.  * @created 2014-7-9 下午4:07:00  如果后期需要支持xml 其他 只需要使用策略模式  
  8.  * @function:基類config 主要維持 配置基本信息 以及配置信息的同步 備份 同時內存中維持一張內存表table 
  9.  */ 
  10. public abstract class AbstractConfig implements IConfig{ 
  11.     /** 
  12.      * 當前的配置表 行 為主機別名 其中一定有一列為版本號 AotmicLong 以及配置的相關字段  值為相關的對象   
  13.      */ 
  14. protected Table<InetSocketAddress, String, Object> config=HashBasedTable.create();//table信息  table 信息 這里無需要用到 哪個ConcurrentHashMap<K, V> 因為這個只會加載讀取 加載  
  15. //不會修改,因為這個table當用戶真的更新config后 會同步并同時刷到更新到文件中的 ,而且每次用戶提供查詢的配置 
  16. //是不會更新到文件里面的  
  17. protected AtomicLong version=new AtomicLong(0);//初始化版本為0;//判斷當前的版本 是佛在config 里面是否存在 
  18. protected BiMap<String,InetSocketAddress> alias=HashBiMap.create(); 
  19. protected Context context; 
  20.        
  21.     public BiMap<String, InetSocketAddress> getAlias() { 
  22. return alias; 
  23. /** 
  24.      * context 需要提供當前主機 以及  
  25.      * @param context 
  26.      */ 
  27. public AbstractConfig(Context context) { 
  28. super(); 
  29. this.context = context; 
  30. wrapConfig(ConfigFactory.load(context.getDefaultFc())); 
  31. @Override 
  32. public void setContext(Context context) { 
  33. this.context=context; 
  34. @Override 
  35. public Context getContext() { 
  36. return context; 
  37. @Override 
  38. public void readConfigFormFile(String file) { 
  39. Config config=TypeSafeConfigLoadUtils.loadFromFile(new File(file)); 
  40. wrapConfig(config); 
  41. @Override 
  42. public void readConfigFormString(String json) { 
  43. Config config=TypeSafeConfigLoadUtils.loadFromString(json); 
  44. wrapConfig(config); 
  45. /** 
  46.  * 對config進行初始化 table 
  47.  * @param config 
  48.  * 添加(修改)人:zhuyuping 
  49.  */ 
  50. protected abstract void wrapConfig(Config config); 
  51. /** 
  52.  * 把table 從內存中讀取從新寫入到配置文件中  
  53.  * @param config 
  54.  * 添加(修改)人:zhuyuping 
  55.  */ 
  56. protected abstract String wrapTable(Table<String, String, Object> config); 
  57. /** 
  58.  * 只保留最近的5個版本 可以回滾 更新***的 
  59.  *  
  60.  * 添加(修改)人:zhuyuping 
  61.  */ 
  62. public void updateVersion(Long version){ 
  63.    
  64. /** 
  65.  * 版本數更新 
  66.  *  更新完后 需要  
  67.  * 添加(修改)人:zhuyuping 
  68.  */ 
  69. public void addVersion(){ 
  70. Long v=version.getAndIncrement(); 
  71. //TODO 需要通知所有節點 我要修改版本了 如果同時有幾個人也這樣 那么接受該節點下次更新的版本號, 
  72.     //在回調函數中 更新配置 隨后同步 只保留5個版本  
  73.     @Override 
  74. public Table<InetSocketAddress, String, Object> getConfig() { 
  75. return config; 
  76. /** 
  77.      *  
  78.      * 提交對文件配置做出的修改 
  79.      * 添加(修改)人:zhuyuping 
  80.      */ 
  81.     protected abstract void commit(); 
  82. /** 
  83.  *  
  84.  * 提交對配置的修改 如果一個人在一個節點上 更改了配置 需要核對版本 并從新更新本地的配置文件 
  85.  * 添加(修改)人:zhuyuping 
  86.  */ 
  87. protected abstract void sync(); 
  88.       

這里 我為了好維護 就直接使用guava的table ,其實你可以用List< map> 實現,這里 重要是獲取所有主機列表的方法

然后就是配置文件讀取后 寫入context 對象 當然 上面說的讀取配置到內存對象 ,內存對象寫入到配置文件是基礎

然后看看怎么寫入的 我為了以后支持xml 所以這讀取方式 寫入方式 交給后面的子類實現類去實現 這樣實現xml只要實現這2個方法即可

 

  1. /** 
  2.  *  
  3.  *       
  4.  *      
  5.  * @author zhuyuping        
  6.  * @version 1.0      
  7.  * @created 2014-7-9 下午10:38:05  
  8.  * @function:默認的配置  允許用戶實現自定義的配置規則 只需要繼承 AbstractConfig 
  9.  */ 
  10. public class SimpleDistributeConfig extends AbstractConfig{ 
  11.     public SimpleDistributeConfig(Context context) { 
  12.         super(context); 
  13.           
  14.     } 
  15.   
  16.     @Override 
  17.     protected void wrapConfig(Config configObj) { 
  18.         //得到所有的節點 
  19.         List<? extends ConfigObject> nodes=configObj.getObjectList("server.hosts"); 
  20.         int i=0
  21.         for (ConfigObject node : nodes) { 
  22.       
  23.            i++; 
  24.            //如果后期添加其他mysql 等支持 這里就需要添加判斷 
  25.             
  26.            //Integer localport=node.containsKey("localPort")?Integer.parseInt(node.get("localPort").render()):LOCALPORT;//Integer.parseInt(node.get("localPort").render()); 
  27.            Integer remotePort=Integer.parseInt(node.get("remotePort").render()); 
  28.            String remoteIp=node.get("remoteHost").unwrapped().toString();//遠程主機的ip 
  29.            //開始初始化配置table 
  30.            String name=node.containsKey("name")?node.get("name").unwrapped().toString():remoteIp;//主機別名 
  31.            InetSocketAddress remoteHost=new InetSocketAddress(remoteIp, remotePort); 
  32.            super.alias.put(name, remoteHost); 
  33.            super.config.put(remoteHost,"version"super.version.incrementAndGet()); 
  34.            super.config.put(remoteHost, "remoteHost", remoteHost); 
  35.            //super.config.put(remoteHost, "localPort", localport); 
  36.            super.config.put(remoteHost, "remotePort", remotePort); 
  37.            super.config.put(remoteHost, "name", name); 
  38.              
  39.            
  40.            if(node.containsKey("file")){ 
  41.                HashMap fcs=(HashMap) node.get("file").unwrapped(); 
  42.                String syncPath=fcs.get("syncPath").toString();//文件同步的路徑 
  43.               // System.out.println("SimpleDistributeConfig.wrapConfig() "+syncPath); 
  44.                super.config.put(remoteHost, "file", syncPath);//以后配置多的時候 分裝成一個bean存入 
  45.            } 
  46.              
  47.              
  48.         } 
  49.         String chost=configObj.getString("client.currentHost"); 
  50.         int port=configObj.getInt("client.currentPort"); 
  51.         super.context.setCurrHost(chost, port); 
  52.           
  53.         //config.root().containsKey(key) 
  54.         //config.getString(path); 
  55.     } 
  56.       
  57.       
  58.     @Override 
  59.     protected String wrapTable(Table<String, String, Object> table) { 
  60.         StringBuilder sb=new StringBuilder("server{"); 
  61.           
  62.         sb.append("\n\t").append("hosts=["); 
  63.         Set<String> rows=table.rowKeySet(); 
  64.         int size=rows.size(); 
  65.         int i=0
  66.         for (String row : rows) { 
  67.             i++; 
  68.             Map<String,Object> map=table.row(row); 
  69.             if(!map.containsKey("remoteHost")) continue
  70.             sb.append("\t {"); 
  71.             Object remoteHost=map.get("remoteHost");   
  72.             Object remotePort=map.get("remotePort"); 
  73.             //Object localPort=map.get("localPort"); 
  74.             Object name=map.get("name"); 
  75.             sb.append("name=").append(name).append("\n\t"); 
  76.             //sb.append("localPort=").append(localPort).append("\n\t"); 
  77.             sb.append("remoteHost=").append(remoteHost).append("\n\t"); 
  78.             sb.append("remotePort=").append(remotePort).append("\n\t"); 
  79.             if(map.containsKey("file")){ 
  80.                 sb.append("file{").append("\n\t").append("syncPath=").append(map.get("syncPath")).append("}"); 
  81.             } 
  82.              
  83.             sb.append("\t }"); 
  84.             if(i!=size){ 
  85.                 sb.append(","); 
  86.             } 
  87.         } 
  88.        sb.append("]").append("\n\t").append("}");    
  89.       //繼續 保存client 
  90.         
  91.        sb.append("\n\t").append("client{").append("\n\t").append("currentHost=").append(context.getCurrHost().getHostString()).append("\n\t"); 
  92.        sb.append("\n\t").append("currentPort=").append(context.getCurrHost().getPort()).append("\n\t"); 
  93.        sb.append("}"); 
  94.          
  95.        return sb.toString(); 
  96.           
  97.     } 
  98.   
  99.     @Override 
  100.     protected void commit() { 
  101.           
  102.           
  103.     } 
  104.   
  105.     @Override 
  106.     protected void sync() { 
  107.           
  108.           
  109.     } 
  110.   
  111.     public static void main(String[] args) { 
  112.       
  113.           
  114.           
  115.     } 
  116.   

ok 基本的簡單的 配置 以及 上下文 這些用來同步的 用來做橋梁的都已經做好了 下面就是怎么監聽配置文件的更改,有人說怎么監聽一個配置文件更改啊,其實 文件有個屬性 ***更改的時間,只要監聽這個就可以 初級版本沒有加上更改,這個后面可以隨時加上 而且為了以后好更改 只寫了相關方式沒有 加上

  1. import java.io.File; 
  2.   
  3. public interface FileListener { 
  4.     public void fileChanged(File file); 

然后用定時器 timeer 或者線程池定時線程去輪訓他 ,

 

 

 

 

 

這里 注意弱應用 ,其實 對于這些時間 我建議用LinkTransferQueue 他是FIFO 先進先出的無阻曬的隊列 然后隊列 加上若引用,保證時間的一些順序,

然后 通知了接口 在接口里面我們在做相應的更改配置 同步配置 的相關操作,這一章基本思想就是

 同步 資源 配置 上下文為橋梁 事件驅動為引擎 

還有支出的是 timer excutors.newSchulerXXXX  還有很多方式實現輪訓的方式  這種方式 也可以實現心跳線 

同時 告訴大家的事 Apache、 camel| 里面的事件驅動文件部分 核心代碼就是上面 這一小部分 

代碼 沒有貼完整 ,但是代碼已經托管到  http://git.oschina.net/zhuyuping/distributeTemplate

 本文鏈接:http://my.oschina.net/yilian/blog/295667

責任編輯:chenqingxiang 來源: oschina
相關推薦

2017-05-11 14:00:02

Flask請求上下文應用上下文

2022-09-14 13:13:51

JavaScript上下文

2012-12-31 10:01:34

SELinuxSELinux安全

2022-09-15 08:01:14

繼承基礎設施基礎服務

2023-07-11 10:02:23

2024-03-14 08:11:45

模型RoPELlama

2011-03-28 13:39:45

nagios分布式

2025-04-07 01:02:00

GoAPI語言

2022-04-24 15:37:26

LinuxCPU

2025-06-06 08:00:00

上下文管理器Python開發

2020-07-24 10:00:00

JavaScript執行上下文前端

2021-07-26 07:47:36

Cpu上下文進程

2017-12-17 17:01:23

限界上下文系統模型

2022-10-28 16:24:33

Context上下文鴻蒙

2024-09-30 14:10:00

2025-03-18 08:14:05

2017-06-27 18:52:05

TensorFlow深度學習

2021-09-07 09:53:42

JavaScript變量提升

2024-08-27 09:46:39

Go協程效率

2012-07-18 11:39:18

ibmdw
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 免费三级网站 | 国产福利在线 | 亚洲精品乱码久久久久久蜜桃 | 欧美精品在欧美一区二区 | 国产精品揄拍一区二区 | 亚洲高清免费视频 | 欧美一级全黄 | 亚洲国产二区 | 久久免费精品 | 日韩久久综合网 | 欧美精品一区二区在线观看 | 国产一区免费 | 干一干操一操 | 亚洲69p | 国产成人av免费看 | 精品日韩一区 | 国产精品美女在线观看 | 成人一区av偷拍 | 久久一区二区视频 | 亚洲一区二区网站 | 一区二区三区中文字幕 | 日韩一区二区视频 | 在线中文视频 | 欧美精品久久 | 国产午夜精品一区二区三区嫩草 | 精品国产一区二区三区久久 | 亚洲自拍偷拍欧美 | 成人在线观看免费 | 日本中文字幕一区 | 国产精品久久久久久久免费大片 | 国产日韩一区二区三免费高清 | 亚洲一区二区视频 | 亚洲成人一区二区 | 99在线免费观看 | 9久9久9久女女女九九九一九 | www.日日干 | 色橹橹欧美在线观看视频高清 | 一级日韩 | 精品在线播放 | 国产大片黄色 | 欧美色综合 |