<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    少年阿賓

    那些青春的歲月

      BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
      500 Posts :: 0 Stories :: 135 Comments :: 0 Trackbacks

    #

    最近因為項目需要,簡單的試用了兩款高可用開源方案:Keepalived和Heartbeat。兩者都很流行,但差異還是很大的,現將試用過程中的感受以及相關知識點簡單總結一下,供大家選擇方案的時候參考。
    1)Keepalived使用更簡單:從安裝、配置、使用、維護等角度上對比,Keepalived都比Heartbeat要簡單得多,尤其是Heartbeat2.1.4后拆分成3個子項目,安裝、配置、使用都比較復雜,尤其是出問題的時候,都不知道具體是哪個子系統出問題了;而Keepalived只有1個安裝文件、1個配置文件,配置文件也簡單很多;
    2)Heartbeat功能更強大:Heartbeat雖然復雜,但功能更強大,配套工具更全,適合做大型集群管理,而Keepalived主要用于集群倒換,基本沒有管理功能;
    3)協議不同:Keepalived使用VRRP協議進行通信和選舉,Heartbeat使用心跳進行通信和選舉;Heartbeat除了走網絡外,還可以通過串口通信,貌似更可靠;
    4)使用方式基本類似:如果要基于兩者設計高可用方案,最終都要根據業務需要寫自定義的腳本,Keepalived的腳本沒有任何約束,隨便怎么寫都可以;Heartbeat的腳本有約束,即要支持service start/stop/restart這種方式,而且Heartbeart提供了很多默認腳本,簡單的綁定ip,啟動apache等操作都已經有了;
    使用建議:優先使用Keepalived,當Keepalived不夠用的時候才選擇Heartbeat
    posted @ 2015-07-26 20:42 abin 閱讀(795) | 評論 (1)編輯 收藏

    1、StatefulJob
    implements StatefulJob使Job成為有狀態的,順序執行 
    同一個有狀態的job實例不存在并發,無狀態的job的并發數由上面配置的線程數決定。不想并發的話,設置成1,第二個線程在前一個執行完以后觸發執行。
    線程數大于1時,如果存在空閑線程,則到執行時間點即觸發執行。

    2、
    MethodInvokingJobDetailFactoryBean
    MethodInvokingJobDetailFactoryBean的并發問題
    大家在使用quartz的時候,一般只設置了“targetObject”和“targetMethod”,MethodInvokingJobDetailFactoryBean類默認是并發執行的,這時候如果不設置“concurrent”為false,很可能帶來并發或者死鎖的問題,而且幾率較小,不容易復現,請大家使用的時候注意設置“concurrent”。
     
        <bean id="cpm.MessageJobFactoryBean" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
            <property name="targetObject" ref="cpm.MessageJob"/>
            <property name="targetMethod" value="execute"/>
            <property name="concurrent" value="false"/>
        </bean>
    concurrent   同時發生
     concurrent:對于相同的JobDetail,當指定多個Trigger時, 很可能第一個job完成之前,第二個job就開始了。
     定concurrent設為false,多個job不會并發運行,第二個job將不會在第一個job完成之前開始




    防止job并行運行的幾種解決方案 
    一、JOB State 
    在通過MethodInvokingJobDetailFactoryBean在運行中動態生成的Job,配置的xml文件有個concurrent屬性,表示job是否可以并行運行:如果一個job的業務處理發費的時間超過了job的啟動的間隔時間(repeatInterval),這個屬性非常有用。如果為false,那么,在這種情況下,當前job還在運行,那么下一個job只能延時運行。如果為true,那么job就會并行運行。在實際的應用中應該配置為true/false,要根據需要了(廢話)。 
    二、如果通過繼承QuartzJobBean實現job的話,默認情況下QuartzJobBean是implements org.quartz.Job接口的,也就是說job示例是stateless的,會出現前面所述的并行情況。而代碼中卻要求job任務必需串行,解決辦法:在job子類中繼續implements org.quartz.StatefulJob。那么這個job實例變成了Stateful,job任務也就是串行的了。
    注: 
    在Quartz中,如果實現org.quartz.Job接口,那么這個job是stateless的,job實例的參數不能在多個任務之間共享,如果實現org.quartz.StatefulJob,這個job是個單例的,job實例的屬性可以從當前任務傳遞到下一個任務。 


    spring和quartz的整合對版本是有要求的。
    spring3.1以下的版本必須使用quartz1.x系列,3.1以上的版本才支持quartz 2.x,不然會出錯。

    至于原因,則是spring對于quartz的支持實現,org.springframework.scheduling.quartz.CronTriggerBean繼承了org.quartz.CronTrigger,在quartz1.x系列中org.quartz.CronTrigger是個類,而在quartz2.x系列中org.quartz.CronTrigger變成了接口,從而造成無法用spring的方式配置quartz的觸發器(trigger)。

    在Spring中使用Quartz有兩種方式實現:第一種是任務類繼承QuartzJobBean,第二種則是在配置文件里定義任務類和要執行的方法,類和方法可以是普通類。很顯然,第二種方式遠比第一種方式來的靈活。



    MethodInvokingJobDetailFactoryBean中concurrent和shouldRecover屬性的作用
    解釋 concurrent為true,則允許一個QuartzJob并發執行,否則就是順序執行。例如QuartzJob A執行時間為15秒,配置為每10秒執行一次;如果concurrent為true,則0秒的時候啟動一次A,10秒的時候再啟動一次A,20秒的時候再啟動一次A,不管前面啟動的A有沒有執行完;如果concurrent為false,則0秒的時候啟動一次A,15秒的時候A執行完畢,再第二次啟動A。
    shouldRecover屬性為true,則當Quartz服務被中止后,再次啟動或集群中其他機器接手任務時會嘗試恢復執行之前未完成的所有任務。例如QuartzJob B,在每次00秒的時候啟動,假如在03:00的任務執行完之后服務器1被中止,服務器2在05:15的時候才接手;如果shouldRecover屬性為true,則服務器2會嘗試著補回原來在04:00和05:00的時候應該做的任務,如果shouldRecover屬性為false,則服務器2只會從06:00的時候再執行B。


    Quartz集群只支持JDBCJobStore存儲方式,而MethodInvokingJobDetailFactoryBean不能序列化存儲job數據到數據庫,
    重寫 quartz 的 QuartzJobBean 類 
    原因是在使用 quartz+spring 把 quartz 的 task 實例化進入數據庫時,會產生: serializable 的錯誤,原因在于:
    這個 MethodInvokingJobDetailFactoryBean 類中的 methodInvoking 方法,是不支持序列化的,因此在把 QUARTZ 的 TASK 序列化進入數據庫時就會拋錯。網上有說把 SPRING 源碼拿來,修改一下這個方案,然后再打包成 SPRING.jar 發布,這些都是不好的方法,是不安全的。
    必須根據 QuartzJobBean 來重寫一個自己的類 。


    posted @ 2015-07-26 01:39 abin 閱讀(2121) | 評論 (0)編輯 收藏

    QRTZ_CALENDARS 以 Blob 類型存儲 Quartz 的 Calendar 信息 
    QRTZ_CRON_TRIGGERS 存儲 Cron Trigger,包括 Cron表達式和時區信息 
    QRTZ_FIRED_TRIGGERS 存儲與已觸發的 Trigger 相關的狀態信息,以及相聯 Job的執行信息QRTZ_PAUSED_TRIGGER_GRPS 存儲已暫停的 Trigger 組的信息 
    QRTZ_SCHEDULER_STATE 存儲少量的有關 Scheduler 的狀態信息,和別的 Scheduler實例(假如是用于一個集群中) 
    QRTZ_LOCKS 存儲程序的觀鎖的信息(假如使用了悲觀鎖) 
    QRTZ_JOB_DETAILS 存儲每一個已配置的 Job 的詳細信息 
    QRTZ_JOB_LISTENERS 存儲有關已配置的 JobListener 的信息 
    QRTZ_SIMPLE_TRIGGERS 存儲簡單的Trigger,包括重復次數,間隔,以及已觸的次數 
    QRTZ_BLOG_TRIGGERS Trigger 作為 Blob 類型存儲(用于 Quartz 用戶用 JDBC創建他們自己定制的 Trigger 類型,JobStore 并不知道如何存儲實例的時候) 
    QRTZ_TRIGGER_LISTENERS 存儲已配置的 TriggerListener 的信息 
    QRTZ_TRIGGERS 存儲已配置的 Trigger 的信息 
    --------------------------------------------------------------------------------------------------
    quartz 持久化數據庫表格字段解釋
    建表,SQL語句在quartz-1.6.6\docs\dbTables文件夾中可以找到,介紹下主要的幾張表: 
           表qrtz_job_details: 保存job詳細信息,該表需要用戶根據實際情況初始化 
           job_name:集群中job的名字,該名字用戶自己可以隨意定制,無強行要求 
           job_group:集群中job的所屬組的名字,該名字用戶自己隨意定制,無強行要求 
           job_class_name:集群中個note job實現類的完全包名,quartz就是根據這個路徑到classpath找到該job類 
           is_durable:是否持久化,把該屬性設置為1,quartz會把job持久化到數據庫中 
           job_data:一個blob字段,存放持久化job對象 

           表qrtz_triggers: 保存trigger信息 
           trigger_name: trigger的名字,該名字用戶自己可以隨意定制,無強行要求 
           trigger_group:trigger所屬組的名字,該名字用戶自己隨意定制,無強行要求 
           job_name: qrtz_job_details表job_name的外鍵 
           job_group: qrtz_job_details表job_group的外鍵 
           trigger_state:當前trigger狀態,設置為ACQUIRED,如果設置為WAITING,則job不會觸發 
           trigger_cron:觸發器類型,使用cron表達式 

           表qrtz_cron_triggers:存儲cron表達式表 
           trigger_name: qrtz_triggers表trigger_name的外鍵 
           trigger_group: qrtz_triggers表trigger_group的外鍵 
           cron_expression:cron表達式 
           
           表qrtz_scheduler_state:存儲集群中note實例信息,quartz會定時讀取該表的信息判斷集群中每個實例的當前狀態 
           instance_name:之前配置文件中org.quartz.scheduler.instanceId配置的名字,就會寫入該字段,如果設置為AUTO,quartz會根據物理機名和當前時間產生一個名字 
           last_checkin_time:上次檢查時間 
           checkin_interval:檢查間隔時間 

    步驟4
     配置quartz.properties文件:
    #調度標識名 集群中每一個實例都必須使用相同的名稱 org.quartz.scheduler.instanceName = scheduler
    #ID設置為自動獲取 每一個必須不同 org.quartz.scheduler.instanceId = AUTO
    #數據保存方式為持久化 org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
    #數據庫平臺 org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.oracle.weblogic.WebLogicOracleDelegate #數據庫別名 隨便取org.quartz.jobStore.dataSource = myXADS
    #表的前綴 org.quartz.jobStore.tablePrefix = QRTZ_
    #設置為TRUE不會出現序列化非字符串類到 BLOB 時產生的類版本問題 org.quartz.jobStore.useProperties = true
    #加入集群 org.quartz.jobStore.isClustered = true
    #調度實例失效的檢查時間間隔 org.quartz.jobStore.clusterCheckinInterval = 20000 
    #容許的最大作業延長時間 org.quartz.jobStore.misfireThreshold = 60000
    #ThreadPool 實現的類名 org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
    #線程數量 org.quartz.threadPool.threadCount = 10
    #線程優先級 org.quartz.threadPool.threadPriority = 5
    #自創建父線程 org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true 
    #設置數據源org.quartz.dataSource.myXADS.jndiURL = CT
    #jbdi類名 org.quartz.dataSource.myXADS.java.naming.factory.initial = weblogic.jndi.WLInitialContextFactory #URLorg.quartz.dataSource.myXADS.java.naming.provider.url = t3://localhost:7001

    【注】:在J2EE工程中如果想用數據庫管理Quartz的相關信息,就一定要配置數據源,這是Quartz的要求。
    posted @ 2015-07-23 15:31 abin 閱讀(654) | 評論 (0)編輯 收藏

    1、下載一個jrebel的文件,解壓到D:\Sys\jrebel6.0.0-crack,在eclipse的classpath路徑下面配置rebel.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.zeroturnaround.com" xsi:schemaLocation="http://www.zeroturnaround.com http://www.zeroturnaround.com/alderaan/rebel-2_0.xsd">
    <classpath>
    <dir name="D:\SystemFile\EclipseWorkspace\SpringAQConsume\target">
    </dir>
    </classpath>
    <web>
    <link target="/">
    <dir name="D:\SystemFile\EclipseWorkspace\SpringAQConsume\src\main\webapp">
    </dir>
    </link>
    </web>
    </application>

    2、在tomcat里面配置
     -javaagent:D:\Sys\jrebel6.0.0-crack\jrebel.jar -noverify  -Xbootclasspath/p:D:\Sys\jrebel6.0.0-crack\rebelboot.jar
     -javaagent:D:\Sys\jrebel-6.0.2\jrebel.jar -noverify  -Xbootclasspath/p:D:\Sys\jrebel-6.0.2\rebelboot.jar


    *********6.2.2需要以下設置**********
    -noverify
    -Djavaagent:D:/Sys\server/JRebel/JRebel6.2.0/jrebel.jar
    -DXbootclasspath/p:D:\Sys\server\JRebel\JRebel6.2.0\rebelboot.jar
    -Drebel.generate.show=true
    -Drebel.spring_plugin=true
    -Drebel.aspectj_plugin=true
    -Drebel.cxf_plugin=true
    -Drebel.logback_plugin=true
    -Drebel.mybatis_plugin=true
    -Xdebug -Djava.compiler=NONE -DXrunjdwp:transport=dt_socket,address=8787,server=y,suspend=n
    -Drebel.dirs=D:\SystemFile\EclipseWorkspace\integrate-svr\integrate-main\target\classes
    -Dmyproject.root=D:\SystemFile\EclipseWorkspace\integrate-svr
    -Drebel.disable_update=true
    posted @ 2015-06-24 11:43 abin 閱讀(3287) | 評論 (0)編輯 收藏

    《秒殺系統架構優化思路》


    上周參加Qcon,有個兄弟分享秒殺系統的優化,其觀點有些贊同,大部分觀點卻并不同意,結合自己的經驗,談談自己的一些看法。


    一、為什么難

    秒殺系統難做的原因:庫存只有一份,所有人會在集中的時間讀和寫這些數據。

    例如小米手機每周二的秒殺,可能手機只有1萬部,但瞬時進入的流量可能是幾百幾千萬。

    又例如12306搶票,亦與秒殺類似,瞬時流量更甚。


    二、常見架構


    流量到了億級別,常見站點架構如上:

    1)瀏覽器端,最上層,會執行到一些JS代碼

    2)站點層,這一層會訪問后端數據,拼html頁面返回給瀏覽器

    3)服務層,向上游屏蔽底層數據細節

    4)數據層,最終的庫存是存在這里的,mysql是一個典型


    三、優化方向

    1)將請求盡量攔截在系統上游:傳統秒殺系統之所以掛,請求都壓倒了后端數據層,數據讀寫鎖沖突嚴重,并發高響應慢,幾乎所有請求都超時,流量雖大,下單成功的有效流量甚小【一趟火車其實只有2000張票,200w個人來買,基本沒有人能買成功,請求有效率為0】

    2)充分利用緩存:這是一個典型的讀多些少的應用場景【一趟火車其實只有2000張票,200w個人來買,最多2000個人下單成功,其他人都是查詢庫存,寫比例只有0.1%,讀比例占99.9%】,非常適合使用緩存


    四、優化細節

    4.1)瀏覽器層請求攔截

    點擊了“查詢”按鈕之后,系統那個卡呀,進度條漲的慢呀,作為用戶,會不自覺的再去點擊“查詢”,繼續點,繼續點,點點點。。。有用么?平白無故的增加了系統負載(一個用戶點5次,80%的請求是這么多出來的),怎么整?

    a)產品層面,用戶點擊“查詢”或者“購票”后,按鈕置灰,禁止用戶重復提交請求

    b)JS層面,限制用戶在x秒之內只能提交一次請求

    如此限流,80%流量已攔


    4.2)站點層請求攔截與頁面緩存

    瀏覽器層的請求攔截,只能攔住小白用戶(不過這是99%的用戶喲),高端的程序員根本不吃這一套,寫個for循環,直接調用你后端的http請求,怎么整?

    a)同一個uid,限制訪問頻度,做頁面緩存,x秒內到達站點層的請求,均返回同一頁面

    b)同一個item的查詢,例如手機車次,做頁面緩存,x秒內到達站點層的請求,均返回同一頁面

    如此限流,又有99%的流量會被攔截在站點層


    4.3)服務層請求攔截與數據緩存

    站點層的請求攔截,只能攔住普通程序員,高級黑客,假設他控制了10w臺肉雞(并且假設買票不需要實名認證),這下uid的限制不行了吧?怎么整?

    a)大哥,我是服務層,我清楚的知道小米只有1萬部手機,我清楚的知道一列火車只有2000張車票,我透10w個請求去數據庫有什么意義呢?對于寫請求,做請求隊列,每次只透過有限的寫請求去數據層,如果均成功再放下一批,如果庫存不夠則隊列里的寫請求全部返回“已售完”

    b)對于讀請求,還用說么?cache來抗,不管是memcached還是redis,單機抗個每秒10w應該都是沒什么問題的

    如此限流,只有非常少的寫請求,和非常少的讀緩存mis的請求會透到數據層去,又有99.9%的請求被攔住了


    4.4)數據層閑庭信步

    到了數據這一層,幾乎就沒有什么請求了,單機也能扛得住,還是那句話,庫存是有限的,小米的產能有限,透過過多請求來數據庫沒有意義。


    五、總結

    沒什么總結了,上文應該描述的非常清楚了,對于秒殺系統,再次重復下筆者的兩個架構優化思路:

    1)盡量將請求攔截在系統上游

    2)讀多寫少的常用多使用緩存

    posted @ 2015-05-23 15:50 abin 閱讀(1366) | 評論 (0)編輯 收藏

    java 有for(;;)和 for(Object obj : List/Array)

    最明顯的一個:前者是有范圍;后者是全部。

    就編碼來說各有好處:for更靈活,foreach更簡便

    for和foreach都是java中重要的集合遍歷方法 
    for循環中 你可以選擇從前往后遍歷,也可以從后往前遍歷,也可以不遍歷默寫值
    但是foreach只能從前往后遍歷,而且每一個都會遍歷一次,他們之間的選擇得看你項目程序中的需求而定
    JVM在解釋執行行,都會將for與foreach解釋成iterator。

    總結如下:

    1.如果只是遍歷集合或者數組,用foreach好些,快些。

    2.如果對集合中的值進行修改,就要用for循環了。
    其實foreach的內部原理其實也是Iterator,但它不能像Iterator一樣可以人為的控制,而且也不能調用iterator.remove();
    更不能使用下標來訪問每個元素,所以不能用于增加,刪除等復雜的操作。



    posted @ 2015-05-21 23:59 abin 閱讀(386) | 評論 (0)編輯 收藏

        Twitter-Snowflake算法產生的背景相當簡單,為了滿足Twitter每秒上萬條消息的請求,每條消息都必須分配一條唯一的id,這些id還需要一些大致的順序(方便客戶端排序),并且在分布式系統中不同機器產生的id必須不同。

    生成的ID是64Bits整型數,同時滿足高性能(>10K ids/s),低延遲(<2ms)和高可用。

    在分布式系統中,需要生成全局UID的場合還是比較多的,twitter的snowflake解決了這種需求,實現也還是很簡單的,除去配置信息,核心代碼就是毫秒級時間41位+機器ID 10位+毫秒內序列12位。

    該項目地址為:https://github.com/twitter/snowflake是用Scala實現的。

    python版詳見開源項目https://github.com/erans/pysnowflake

    核心代碼為其IdWorker這個類實現,其原理結構如下,我分別用一個0表示一位,用—分割開部分的作用:

    0---0000000000 0000000000 0000000000 0000000000 0 --- 00000 ---00000 ---0000000000 00

    在上面的字符串中,第一位為未使用(實際上也可作為long的符號位),接下來的41位為毫秒級時間,然后5位datacenter標識位,5位機器ID(并不算標識符,實際是為線程標識),然后12位該毫秒內的當前毫秒內的計數,加起來剛好64位,為一個Long型。

    這樣的好處是,整體上按照時間自增排序,并且整個分布式系統內不會產生ID碰撞(由datacenter和機器ID作區分),并且效率較高,經測試,snowflake每秒能夠產生26萬ID左右,完全滿足需要。

    1. 41位的時間序列(精確到毫秒,41位的長度可以使用69年) 

    2. 10位的機器標識(10位的長度最多支持部署1024個節點,支持多機房的分布式,需要使用zookeeper) 

    3. 12位的計數順序號(12位的計數順序號支持每個節點每毫秒產生4096個ID序號) 最高位是符號位,始終為0。

    //64--------63-----------22-----------12----------0
    //符號位 |41位時間 |10位機器碼 |12位自增碼|

    對twitter而言這樣的ID生成方案滿足:

    1.每秒能夠生成足夠的ID數。 2.生成的ID按照時間大致有序。

    用zookeeper的原因是需要獲取一個workerId,當然你也可以給分布式節點手工指定不同的workderId,那樣就不需要用zookeeper了。

    一個server一個workerid, 用zookeeper做保證.


    除了最高位bit標記為不可用以外,其余三組bit占位均可浮動,看具體的業務需求而定。默認情況下41bit的時間戳可以支持該算法使用到2082年,10bit的工作機器id可以支持1023臺機器,序列號支持1毫秒產生4095個自增序列id
















    posted @ 2015-05-17 13:20 abin 閱讀(1207) | 評論 (0)編輯 收藏

    1.Http作為web服務的首選協議,居有4大優點:
       1)http非常簡單,以純文本(超文本)形式編碼的請求和響應組成
       2)http是無狀態的。一旦發送了一個http請求,客戶和服務器之間的連接信息就會被釋放,有利于減少服務器資源的消耗。
       3)http的運行端口80,在大多數防火墻上是公開的
       4)行業認可。
      但是Http的缺點:
       1)缺少對異步消息的支持
       2)消息傳輸的不可靠性

    web service相對http (post/get)有好處嗎?

     

    1.接口中實現的方法和要求參數一目了然

    2.不用擔心大小寫問題

    3.不用擔心中文urlencode問題

    4.代碼中不用多次聲明認證(賬號,密碼)參數

    5.傳遞參數可以為數組,對象等...

    http和webservice的區別:
    1、http是采用get,post等方式傳輸數據,而webservice是采用xml格式打包數據,傳輸是基于http協議進行傳輸。
    2、http直接傳輸數據,而webservice是采用xml編解碼數據,所以能速度上面有些慢。
    3、webservice可以直接傳輸數組或者對象的數據格式,實際現在常用的http+json也可以的,只是需要進行字符串和各種格式的轉換。
    4、http傳輸占用的帶寬要比webservice占用的帶寬少。
    5、webservice支持用戶權限的驗證,而http不支持直接的用戶權限驗證。
    6、webservice接口中實現的方法和要求參數一目了然。


    HTTPS和HTTP的區別:
    https協議需要到ca申請證書,一般免費證書很少,需要交費。
    http是超文本傳輸協議,信息是明文傳輸,https 則是具有安全性的ssl加密傳輸協議
    http和https使用的是完全不同的連接方式用的端口也不一樣,前者是80,后者是443。
    http的連接很簡單,是無狀態的
    HTTPS協議是由SSL+HTTP協議構建的可進行加密傳輸、身份認證的網絡協議 要比http協議安全


    SSL協議基礎

    SSL協議位于TCP/IP協議與各種應用層協議之間,本身又分為兩層:

    SSL記錄協議(SSL Record Protocol):建立在可靠傳輸層協議(TCP)之上,為上層協議提供數據封裝、壓縮、加密等基本功能。

    SSL握手協議(SSL Handshake Procotol):在SSL記錄協議之上,用于實際數據傳輸前,通訊雙方進行身份認證、協商加密算法、交換加密密鑰等。


    HTTPS通信過程:
    1.在服務器端存在一個公鑰及私鑰
    2.客戶端從服務器取得這個公鑰
    3.客戶端產生一個隨機的密鑰
    4.客戶端通過公鑰對密鑰加密(非對稱加密)
    5.客戶端發送到服務器端
    6.服務器端接受這個密鑰并且以后的服務器端和客戶端的數據全部通過這個密鑰加密(對稱加密)





















    posted @ 2015-05-10 11:27 abin 閱讀(1306) | 評論 (0)編輯 收藏

    Zookeeper有兩種運行模式:

    獨立模式(standalone mode):只運行在一臺服務器上,適合測試環境

    復制模式(replicated mode):運行于一個集群上,適合生產環境,這個計算機集群被稱為一個“集合體”(ensemble)。Zookeeper通過復制來實現高可用性,只要集合體中半數以上的機器處于可用狀態,它就能夠保證服務繼續。為什么一定要超過半數呢?這跟Zookeeper的復制策略有關:zookeeper確保對znode樹的每一個修改都會被復制到集合體中超過半數的機器上。

    生產環境,zookeeper集群的服務器數目應該是奇數。

    Zookeeper集群中的角色及其職責

    領導者

      1.管理寫請求

    跟隨者

      1.響應客戶端的讀請求

      2.負責把客戶端提交的寫請求轉發給領導者

     

    znode的觀察機制

     

    znode以某種方式發生變化時,“觀察”(watch)機制可以讓客戶端得到通知。可以針對ZooKeeper服務的“操作”來設置觀察,該服務的其他操作可以觸發觀察。比如,客戶端可以對某個客戶端調用exists操作,同時在它上面設置一個觀察,如果此時這個znode不存在,則exists返回false,如果一段時間之后,這個znode被其他客戶端創建,則這個觀察會被觸發,之前的那個客戶端就會得到通知。

    sync: 將客戶端的znode視圖與ZooKeeper同步
    SYNC消息:返回SYNC結果到客戶端,這個消息最初由客戶端發起,用來強制得到最新的更新。

    跨客戶端視圖的并發一致性:

    ZooKeeper并不保證在某時刻,兩個不同的客戶端具有一致的數據視圖。因為網絡延遲的原因,一個客戶端可能在另一個客戶端得到修改通知之前進行更新。假定有兩個客戶端AB。如果客戶端A將一個節點/a的值從0修改為1,然后通知客戶端B讀取/a,客戶端B讀取到的值可能還是0,這取決于它連接到了哪個服務器。如果客戶端AB讀取到相同的值很重要,那么客戶端B應該在執行讀取之前調用sync()方法。

    所以,ZooKeeper本身不保證修改在多個服務器間同步地發生,但是可以使用ZooKeeper原語來構建高層功能,提供有用的客戶端同步。



     設計目的
    1.最終一致性:client不論連接到哪個Server,展示給它都是同一個視圖,這是zookeeper最重要的性能。
    2 .可靠性:具有簡單、健壯、良好的性能,如果消息m被到一臺服務器接受,那么它將被所有的服務器接受。
    3 .實時性:Zookeeper保證客戶端將在一個時間間隔范圍內獲得服務器的更新信息,或者服務器失效的信息。但由于網絡延時等原因,Zookeeper不能保證兩個客戶端能同時得到剛更新的數據,如果需要最新數據,應該在讀數據之前調用sync()接口。
    4 .等待無關(wait-free):慢的或者失效的client不得干預快速的client的請求,使得每個client都能有效的等待。
    5.原子性:更新只能成功或者失敗,沒有中間狀態。
    6 .順序性:包括全局有序和偏序兩種:全局有序是指如果在一臺服務器上消息a在消息b前發布,則在所有Server上消息a都將在消息b前被發布;偏序是指如果一個消息b在消息a后被同一個發送者發布,a必將排在b前面。


    節點宕機:

    應用集群中,我們常常需要讓每一個機器知道集群中(或依賴的其他某一個集群)哪些機器是活著的,并且在集群機器因為宕機,網絡斷鏈等原因能夠不在人工介入的情況下迅速通知到每一個機器。
    Zookeeper同樣很容易實現這個功能,比如我在zookeeper服務器端有一個znode叫/APP1SERVERS,那么集群中每一個機器啟動的時候都去這個節點下創建一個EPHEMERAL類型的節點,比如server1創建/APP1SERVERS/SERVER1(可以使用ip,保證不重復),server2創建/APP1SERVERS/SERVER2,然后SERVER1和SERVER2都watch /APP1SERVERS這個父節點,那么也就是這個父節點下數據或者子節點變化都會通知對該節點進行watch的客戶端。因為EPHEMERAL類型節點有一個很重要的特性,就是客戶端和服務器端連接斷掉或者session過期就會使節點消失,那么在某一個機器掛掉或者斷鏈的時候,其對應的節點就會消失,然后集群中所有對/APP1SERVERS進行watch的客戶端都會收到通知,然后取得最新列表即可。


    zookeeper是一個高可用性,高性能的協調服務
    解決哪些問題
    在分布式應用中,經常會出現部分失敗的情況,即當節點間傳遞消息的時候由于網絡或者接收者進程死掉等原因,發送者無法知道接收者是否收到消息。
    由于部分失敗是分布式系統固有的特征因此zookeeper并不能避免部分失敗,但是它可以幫你在部分失敗的時候進行正確處理
    為了解決這個問題zookeeper具有以下特征:
    1:zookeeper提供豐富的構件(building block)來實現很多協調數據結構和協議
    2:訪問原子性,客戶端要么讀到所有數據,要么讀取失敗,不會出現只讀取部分的情況
    3:zookeeper運行在一組機器上,具有高可用性,幫助系統避免單點故障,同時刪掉故障服務器
    4:順序一致性:任意客戶端的更新請求會被按照發送順序提交
    5:單一系統映像:當一臺服務器故障,導致它的客戶端需要連接其它服務器的時候,所有更新晚于故障服務器的服務器都不會接收請求,一直到更新趕上故障服務器
    6:及時性:任何客戶端能看到的滯后都是有限的,不會超過幾十秒,且提供sync操作強制客戶端所連的服務器與領導者同步
    7:會話:每個客戶端連接時會嘗試連接到配置列表中的一臺服務器,一旦失敗會自動連接另一臺服務器依次類推,知道成功連接一臺服務器,從而創建一個會話,客戶端可以位每個會話設置超時時間,一旦會話過期,則所有短暫znode會丟失,因為zookeeper會自動發送心跳包,所以很少發生
    8:約會機制(rendezvous),在交互的過程中,被協調的各方不許要事先彼此了解,甚至不必同時存在
    9:ACL:zookeeper提供了digest(通過用戶名密碼),host(通過主機名),ip(通過ip地址)3種身份驗證模式,依賴與zookeeper的身份驗證機制每個ACL都是一個身份對應一組權限,如果我們要給demo.com的客戶端域一個讀權限在java語言中可以這樣創建:
    new ACL(Perms.READ, new Id("host", "demo.com"));
    Ids.OPEN_ACL_UNSAFE是將所有ADMIN之外的權限授予每個人
    另zookeeper還可以集成第三方的身份驗證系統
    10:提供關于通用協調模式的開源共享資源庫
    11:高性能的(官方數據)對以寫為主的工作負載來說使用5臺不錯的機器基準吞吐量達到10000+




    posted @ 2015-05-08 22:10 abin 閱讀(649) | 評論 (0)編輯 收藏

    各種設計模式--應用場景:
    裝飾器模式:
    1、類繼承會導致類的膨脹,這時候裝飾器就派上用場了
    責任鏈模式:
    1、ifelse 用責任鏈來實現
    狀態模式:
    1、ifelse
    適配器模式:目的是在原來代碼的基礎上面,增加一些修飾的東西。
    1、訂單信息,比如增加了活動了之后,返回結果中要包含活動信息,在原來代碼的基礎上面給返回的Bean里面增加一些活動信息。
    代理模式:
     比如吧,我有一個業務,同時要調用外部系統的http實現的接口和webservice實現的接口,可以做一個代理類, 代理webservice接口和http接口, 代理類幫我判斷該用哪個, 我直接調用代理類就行了。代理類專門屏蔽后面的接口或者協議。
    模板方法模式:
    1、比如訂單的下單還有退款操作,都需要同時判斷使用的金額和紅包。
    2、支付的時候,調用不同的支付方式,都需要去做判斷。
    策略模式:





    策略模式和裝飾器模式區別:
    策略模式偏向于對實現方法或策略的封裝,調用者不需要考慮具體實現,只要指定使用的策略即可。
    裝飾器模式一般用于需要對功能進行擴展的場合,每一種裝飾都是一種擴展或增強。

    看起來兩個模式好像沒有必然的聯系,但是在實際使用過程中,發現了一個讓我困惑的地方。
    先看一個典型的場景:
                商場對客戶打折,老客戶8折,新客戶9折,新客戶購物滿3000,打8.5折
    對這個基本場景,一般給的經典模式是策略模式,很多書也以這個作為策略模式的的經典案例。
    但是,如果我把每一種折扣看作是一種對原有價格的裝飾,這個場景也是可以用裝飾器模式實現的。
    兩個模式都需要花費一些代碼去判斷策略或裝飾器的類型,而且實現難度也旗鼓相當。

    我用兩種模式都實現了相同的功能,但是卻沒有發現明顯的區別,不知道大家對這兩個模式怎么看,
    歡迎討論。


    策略模式更傾向是N選1的模式,也即根據條件選擇相應的算法,但各種算法是互斥的,比如:團體客戶和個人客戶的優惠政策必然是非此即彼的;

    裝飾模式是在主體邏輯的基礎上的附加邏輯,比如,個人客戶有的屬于同城客戶,支持送貨上門。

    謝謝您的回復,如果按照策略模式,每一種打折方案是一種策略,而且只能選擇一個,這是沒有問題的。
    按照裝飾模式,每一種折扣都是在購買金額上的附加,在沒有折上折或者送貨上門這些附加值的時候,我感覺裝飾模式也是實用的,當然,當折上折和送貨這種附加體現的時候,裝飾起的模式就體現去來了。

    所以,我感覺在當前描述的問題中,這兩個模式應該都可以很恰當的實現需求,但是沒感覺到本質的區別。
    于是就有些困惑了,看了您的總結,我感覺自己有點鉆牛角了。
    如果這個場景新增附加需求,比如新增vip客戶,那么策略模式就比較合適了。
    但是如果進行折上折或者送貨上門這類附加需求,很明顯裝飾模式會更好一些了。
    看來具體的模式還得根據實際需求確定,不能死搬硬套。
    盡管樓主可以使用兩種模式實現自己說的場景,但是兩者還是有本質的區別。

    策略模式,已經說的很清楚, 就不多說了。

    裝飾模式是主題邏輯的基礎上的加強。可以看看JAVA IO的設計。
    就像樓上說的, 如果客戶購買滿5000, 不只可以享受7折優惠, 還可以送貨上門。
    這里有兩項功能: 1) 7折優惠, 2)送貨上門
    如果使用策略模式, 我們勢必把兩項功能都寫在一個策略的實現類里面。
    假使現在有新的場景出現,就是老客戶購買滿3000, 也享受送貨上門。(或者說這里面的還蘊藏一些其他的優惠,比如說返券等等)
    難道我們又把這些功能添加到我們的策略里面, 這樣代碼就很生硬而且不容易修改。

    但是使用裝飾模式就不一樣,裝飾模式能動態的給對象增加特有的功能。 比如說IO里面可以添加Buffer的功能。 同樣在我們的場景里面,我們也可以將送貨上門、返券等也動態的增強, new 送貨上門(new 返券())...., 這樣子就很靈活了。

    策略實現可能類似:
    do7折();
    do送貨上門();
    do返券()

    裝飾的實現可能了類似:
    new 7折( new 送貨上門(new 返券())), 能隨意組合;

    所有的優惠都享受上了, 看上去還是爽一點。 

    其實裝飾模式, 還是更符合設計的一條原則: 少繼承, 多組合 
    posted @ 2015-05-08 17:32 abin 閱讀(493) | 評論 (0)編輯 收藏

    僅列出標題
    共50頁: 上一頁 1 2 3 4 5 6 7 8 9 下一頁 Last 
    主站蜘蛛池模板: 黄页网站在线免费观看| 国产成人高清精品免费软件 | 国产无遮挡色视频免费观看性色| 亚洲色成人网一二三区| 中文字幕亚洲综合久久男男| 大香人蕉免费视频75| 182tv免费视视频线路一二三| 精品乱子伦一区二区三区高清免费播放| 亚洲一区二区三区在线观看网站 | 一区二区三区免费视频网站| 亚洲私人无码综合久久网| 亚洲国产美国国产综合一区二区 | 亚洲国产精品无码久久久秋霞1| 亚洲综合视频在线观看| 亚洲国产精品嫩草影院在线观看| 亚洲精品国产精品乱码不卡| 蜜臀91精品国产免费观看| 国产精品久久免费| 95老司机免费福利| 午夜免费福利视频| 免费成人在线视频观看| 两个人日本免费完整版在线观看1| 欧亚一级毛片免费看| 无遮挡呻吟娇喘视频免费播放| 亚洲另类自拍丝袜第五页| 久久乐国产综合亚洲精品| 亚洲一级特黄特黄的大片| 亚洲一级视频在线观看| 亚洲午夜成激人情在线影院 | 青娱乐免费视频在线观看| 16女性下面无遮挡免费| 67194成手机免费观看| 99久久精品国产免费| 久久亚洲免费视频| 免费国产黄网站在线观看可以下载| 在线成人精品国产区免费| 久久午夜免费鲁丝片| 1000部拍拍拍18免费网站| 亚洲国产精品免费观看| 大地资源免费更新在线播放| 成人免费无码大片A毛片抽搐|