志當存高遠,功到自然成!

          少年強則中國強,少年進步則中國進步!

          BlogJava 首頁 新隨筆 聯系 聚合 管理
            53 Posts :: 2 Stories :: 2 Comments :: 0 Trackbacks

          2009年2月2日 #

          mysql 5.1支持觸發器以及自定義函數接口(UDF)的特性,如果配合libmemcache以及Memcached Functions for MySQL,就能夠實現memcache的自動更新。簡單記錄一下安裝測試步驟。

            mysql 5.1支持觸發器以及自定義函數接口(UDF)的特性,如果配合libmemcache以及Memcached Functions for MySQL,就能夠實現memcache的自動更新。簡單記錄一下安裝測試步驟。

            安裝步驟

            安裝memcached,這個步驟很簡單,隨處可見。安裝mysql server 5.1RC,安裝辦法也很大眾,不廢話 了。

            編譯libmemcached,解壓后安裝即可./configure; make; make install

            編譯Memcached Functions for MySQL,在http://download.tangent.org/找一個最新的版本下載就 是,./configure --with-mysql=/usr/local/mysql/bin/mysql_config -- libdir=/usr/local/mysql/lib/mysql/

            make

            make install

            接下來有兩個辦法讓Memcached Functions for MySQL在mysql中生效。

            在mysql的shell中執行memcached_functions_mysql源碼目錄下的sql/install_functions.sql,這會 把memcache function作為UDF加入mysql。

            運行memcached_functions_mysql源碼目錄下的utils/install.pl,這是一個perl腳本,作用同上一 條。

            測試memcache function。

            以下測試腳本摘自memcached_functions_mysql的源碼目錄,有興趣可以試試。


          PLAIN TEXTCODE: drop table if exists urls;
          create table urls (
          id int(3) not null,
          url varchar(64) not null default '',
          primary key (id)
          );
          select memc_servers_set('localhost:11211');
          select memc_set('urls:sequence', 0);
          DELIMITER |
          DROP TRIGGER IF EXISTS url_mem_insert;
          CREATE TRIGGER url_mem_insert
          BEFORE INSERT ON urls
          FOR EACH ROW BEGIN
          SET NEW.id= memc_increment('urls:sequence');
          SET @mm= memc_set(concat('urls:',NEW.id), NEW.url);
          END |
          DELIMITER ;
          insert into urls (url) values ('http://google.com');
          insert into urls (url) values ('http://www.ooso.net/index.php');
          insert into urls (url) values ('http://www.ooso.net/');
          insert into urls (url) values ('http://slashdot.org');
          insert into urls (url) values ('http://mysql.com');
          select * from urls;
          select memc_get('urls:1');
          select memc_get('urls:2');
          select memc_get('urls:3');
          select memc_get('urls:4');
          select memc_get('urls:5');
          posted @ 2010-08-12 15:22 存鷹之心于高遠,取鷹之志而凌云,習鷹之性以涉險,融鷹之神在山巔. 閱讀(475) | 評論 (0)編輯 收藏

          假設我們有3臺memcached 服務器,server1 和server2 有3GB 的內存空間,server3 有2GB 的內存空間.
          下面程序說明怎么來創建客戶端.
          import com.danga.MemCached.*;

          public class MyClass {

          // 創建一個 memcached 客戶端對象

          protected static MemCachedClient mcc = new MemCachedClient();

          // 創建  memcached連接池

          static

          {  // 指定memcached服務地址 String[] servers =
          { "server1.mydomain.com:1121","server2.mydomain.com:1121",
          "server3.mydomain.com:1121" };
          // 指定memcached服務器負載量
          Integer[]  weights    ={ 3, 3, 2 };
          // 從連接池獲取一個連接實例

          SockIOPool pool = SockIOPool.getInstance();

          // 設置服務器和服務器負載量

          pool.setServers( servers );

          pool.setWeights( weights );

          // 設置一些基本的參數

          //設置初始連接數5   最小連接數 5   最大連接數 250

          //設置一個連接最大空閑時間6小時

          pool.setInitConn( 5 );

          pool.setMinConn( 5 );

          pool.setMaxConn( 250 );

          pool.setMaxIdle( 1000 * 60 * 60 * 6 );

          // 設置主線程睡眠時間

          // 每隔30秒醒來  然后

          // 開始維護 連接數大小

          pool.setMaintSleep( 30 );

          // 設置tcp 相關的樹形

          // 關閉nagle算法

          // 設置 讀取 超時3秒鐘  set the read timeout to 3 secs

          //  不設置連接超時

          pool.setNagle( false );

          pool.setSocketTO( 3000 );

          pool.setSocketConnectTO( 0 );

          // 開始初始化 連接池

          pool.initialize();

          // 設置壓縮模式

          //如果超過64k壓縮數據

          mcc.setCompressEnable( true );

          mcc.setCompressThreshold( 64 * 1024 );

          }

          public static void examples() {

          mcc.set( "foo", "This is a test String" );

          String bar = mcc.get( "foo" );

          }

          }
          MemCachedClient 類 常用的方法說明

          創建 client對象 設置參數:

          MemCachedClient mc = new MemCachedClient();
          //壓縮模式
          mc.setCompressEnable(true);
          // 如果 cache數據 大于4 KB  就啟用壓縮
          mc.setCompressThreshold(4096);
          // 基本類型tostring方法
          // 通常不需要設置
          mc.setPrimitiveAsString(true);
          存儲一個對象:

          MemCachedClient mc = new MemCachedClient();

          String key   = "cacheKey1";

          Object value = SomeClass.getObject();

          mc.set(key, value);
          用客戶端hashcode 存儲一個對象:


          MemCachedClient mc = new MemCachedClient();

          String key   = "cacheKey1";

          Object value = SomeClass.getObject();

          Integer hash = new Integer(45);

          mc.set(key, value, hash);

          set方法:在cache中存儲一個指定對象

             add 和replace 方法功能差不多

            add -- 如果不存在 這個key的對象,將會存儲一個對象到cache中
            replace --只有當存在指定key對象的時候 會覆蓋已有對象
          刪除一個對象:

          MemCachedClient mc = new MemCachedClient();

          String key   = "cacheKey1";

          mc.delete(key);
          結合hashcode 刪除一個對象:

          MemCachedClient mc = new MemCachedClient();

          String key   = "cacheKey1";

          Integer hash = new Integer(45);

          mc.delete(key, hashCode);
          怎么cache計數,增 減計數:

          MemCachedClient mc = new MemCachedClient();

          String key   = "counterKey";

          mc.storeCounter(key, new Integer(100));

          System.out.println("counter after adding      1: " mc.incr(key));

          System.out.println("counter after adding      5: " mc.incr(key, 5));

          System.out.println("counter after subtracting 4: " mc.decr(key, 4));

          System.out.println("counter after subtracting 1: " mc.decr(key));
          利用客戶端的hashcode存儲計數 增減 計數:

          MemCachedClient mc = new MemCachedClient();

          String key   = "counterKey";

          Integer hash = new Integer(45);

          mc.storeCounter(key, new Integer(100), hash);

          System.out.println("counter after adding      1: " mc.incr(key, 1, hash));

          System.out.println("counter after adding      5: " mc.incr(key, 5, hash));

          System.out.println("counter after subtracting 4: " mc.decr(key, 4, hash));

          System.out.println("counter after subtracting 1: " mc.decr(key, 1, hash));
          獲取一個對象:

          MemCachedClient mc = new MemCachedClient();

          String key   = "key";

          Object value = mc.get(key);
          用客戶端hashcode獲取一個對象:

          MemCachedClient mc = new MemCachedClient();

          String key   = "key";

          Integer hash = new Integer(45);

          Object value = mc.get(key, hash);
          MemCachedClient mc = new MemCachedClient();

          String key   = "key";

          Integer hash = new Integer(45);

          Object value = mc.get(key, hash);
          從cache 中獲取多個對象

          MemCachedClient mc = new MemCachedClient();

          String[] keys      ={ "key", "key1", "key2" };Mapvalues = mc.getMulti(keys);
          用客戶端hashcode 從cache中獲取多個對象
          MemCachedClient mc = new MemCachedClient();
          String[] keys      = { "key", "key1", "key2" };

          Integer[] hashes   =
          { new Integer(45), new Integer(32), new Integer(44) };
          Mapvalues = mc.getMulti(keys, hashes);
          清空所有的對象
          MemCachedClient mc = new MemCachedClient();

          mc.flushAll();
          得到服務器memcached的狀態信息
          MemCachedClient mc = new MemCachedClient();

          Map stats = mc.stats();
          注意點
          1:Failover/Failback
          當一個memcached服務器失效的時候客戶端默認會failover另一個服務去.

          如果失效的服務器 恢復運行,客戶端會返回到原來連接的服務器.
          如果你不想用這個功能 設置下面的參數
          pool.setFailover( false );
          pool.setFailback( false );

          2:序列化

          Boolean
          Byte
          String
          Character
          StringBuffer
          StringBuilder
          Short
          Long
          Double
          Float
          Date
          java默認的類型沒有實現序列化 可以設置
          mcc.setPrimitiveAsString( true )替代.
          Meetup.com實踐過程中得出的一個經驗 ,項目中model 對象implement Externalizable 實現序列化,
          可以節省cache 對象的大小。從而節省網絡帶寬和內存空間。
          posted @ 2010-08-11 23:21 存鷹之心于高遠,取鷹之志而凌云,習鷹之性以涉險,融鷹之神在山巔. 閱讀(10777) | 評論 (1)編輯 收藏

          一:硬架構

          1 :機房的選擇:

          在 選擇機房的時候,根據網站用戶的地域分布,可以選擇網通或電信機房,但更多時候,可能雙線機房才是合適的。越大的城市,機房價格越貴,從成本的角度看可以 在一些中小城市托管服務器,比如說廣州的公司可以考慮把服務器托管在東莞,佛山等地,不是特別遠,但是價格會便宜很多。

          2 :帶寬的大小:

          通常老板花錢請我們架構網站的時候,會給我們提出一些目標,諸如網站每天要能承受100 萬PV 的訪問量等等。這時我們要預算一下大概需要多大的帶寬,計算帶寬大小主要涉及兩個指標(峰值流量和頁面大小),我們不妨在計算前先做出必要的假設:

          第一:假設峰值流量是平均流量的5 倍。
          第二:假設每次訪問平均的頁面大小是100K 字節左右。

          如果100 萬PV 的訪問量在一天內平均分布的話,折合到每秒大約12 次訪問,如果按平均每次訪問頁面的大小是100K 字節左右計算的話,這12 次訪 問總計大約就是1200K 字節,字節的單位是Byte ,而帶寬的單位是bit ,它們之間的關系是1Byte = 8bit ,所以1200K Byte 大致就相當于9600K bit ,也就是9Mbps 的樣子,實際情況中,我們的網站必須能在峰值流量時保持正常訪問,所以按照假設的峰值流量算,真實帶寬的需求應該在45Mbps  左右。

          當然,這個結論是建立在前面提到的兩點假設的基礎上,如果你的實際情況和這兩點假設有出入,那么結果也會有差別。

          3 :服務器的劃分:

          先看我們都需要哪些服務器:圖片服務器,頁面服務器,數據庫服務器,應用服務器,日志服務器等等。

          對于訪問量大點的網站而言,分離單獨的圖片服務器和頁面服務器相當必要,我們可以用lighttpd 來跑圖片服務器,用apache 來跑頁面服務 器,當然也可以選擇別的,甚至,我們可以擴展成很多臺圖片服務器和很多臺頁面服務器,并設置相關域名,如img.domain.com 和 www.domain.com ,頁面里的圖片路徑都使用絕對路徑,如<img src="http://img.domain.com/abc.gif" /> ,然后設置DNS 輪循,達到最初級的負載均衡。當然,服務器多了就不可避免的涉及一個同步的問題,這個可以使用rsync 軟件來搞定。

          數據庫服務器是重中之重,因為網站的瓶頸問題十有八九是出在數據庫身上。現在一般的中小網站多使用MySQL 數據庫,不過它的集群功能似乎還沒有達 到stable 的階段,所以這里不做評價。一般而言,使用MySQL 數據庫的時候,我們應該搞一個主從(一主多從)結構,主數據庫服務器使用innodb  表結構,從數據服務器使用myisam 表結構,充分發揮它們各自的優勢,而且這樣的主從結構分離了讀寫操作,降低了讀操作的壓力,甚至我們還可以設定一個專門的從服務器做備份服務器,方便備份。不然如果你只有一臺主服務器,在大數據量的情況下,mysqldump 基本就沒戲了,直接拷貝數據文件的話,還得先停止數據庫服務再拷貝,否則備份文件會出錯。但對于很多網站而言,即使數據庫服務僅停止了一秒也是不可接受的。如果你有了一臺從數據庫服務器,在備份數 據的時候,可以先停止服務(slave stop )再備份,再啟動服務(slave start )后從服務器會自動從主服務器同步數據,一切都沒有影響。但是主從結構也是有致命缺點的,那就是主從結構只是降低了讀操作的壓力,卻不能降低寫操作的壓力。為了適應更大的規模,可能只剩下最后這招了:橫向/ 縱向分割數據庫。所謂橫向分割數據庫,就是把不同的表保存到不同的數據庫服務器上,比如說用戶表保存在A 數據庫服務器上,文章表保存在B 數據庫服務器上,當然這樣的分割是有代價的,最基本的就是你沒法進行LEFT JOIN 之類的操作了。所謂縱向分割數據庫,一般是指按照用戶標識(user_id )等來劃分數據存儲的服務器,比如說:我們有5 臺數據庫服務器,那么 “user_id % 5 + 1” 等于1 的就保存到1 號服務器,等于2 的就保存到2 好服務器,以此類推,縱向分隔的原則有很多種,可以視情況選擇。不過和橫向分割數據庫一樣,縱向分割 數據庫也是有代價的,最基本的就是我們在進行如COUNT, SUM 等匯總操作的時候會麻煩很多。綜上所述,數據庫服務器的解決方案一般視情況往往是一個混合的方案,以其發揮各種方案的優勢,有時候還需要借助 memcached 之類的第三方軟件,以便適應更大訪問量的要求。

          如果有專門的應用服務器來跑PHP 腳本是最合適不過的了,那樣我們的頁面服務器只保存靜態頁面就可以了,可以給應用服務器設置一些諸如 app.domain.com 之類的域名來和頁面服務器加以區別。對于應用服務器,我還是更傾向于使用prefork 模式的apache ,配上必要的 xcache 之類的PHP 緩存軟件,加載模塊要越少越好,除了mod_rewrite 等必要的模塊,不必要的東西統統舍棄,盡量減少httpd 進程的內存消耗,而那些圖片服務器,頁面服務器等靜態內容就可以使用lighttpd 或者tux 來搞,充分發揮各種服務器的特點。

          如果條件允許,獨立的日志服務器也是必要的,一般小網站的做法都是把頁面服務器和日志服務器合二為一了,在凌晨訪問量不大的時候cron 運行前一天 的日志計算,不過如果你使用awstats 之類的日志分析軟件,對于百萬級訪問量而言,即使按天歸檔,也會消耗很多時間和服務器資源去計算,所以分離單獨的日志服務器還是有好處的,這樣不會影響正式服務器的工作狀態。

          二:軟架構

          1 :框架的選擇:

          現在的PHP 框架有很多選擇,比如:CakePHP ,Symfony ,Zend Framework 等等,至于應該使用哪一個并沒有唯一的答案,要根據Team 里團隊成員對各個框架的了解程度而定。很多時候,即使沒有使用框架,一樣能寫出好的程序來,比如Flickr 據說就是用Pear+Smarty 這樣的類庫寫出來的,所以是否用框架,用什么框架,一般不是最重要,重要的是我們的編程思想里要有框架的意識。

          現在的.NET 框架有很多選擇,比如:cnForums ,.text ,cs, Castle, 等等

          2 :邏輯的分層:

          網站規模到了一定的程度之后,代碼里各種邏輯糾纏在一起,會給維護和擴展帶來巨大的障礙,這時我們的解決方式其實很簡單,那就是重構,將邏輯進行分層。通常,自上而下可以分為表現層,應用層,領域層,持久層。

          所 謂表現層,并不僅僅就指模板,它的范圍要更廣一些,所有和表現相關的邏輯都應該被納入表現層的范疇。比如說某處的字體要顯示為紅色,某處的開頭要空兩格, 這些都屬于表現層。很多時候,我們容易犯的錯誤就是把本屬于表現層的邏輯放到了其他層面去完成,這里說一個很常見的例子:我們在列表頁顯示文章標題的時 候,都會設定一個最大字數,一旦標題長度超過了這個限制,就截斷,并在后面顯示“..” ,這就是最典型的表現層邏輯,但是實際情況,有很多程序員都是在非表現層代碼里完成數據的獲取和截斷,然后賦值給表現層模板,這樣的代碼最直接的缺點就是同樣一段數據,在這個頁面我可能想顯示前10 個字,再另一個 頁面我可能想顯示前15 個字,而一旦我們在程序里固化了這個字數,也就喪失了可移植性。正確的做法是應該做一個視圖助手之類的程序來專門處理此類邏輯,比如說:Smarty 里的truncate 就屬于這樣的視圖助手(不過它那個實現不適合中文)。

          所謂應用層,它的主要作用是定義用戶可以做什么,并把操作結果反饋給表現層。至于如何做,通常不是它的職責范圍(而是領域層的職責范圍),它會通過委派把如何做的工作交給領域層去處理。在使用MVC 架構的網站中,我們可以看到類似下面這樣的URL :domain.com/articles/view/123 ,其內部編碼實現,一般就是一個Articles 控制器類,里面有一個view 方法,這就是一 個典型的應用層操作,因為它定義了用戶可以做一個查看的動作。在MVC 架構中,有一個準則是這么說的:Rich Model Is Good 。言外之意,就是Controller 要保持“ 瘦” 一些比較好,進而說明應用層要盡量簡單,不要包括涉及領域內容的邏輯。

          所謂領域層,最直接的解釋就是包含領域邏輯的層。它是一個軟件的靈魂所在。先來看看什么叫領域邏輯,簡單的說,具有明確的領域概念的邏輯就是領域邏輯,比如我們在ATM 機上取錢,過程大致是這樣的:插入銀聯卡,輸入密碼,輸入取款金額,確定,拿錢,然后ATM 吐出一個交易憑條。在這個過程中,銀聯卡 在ATM 機器里完成錢從帳戶上劃撥的過程就是一個領域邏輯,因為取錢在銀行中是一個明確的領域概念,而ATM 機吐出一個交易憑條則不是領域邏輯,而僅是一 個應用邏輯,因為吐出交易憑條并不是銀行中一個明確的領域概念,只是一種技術手段,對應的,我們取錢后不吐交易憑條,而發送一條提醒短信也是可能的,但并 不是一定如此,如果在實際情況中,我們要求取款后必須吐出交易憑條,也就是說吐出交易憑條已經和取款緊密結合,那么你也可以把吐出交易憑條看作是領域邏輯 的一部分,一切都以問題的具體情況而定。在Eric 那本經典的領域驅動設計中,把領域層分為了五種基本元素:實體,值對象,服務,工廠,倉儲。具體可以參 閱書中的介紹。領域層最常犯的錯誤就是把本應屬于領域層的邏輯泄露到了其他層次,比如說在一個CMS 系統,對熱門文章的定義是這樣的:每天被瀏覽的次數多 于1000 次,被評論的次數多于100 次,這樣的文章就是熱門文章。對于一個CMS 來說,熱門文章這個詞無疑是一個重要的領域概念,那么我們如何實現這個邏輯的設計的?你可能會給出類似下面的代碼:“SELECT ... FROM ... WHERE  瀏覽 > 1000 AND  評論 > 100” ,沒錯,這是最簡單的實現方式,但是這里需要注意的是“ 每天被瀏覽的次數多于1000 次,被評論的次數多于100 次” 這個重要的領域邏輯被隱藏到了SQL 語句中,SQL 語句顯然不屬于領域層的范疇,也就是說,我們的領域邏輯泄露了。

          所謂持久層,就是指把我們的領域模型保存到數據庫中。因為我們的程序代碼是面向對象風格的,而數據庫一般是關系型的數據庫,所以我們需要把領域模型 碾平,才能保存到數據庫中,但是在 PHP 里,直到目前還沒有非常好的 ORM 出現,所以這方面的解決方案不是特別多,參考 Martin 的企業應用架構模式一   書,大致可以使用的方法有行數據入口( Row Data Gateway )或者表數據入口( Table Data Gateway),或者把領域層和持久層合二為一變成活動記錄(Active Record)的方式。

          posted @ 2010-08-11 14:32 存鷹之心于高遠,取鷹之志而凌云,習鷹之性以涉險,融鷹之神在山巔. 閱讀(433) | 評論 (0)編輯 收藏

          TOMCAT崩潰事件

          http://www.aygfsteel.com/tedeyang/archive/2008/06/04/205740.html

          今天一大早產品一部項目經理就來找我,他們的一臺服務器昨天晚上tomcat服務崩潰,還不能重啟服務,最后將服務器重啟才OK。
          我將事件過程和分析過程記錄如下:

          服務器:win 2000 sp4,apache 2 + tomcat 5.0 采用mod_jk級聯。內存2G,硬盤剩余空間充足,CPU基本空閑。
          主要應用:J2EE 1.4,JDBC(連接另一臺mysql服務器)
          崩潰時間: 2008-6-3 18:37:50

          一.各種日志綜合如下:

             1.37分45秒,操作系統事件中諾頓殺毒軟件報內存過低警報
             2.37分45秒,web應用拋出JDBC連接異常:

          2008-06-03 18:37:45 cn.*.db.DBManager.getConnection(DBManager.java:157) ERROR swim.db.DBManager   com.mysql.jdbc.CommunicationsException: Communications link failure due to underlying exception:
          ** BEGIN NESTED EXCEPTION **
          java.net.SocketException
          MESSAGE: java.net.SocketException: No buffer 
          space available (maximum connections reached?): JVM_Bind


             3.37分50秒,tomcat拋出session無法save異常:

          2008-06-03 18:37:50 ERROR- IOException while saving persisted sessions: java.io.FileNotFoundException: "izzs"SESSIONS.ser (系統資源不足,無法完成請求的服務。)
          java.io.FileNotFoundException: "izzs"SESSIONS.ser (系統資源不足,無法完成請求的服務。)
              at java.io.FileOutputStream.open(Native Method)
              at java.io.FileOutputStream.
          <init>(FileOutputStream.java:179)
              at java.io.FileOutputStream.
          <init>(FileOutputStream.java:70)
              at org.apache.catalina.session.StandardManager.doUnload(StandardManager.java:
          511)
              at org.apache.catalina.session.StandardManager.unload(StandardManager.java:
          485)
              at org.apache.catalina.session.StandardManager.stop(StandardManager.java:
          687)
              at org.apache.catalina.core.StandardContext.stop(StandardContext.java:
          4496)
              at org.apache.catalina.core.StandardContext.reload(StandardContext.java:
          3037)
              at org.apache.catalina.core.StandardContext.backgroundProcess(StandardContext.java:
          4658)
              at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:
          1619)
              at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:
          1628)
              at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:
          1628)
              at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:
          1608)
              at java.lang.Thread.run(Thread.java:
          534)


           

          二.簡單分析

          崩潰原因:內存不足導致資源不足,引起Tomcat的session崩潰。
            這臺服務器上運行著很多應用,是什么原因引起內存不足還無法確定。
          初步判斷罪魁禍首可能是apache,該進程平常占用500MB內存,經常會飚到1G以上。

          Apache2的配置文件中:KeepAlive=On,MaxKeepAliveRequests=100,KeepAliveTimeout=15,分析aceess.log文件可以發現每個頁面觸發的request數量在10個以下,點擊率較低,可能使連接過多。
          我建議將keepAlive設為off,增加CPU負載,降低內存消耗。

          三.效果

           有待觀察......

          參考資料:
          http://www.withend.com/post/78.html

          四.結局 
          時隔一天,晚上九點再次崩潰,黑暗事件重演。
          這一次,我才得知原來該apache還配置有其他域名,于是調出該域名下的access.log。項目經理去了機房,在轟轟地風扇聲中打電話給我,讓我分析分析。
          仔細看訪問日志,發現原來有N多Connect 443連接,443是什么?是SSL端口!HTTPS!,Connect命令則顯然是代理功能!
          而且這些connect的IP來自全球各地,加拿大、美國、澳洲、新西蘭、北京、上海、英國、哪都有。
          看來這臺服務器是被人當代理服務器用了。
          怪不得半夜會死機,人家西半球那時正大白天撒歡兒呢。

          問題就出在apache的配置上,由于應用眾多,并且這臺服務器還是其他幾臺web服務器的對外出口,因此apache中配置了反向代理,不過不小心把正向代理(mod_proxy模塊的ProxyRequests指令)也打開了。
          看看apache2.0的官方文檔中mod_proxy部分,里面明明白白寫著:

          警告
          在您沒有對服務器采取安全措施之前,請不要用ProxyRequests啟用您的代理。一個開放的代理服務器不僅對您的網絡有威脅,對整個因特網來說也同樣如此。
          真的是很有威脅!大量代理請求急劇消耗內存,最終造成死機!

          解決辦法就是把正向代理關掉:ProxyRequests Off
          posted @ 2010-08-11 14:25 存鷹之心于高遠,取鷹之志而凌云,習鷹之性以涉險,融鷹之神在山巔. 閱讀(2036) | 評論 (0)編輯 收藏

          分布式緩存系統Memcached簡介與實踐

          http://blog.csdn.net/hitman9099/archive/2008/09/04/2878417.aspx

           

          緣起: 在數據驅動的web開發中,經常要重復從數據庫中取出相同的數據,這種重復極大的增加了數據庫負載。緩存是解決這個問題的好辦法。但是ASP.NET中的雖然已經可以實現對頁面局部進行緩存,但還是不夠靈活。此時Memcached或許是你想要的。

          Memcached是什么?
          Memcached是由Danga Interactive開發的,高性能的,分布式的內存對象緩存系統,用于在動態應用中減少數據庫負載,提升訪問速度。

          Memcached能緩存什么?
          通過在內存里維護一個統一的巨大的hash表,Memcached能夠用來存儲各種格式的數據,包括圖像、視頻、文件以及數據庫檢索的結果等。

          Memcached快么?

          非 常快。Memcached使用了libevent(如果可以的話,在linux下使用epoll)來均衡任何數量的打開鏈接,使用非阻塞的網絡I/O,對 內部對象實現引用計數(因此,針對多樣的客戶端,對象可以處在多樣的狀態), 使用自己的頁塊分配器和哈希表, 因此虛擬內存不會產生碎片并且虛擬內存分配的時間復雜度可以保證為O(1).。

          Danga Interactive為提升Danga Interactive的速度研發了Memcached。目前,LiveJournal.com每天已經在向一百萬用戶提供多達兩千萬次的頁面訪問。而這 些,是由一個由web服務器和數據庫服務器組成的集群完成的。Memcached幾乎完全放棄了任何數據都從數據庫讀取的方式,同時,它還縮短了用戶查看 頁面的速度、更好的資源分配方式,以及Memcache失效時對數據庫的訪問速度。

          Memcached的特點
          Memcached的緩存是一種分布式的,可以讓不同主機上的多個用戶同時訪問, 因此解決了共享內存只能單機應用的局限,更不會出現使用數據庫做類似事情的時候,磁盤開銷和阻塞的發生。

          Memcached的使用 
           
          Memcached服務器端的安裝 (此處將其作為系統服務安裝)
          下載文件:memcached 1.2.1 for Win32 binaries (Dec 23, 2006)
              1 解壓縮文件到c:\memcached
             2 命令行輸入 'c:\memcached\memcached.exe -d install' 
              3 命令行輸入 'c:\memcached\memcached.exe -d start' ,該命令啟動 Memcached ,默認監聽端口為 11211
          通過 memcached.exe -h 可以查看其幫助

           

          一個簡單的測試例子

          1. package com.mapbar.util.cache;

          2. import java.util.Date;
          3. import java.util.ResourceBundle;

          4. import com.danga.MemCached.MemCachedClient;
          5. import com.danga.MemCached.SockIOPool;
          6. /**
          7.  * 使用配置文件方式的memcache組件
          8.  *
          9.  */
          10. public class Cache {

          11.  protected static ResourceBundle rb=ResourceBundle.getBundle("memcached");;
          12.  public static MemCachedClient mcc = new MemCachedClient(); 
          13.  static {
          14.   init();
          15.  }     
          16.  public static void init(){
          17.   synchronized (mcc) {  
          18.    System.out.println("init call");
          19.    String[] servers =rb.getString("cache.servers").split(",");       
          20.          
          21.          String[] strWeights =rb.getString("cache.weights").split(",");  
          22.          Integer[] weights = new Integer[strWeights.length];
          23.          for(int i=0;i<strWeights.length;i++){
          24.           weights[i]=Integer.parseInt(strWeights[i]);
          25.          }
          26.         
          27.          //創建一個實例對象SockIOPool     
          28.          SockIOPool pool = SockIOPool.getInstance();       
          29.         
          30.          // set the servers and the weights    
          31.          //設置Memcached Server    
          32.          pool.setServers( servers );       
          33.          pool.setWeights( weights );       
          34.          pool.setInitConn(Integer.parseInt(rb.getString("cache.initConn")));       
          35.          pool.setMinConn(Integer.parseInt(rb.getString("cache.minConn")));       
          36.          pool.setMaxConn(Integer.parseInt(rb.getString("cache.maxConn")));       
          37.          pool.setMaxIdle(Long.parseLong(rb.getString("cache.maxIdle")));       
          38.         
          39.          // set the sleep for the maint thread       
          40.          // it will wake up every x seconds and       
          41.          // maintain the pool size       
          42.          pool.setMaintSleep( 30 );       
          43.         
          44. //         Tcp的規則就是在發送一個包之前,本地機器會等待遠程主機    
          45. //         對上一次發送的包的確認信息到來;這個方法就可以關閉套接字的緩存,    
          46. //         以至這個包準備好了就發;    
          47.          pool.setNagle( false );       
          48.          //連接建立后對超時的控制    
          49.          pool.setSocketTO( 3000 );    
          50.          //連接建立時對超時的控制    
          51.          pool.setSocketConnectTO( 0 );       
          52.         
          53.          // initialize the connection pool       
          54.          //初始化一些值并與MemcachedServer段建立連接    
          55.          pool.initialize();    

          56.          // lets set some compression on for the client       
          57.          // compress anything larger than 64k       
          58.          mcc.setCompressEnable( true );       
          59.          mcc.setCompressThreshold( 64 * 1024 );  
          60.   }
          61.  }
          62.  protected static void bulidCache(){  
          63.   
          64.         //set(key,value,Date) ,Date是一個過期時間,如果想讓這個過期時間生效的話,這里傳遞的new Date(long date) 中參數date,需要是個大于或等于1000的值。    
          65.         //因為java client的實現源碼里是這樣實現的 expiry.getTime() / 1000 ,也就是說,如果 小于1000的值,除以1000以后都是0,即永不過期    
          66.         mcc.set( "test""This is a test String" ,new Date(100000));   //十秒后過期    
          67.               
          68.     }       
          69.       
          70.  protected static void output() {       
          71.         //從cache里取值    
          72.         String value = (String) mcc.get( "test" );       
          73.         System.out.println(value);        
          74.     }       
          75.            
          76.  public static void main(String[] args){       
          77.         bulidCache();      
          78.         output();           
          79.     }        

          80. }


          其中在classespath下有個memcached.properties文件

          內容如下:

          ##muti servers spilt by ,

          #這里是你的memcached啟動的地址
          cache.servers=192.168.0.116:11211  
          cache.weights=1
          #memcached be used
          cache.cluster=true

          #set some basic pool settings       
          #5 initial, 5 min, and 250 max conns       
          #and set the max idle time for a conn       
          #to 6 hours  6*60*60*1000
          cache.initConn=5
          cache.minConn=5
          cache.maxConn=250
          cache.maxIdle=21600000

           

           

           

           

          在Windows下安裝Memcached

          http://www.oschina.net/docs/article/4

          很多phper不知道如何在Windows下搭建Memcache的開發調試環境,最近個人也在研究Memcache,記錄下自己安裝搭建的過程。
          其實我開始研究Memcache的時候并不知道居然還有memcached for Win32這個鳥東西,害得我在CnetOS下折騰1天才搞定,今天突然發現Windows下的Memcache進行開發調試完全沒有問題,所以寫篇 Memcache的文檔分享給大家。

          Windows下的Memcache安裝
          1. 下載memcache的 windows穩定版,解壓放某個盤下面,比如在c:\memcached
          2. 在終端(也即cmd命令界面)下輸入 ‘c:\memcached\memcached.exe -d install’ 安裝
          3. 再輸入: ‘c:\memcached\memcached.exe -d start’ 啟動。NOTE: 以后memcached將作為windows的一個服務每次開機時自動啟動。這樣服務器端已經安裝完畢了。
          4.下載php_memcache.dll, 請自己查找對應的php版本的文件
          5. 在C:\winnt\php.ini 加入一行 ‘extension=php_memcache.dll’
          6.重新啟動Apache,然后查看一下phpinfo,如果有memcache,那么就說明安裝成功!

          memcached的基本設置

          -p 監聽的端口
          -l 連接的IP地址, 默認是本機
          -d start 啟動memcached服務
          -d restart 重起memcached服務
          -d stop|shutdown 關閉正在運行的memcached服務
          -d install 安裝memcached服務
          -d uninstall 卸載memcached服務
          -u 以的身份運行 (僅在以root運行的時候有效)
          -m 最大內存使用,單位MB。默認64MB
          -M 內存耗盡時返回錯誤,而不是刪除項
          -c 最大同時連接數,默認是1024
          -f 塊大小增長因子,默認是1.25
          -n 最小分配空間,key+value+flags默認是48
          -h 顯示幫助

          Memcache環境測試
          運行下面的php文件,如果有輸出This is a test!,就表示環境搭建成功。開始領略Memcache的魅力把!
          < ?php
          $mem = new Memcache;
          $mem->connect(”127.0.0.1″, 11211);
          $mem->set(’key’, ‘This is a test!’, 0, 60);
          $val = $mem->get(’key’);
          echo $val;
          ?>

          posted @ 2010-08-11 14:22 存鷹之心于高遠,取鷹之志而凌云,習鷹之性以涉險,融鷹之神在山巔. 閱讀(466) | 評論 (0)編輯 收藏

          日志原文:http://j2ee.blog.sohu.com/70343632.html   
          memcache for win 軟件主頁:http://jehiah.cz/projects/memcached-win32/  
          http://labs.northscale.com/memcached-packages/
          meecache for liunx 軟件主頁:http://memcached.org/  
                                               
          最近一直在做一個項目的前期設計工作,考慮到后期系統的擴展和性能問題也找了很多解決方法,有一個就是用到了數據庫的緩存工具memcached(當然該工具并不僅僅局限于數據庫的緩存)。先簡單的介紹下什么是memcached。

              Memcached是高性能的,分布式的內存對象緩存系統,用于在動態應用中減少數據庫負 載,提升訪問速度。Memcached由Danga Interactive開發,用于提升LiveJournal.com訪問速度的。LJ每秒動態頁面訪問量幾千次,用戶700萬。Memcached將數 據庫負載大幅度降低,更好的分配資源,更快速訪問。

              上網baidu了很多東西,幾乎都差不多,而且基于java的說的很少,所有只有在研究了各個其他語言類的應用后再來嘗試在java上進行簡單的操作應 用。先從memcached上進行說明,memcached的最新版是采用c語言進行開發和設計的,據說舊版的是采用perl語言開發的,而且它是一個應 用軟件來的,是作為緩存服務器的服務器端運行在服務器上的,需要使用特定的語言編寫客戶端與其進行通信來進行數據的緩存和獲取。通常我們是把 memcached安裝運行在web服務器上,然后通過對需要的數據進行緩存,據我目前所知,所有數據的緩存設置和存取操作,以及數據的更新后替換操作全 部需要程序來進行,而不是自動進行的(自動不知道能不能成功,呵呵)。下面從一個實際的例子來應用memcached。

              首先到http://danga.com/memcached/下 載memcached的windows版本和java客戶端jar包,目前最新版本是memcached-1.2.1-win32.zip和 java_memcached-release_1.6.zip,分別解壓后即可!首先是安裝運行memcached服務器,我們將memcached- 1.2.1-win32.zip解壓后,進入其目錄,然后運行如下命令:

          c:>memcached.exe -d install
          c:>memcached.exe -l 127.0.0.1 -m 32 -d start

              第一行是安裝memcached成為服務,這樣才能正常運行,否則運行失敗!第一行是啟動memcached的,作為測試我們就簡單的只分配32M內存 了,然后監聽本機端口和以守護進行運行。執行完畢后,我們就可以在任務管理器中見到memcached.exe這個進程了。好了,我們的服務器已經正常運 行了, 下面我們就來寫java的客戶端連接程序。

              我們將java_memcached-release_1.6.zip解壓后的目錄中的java_memcached-release_1.6.jar文件復制到java項目的lib目錄下,然后我們來編寫代碼,比如我提供的一個應用類如下:

          package utils.cache;

          import java.util.Date;

          import com.danga.MemCached.MemCachedClient;
          import com.danga.MemCached.SockIOPool;


          /**
          * 使用memcached的緩存實用類.
          *
          *
          @author 鐵木箱子
          *
          */
          public class MemCached
          {
             
          // 創建全局的唯一實例
              protected static MemCachedClient mcc = new MemCachedClient();
             
             
          protected static MemCached memCached = new MemCached();
             
             
          // 設置與緩存服務器的連接池
              static {
                 
          // 服務器列表和其權重
                  String[] servers = {"127.0.0.1:11211"};
                  Integer[] weights
          = {3};

                 
          // 獲取socke連接池的實例對象
                  SockIOPool pool = SockIOPool.getInstance();

                 
          // 設置服務器信息
                  pool.setServers( servers );
                  pool.setWeights( weights );

                 
          // 設置初始連接數、最小和最大連接數以及最大處理時間
                  pool.setInitConn( 5 );
                  pool.setMinConn(
          5 );
                  pool.setMaxConn(
          250 );
                  pool.setMaxIdle(
          1000 * 60 * 60 * 6 );

                 
          // 設置主線程的睡眠時間
                  pool.setMaintSleep( 30 );

                 
          // 設置TCP的參數,連接超時等
                  pool.setNagle( false );
                  pool.setSocketTO(
          3000 );
                  pool.setSocketConnectTO(
          0 );

                 
          // 初始化連接池
                  pool.initialize();

                 
          // 壓縮設置,超過指定大小(單位為K)的數據都會被壓縮
                  mcc.setCompressEnable( true );
                  mcc.setCompressThreshold(
          64 * 1024 );
              }
             
             
          /**
               * 保護型構造方法,不允許實例化!
               *
              
          */
             
          protected MemCached()
              {
                 
              }
             
             
          /**
               * 獲取唯一實例.
               *
          @return
              
          */
             
          public static MemCached getInstance()
              {
                 
          return memCached;
              }
             
             
          /**
               * 添加一個指定的值到緩存中.
               *
          @param key
               *
          @param value
               *
          @return
              
          */
             
          public boolean add(String key, Object value)
              {
                 
          return mcc.add(key, value);
              }
             
             
          public boolean add(String key, Object value, Date expiry)
              {
                 
          return mcc.add(key, value, expiry);
              }
             
             
          public boolean replace(String key, Object value)
              {
                 
          return mcc.replace(key, value);
              }
             
             
          public boolean replace(String key, Object value, Date expiry)
              {
                 
          return mcc.replace(key, value, expiry);
              }
             
             
          /**
               * 根據指定的關鍵字獲取對象.
               *
          @param key
               *
          @return
              
          */
             
          public Object get(String key)
              {
                 
          return mcc.get(key);
              }
             
             
          public static void main(String[] args)
              {
                  MemCached cache
          = MemCached.getInstance();
                  cache.add(
          "hello", 234);
                  System.out.print(
          "get value : " + cache.get("hello"));
              }
          }

              那么我們就可以通過簡單的像main方法中操作的一樣存入一個變量,然后再取出進行查看,我們可以看到先調用了add,然后再進行get,我們運行一次 后,234這個值已經被我們存入了memcached的緩存中的了,我們將main方法中紅色的那一行注釋掉后,我們再運行還是可以看到get到的 value也是234,即緩存中我們已經存在了數據了。

              對基本的數據我們可以操作,對于普通的POJO而言,如果要進行存儲的話,那么比如讓其實現java.io.Serializable接口,因為 memcached是一個分布式的緩存服務器,多臺服務器間進行數據共享需要將對象序列化的,所以必須實現該接口,否則會報錯的。比如我們寫一個簡單的測 試Bean如下:

          class TBean implements java.io.Serializable
          {
             
          private static final long serialVersionUID = 1945562032261336919L;
             
             
          private String name;

             
          public String getName()
              {
                 
          return name;
              }

             
          public void setName(String name)
              {
                 
          this.name = name;
              }
          }

              然后我們在main方法中加入如下幾行代碼:

          TBean tb = new TBean();
          tb.setName(
          "鐵木箱子");
          cache.add(
          "bean", tb);
          TBean tb1
          = (TBean)cache.get("bean");
          System.out.print(
          "name=" + tb1.getName());
          tb1.setName(
          "鐵木箱子_修改的");
          tb1
          = (TBean)cache.get("bean");
          System.out.print(
          "name=" + tb1.getName());

              我們首先把TBean的一個實例放入緩存中,然后再取出來,并進行名稱的修改,然后我們再取這個對象,我們再看其名稱,發現修改的對象并不是緩存中的對 象,而是通過序列化過來的一個實例對象,這樣我們就無須擔心對原生類的無意修改導致緩存數據失效了,呵呵~~看來我也是多此一想啊。所以這表明從緩存中獲 取的對象是存入對象的一個副本,對獲取對象的修改并不能真正的修改緩存中的數據,而應該使用其提供的replace等方法來進行修改。

              以上是我在windows下對memcached的一點小學習和實踐,在以后的項目開發過程中將會更深入的學習和應用這一緩存工具,也希望和有興趣的同行一起討論學習該工具的使用~~ 微笑


          posted @ 2010-08-11 13:51 存鷹之心于高遠,取鷹之志而凌云,習鷹之性以涉險,融鷹之神在山巔. 閱讀(769) | 評論 (0)編輯 收藏

          轉載:http://www.aygfsteel.com/cnfree/archive/2008/06/12/207343.html

          最近的項目需要使用報表,因為是RCP應用,所以選擇了Birt,用了一下,感覺還可以,就是網上資料少了點,不過以前也研究過一些Eclipse相關技術,這些都不重要了,找了SDK版本Debug,啥研究不出來?

          BIRT是一個Eclipse-based開放源代碼報表系統。它主要是用在基于Java與J2EE的Web應用程序上。BIRT主要由兩部分組成:一個是基于Eclipse的報表設計和一個可以加到你應用服務的運行期組件。BIRT同時也提供一個圖形報表制作引擎。

          官方主頁:http://www.eclipse.org/birt
          官方BBS支持:http://www.actuatechina.com/forum2.html

          基本上來說Birt功能還是很強大的,支持時下比較流行的WebService,Ajax技術,既可用于Web,也可以用于桌面,更新也算穩定,基本上遵循Eclipse的開發步驟,一個一個大版本,同時支持腳本調用,debug開發等等。唯一不足的就是中國的國情支持得還不夠完善,畢竟中國比較特殊,我以前給公司做黨務報表,要按照紙質報表畫,一分一毫都不能變差,那個變態呀,在電腦上畫報表還是拿尺子量。

          剛剛開始用,慢慢研究,看了下Birt自帶的Example,的確是很強大,做得也很漂亮,自己試著創建一個報表也很簡單,希望能夠比較快的上手吧。

          在網上找了一些資源:
          http://blogger.org.cn/blog/more.asp?name=sixsun&id=13933 BIRT 中文指南
          http://www.springside.org.cn/docs/reference/Birt.htm BIRT報表
          http://www-128.ibm.com/developerworks/cn/opensource/os-ecl-birt/ Birt的IBM DW的中文教程
          http://download.eclipse.org/birt/downloads/demos/FirstReport/MyFirstReport.html Birt Flash Demo.
          posted @ 2009-02-02 09:31 存鷹之心于高遠,取鷹之志而凌云,習鷹之性以涉險,融鷹之神在山巔. 閱讀(378) | 評論 (0)編輯 收藏

          主站蜘蛛池模板: 浑源县| 文成县| 正镶白旗| 阳朔县| 嘉禾县| 和平县| 响水县| 辰溪县| 紫阳县| 虎林市| 五常市| 拜泉县| 诸暨市| 大丰市| 邢台市| 福海县| 大方县| 孟津县| 资中县| 随州市| 乐平市| 抚顺县| 宁安市| 巴马| 濮阳县| 屏东市| 独山县| 元氏县| 马尔康县| 松溪县| 白玉县| 葵青区| 金寨县| 峨眉山市| 霍州市| 扬州市| 寻乌县| 嘉祥县| 揭阳市| 南宁市| 宜黄县|