Java版線程池實(shí)現(xiàn)_第1頁
Java版線程池實(shí)現(xiàn)_第2頁
Java版線程池實(shí)現(xiàn)_第3頁
Java版線程池實(shí)現(xiàn)_第4頁
Java版線程池實(shí)現(xiàn)_第5頁
已閱讀5頁,還剩37頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、Java版線程池實(shí)現(xiàn)線程池調(diào)度技術(shù)原理:package test.threadpool;import java.util.*;import test.cfg.*;public class ThreadPool private int reserve = 0; /保留線程 private int minPools = 10; /最小連接池?cái)?shù)目,預(yù)啟動(dòng)線程數(shù)目 private int maxActive = 70; /最多活動(dòng)線程數(shù)目 private int maxPools = 100; /最大連接池?cái)?shù)目 private int checkThreadPeriod = 5; /檢查連接池的周期

2、ArrayList m_ThreadList; /工作線程列表 ArrayList m_ReserveList; /保留線程鏈表 LinkedList m_RunList = null; /工作任務(wù)列表 int freeThreadCount = 0;/未被使用的線程數(shù)目 private java.util.Timer timer = null;/定時(shí)器 static Object o = new Object(); public void setMinPools(int minPools) this.minPools = minPools; public void setMaxPools(i

3、nt maxPools) this.maxPools = maxPools; public void setCheckThreadPeriod(int checkThreadPeriod) this.checkThreadPeriod = checkThreadPeriod; /* * 初始化線程池,由于各個(gè)線程啟動(dòng)的時(shí)候是有一定的時(shí)間間隔,啟動(dòng)的時(shí)候會(huì)有一定的時(shí)間 * */ public ThreadPool() / reserve = Integer.parseInt(FtpConfig.getValue(reserve); /從配置文件中獲取參數(shù) / minPools = Integer

4、.parseInt(FtpConfig.getValue(minPools); /從配置文件中獲取參數(shù) /maxActive = Integer.parseInt(FtpConfig.getValue(maxActive);/從配置文件中獲取參數(shù) /maxPools = Integer.parseInt(FtpConfig.getValue(maxPools); /從配置文件中獲取參數(shù) /checkThreadPeriod = Integer.parseInt(FtpConfig / .getValue(monitorPeriod) * 60 * 1000; /以分為輪詢單位 m_Thread

5、List = new ArrayList(); /初始化工作線程鏈表 m_ReserveList = new ArrayList(); m_RunList = new LinkedList(); /初始化任務(wù)列表 ArrayList list = null; if (reserve 0) list = (ArrayList) FtpConfig.getProValueList(reserveList; for (int i = 0; i reserve; i+) /啟動(dòng)保留線程,根據(jù)配置鏈表中的線程列表啟動(dòng)對(duì)應(yīng)的保留線程.保存的是線程的全路徑 /class name try Thread th

6、r = (Thread) Class.forName(String) list.get(i) .newInstance(); m_ReserveList.add(i, thr); thr.start(); Thread.sleep(10); catch (Exception e) e.printStackTrace(); for (int i = 0; i minPools; i+) /初始化空閑線程 WorkerThread temp = new WorkerThread(); m_ThreadList.add(temp); /將線程添加到線程鏈表中 temp.start(); /啟動(dòng)工作線

7、程 try Thread.sleep(10); /每個(gè)100us啟動(dòng)一個(gè)線程 catch (Exception e) printDebugInfo(); timer = new Timer(true);/啟動(dòng)定時(shí)器 timer.schedule(new CheckThreadTask(this), 0, checkThreadPeriod); /設(shè)置定時(shí)器調(diào)度線程池 /* * 應(yīng)用程序調(diào)用入口,可以是一個(gè)封裝好的job類,具體視應(yīng)用而定 * param work */ public synchronized void run(Object work) synchronized (m_RunLi

8、st) /添加任務(wù)到任務(wù)鏈表中 m_RunList.add(work); m_RunList.notify(); /* * monitor 所要采取的動(dòng)作(輪詢) * */ public synchronized void checkAllThreads() /printDebugInfo(); /如果空閑線程數(shù)少于預(yù)啟動(dòng)線程數(shù)目,并且沒有達(dá)到最大的活動(dòng)線程數(shù)時(shí)則增加空閑線程 if(freeThreadCountminPools&m_ThreadList.size()(maxActive-m_ThreadList.size()?(maxActive-m_ThreadList.size()min

9、Pools-freeThreadCount); for(int i=0;iminPools & (m_ThreadList.size()maxActive) ) int count=(freeThreadCount-minPools)(m_ThreadList.size()-maxActive)?(freeThreadCount-minPools)freeThreadCount-minPools); for(int i=m_ThreadList.size()-1;i=0&count0;i-,count-) WorkerThread thr=(WorkerThread)m_ThreadList.

10、get(i); if(thr!=null & thr.isdo) continue; if(thr!=null) synchronized(o) m_ThreadList.remove(i); try thr.stop(); /銷毀線程 catch(Exception e) e.printStackTrace(); freeThreadCount-; for(int i=0;i=0;i-) Thread thr=(Thread)m_ReserveList.get(i); if(thr!=null & !(thr.isAlive() /m_ReserveList.remove(i); try /

11、thr.destroy();/銷毀原先的線程 thr.stop(); thr = (Thread) Class.forName(String) FtpConfig.getProValueList(reserveList.get(i).newInstance(); m_ReserveList.remove(i);/去除原先的對(duì)象 m_ReserveList.set(i,thr); thr.start(); catch(Exception e) e.printStackTrace(); /* * 打印調(diào)試信息 * */ public void printDebugInfo() System.out

12、.println(m_ThreadList.size()= + m_ThreadList.size(); System.out.println(freeThreadCount + freeThreadCount); /* * 獲取任務(wù)鏈表 * * return */ public LinkedList getRunList() return m_RunList; /* * 增加空閑線程數(shù)目 * */ public void addFreeThreadCount() synchronized (o) freeThreadCount+; /* * 減少空閑線程數(shù)目 * */ public void

13、 delFreeThreadCount() synchronized (o) freeThreadCount-; class WorkerThread extends Thread boolean running = true; boolean isdo=false; String work; public WorkerThread() setDaemon(false); /設(shè)置線程為精靈線程 /* * 設(shè)置線程的運(yùn)行狀態(tài) * * param state */ public synchronized void setRunState(boolean state) this.running =

14、state; /* * 獲取線程運(yùn)行狀態(tài) * return */ public synchronized boolean getIsdo() return isdo; public void run() while (running) synchronized (o) freeThreadCount+; synchronized (m_RunList) while (m_RunList.size() = 0) try m_RunList.wait(); if (!running) return; catch (InterruptedException e) /* do what you wan

15、t to do */ synchronized (o) /空閑線程減少 freeThreadCount-; isdo=true; /*這里傳進(jìn)來的東西可以是一個(gè)socket句柄,用于數(shù)據(jù)的交換或者是一個(gè)其他的對(duì)象,具體業(yè)務(wù)而定*/ / System.out.println(m_RunList.getFirst() + getName(); BaseCtl ctl=(BaseCtl)m_RunList.getFirst(); ctl.doIt(); m_RunList.removeFirst(); isdo=false; public static void main(String args)

16、ThreadPool pool = new ThreadPool(); BaseCtl ctl=new LogonCtl(); pool.run(ctl);package test.threadpool;import java.util.TimerTask;/* author Administrator* version 1.0.0*/public class CheckThreadTask extends TimerTask Object obj=null; public CheckThreadTask(Object obj) this.obj=obj; public void run()

17、(ThreadPool)obj).checkAllThreads(); package test.threadpool;/* author Administrator* version 1.0.0*/public abstract class BaseCtl /當(dāng)然通過這種方式你也可以把socket等句柄傳到你的子類中來處理網(wǎng)絡(luò)應(yīng)用public abstract void doIt();package test.threadpool;/* author Administrator* version 1.0.0*/public class LogonCtl extends BaseCtl pub

18、lic void doIt() System.out.println(hello world; Java版線程池實(shí)現(xiàn)線程池調(diào)度技術(shù)原理:package test.threadpool;import java.util.*;import test.cfg.*;public class ThreadPool private int reserve = 0; /保留線程 private int minPools = 10; /最小連接池?cái)?shù)目,預(yù)啟動(dòng)線程數(shù)目 private int maxActive = 70; /最多活動(dòng)線程數(shù)目 private int maxPools = 100; /最大連接池

19、數(shù)目 private int checkThreadPeriod = 5; /檢查連接池的周期 ArrayList m_ThreadList; /工作線程列表 ArrayList m_ReserveList; /保留線程鏈表 LinkedList m_RunList = null; /工作任務(wù)列表 int freeThreadCount = 0;/未被使用的線程數(shù)目 private java.util.Timer timer = null;/定時(shí)器 static Object o = new Object(); public void setMinPools(int minPools) thi

20、s.minPools = minPools; public void setMaxPools(int maxPools) this.maxPools = maxPools; public void setCheckThreadPeriod(int checkThreadPeriod) this.checkThreadPeriod = checkThreadPeriod; /* * 初始化線程池,由于各個(gè)線程啟動(dòng)的時(shí)候是有一定的時(shí)間間隔,啟動(dòng)的時(shí)候會(huì)有一定的時(shí)間 * */ public ThreadPool() / reserve = Integer.parseInt(FtpConfig.get

21、Value(reserve); /從配置文件中獲取參數(shù) / minPools = Integer.parseInt(FtpConfig.getValue(minPools); /從配置文件中獲取參數(shù) /maxActive = Integer.parseInt(FtpConfig.getValue(maxActive);/從配置文件中獲取參數(shù) /maxPools = Integer.parseInt(FtpConfig.getValue(maxPools); /從配置文件中獲取參數(shù) /checkThreadPeriod = Integer.parseInt(FtpConfig / .getVal

22、ue(monitorPeriod) * 60 * 1000; /以分為輪詢單位 m_ThreadList = new ArrayList(); /初始化工作線程鏈表 m_ReserveList = new ArrayList(); m_RunList = new LinkedList(); /初始化任務(wù)列表 ArrayList list = null; if (reserve 0) list = (ArrayList) FtpConfig.getProValueList(reserveList; for (int i = 0; i reserve; i+) /啟動(dòng)保留線程,根據(jù)配置鏈表中的線程

23、列表啟動(dòng)對(duì)應(yīng)的保留線程.保存的是線程的全路徑 /class name try Thread thr = (Thread) Class.forName(String) list.get(i) .newInstance(); m_ReserveList.add(i, thr); thr.start(); Thread.sleep(10); catch (Exception e) e.printStackTrace(); for (int i = 0; i minPools; i+) /初始化空閑線程 WorkerThread temp = new WorkerThread(); m_ThreadL

24、ist.add(temp); /將線程添加到線程鏈表中 temp.start(); /啟動(dòng)工作線程 try Thread.sleep(10); /每個(gè)100us啟動(dòng)一個(gè)線程 catch (Exception e) printDebugInfo(); timer = new Timer(true);/啟動(dòng)定時(shí)器 timer.schedule(new CheckThreadTask(this), 0, checkThreadPeriod); /設(shè)置定時(shí)器調(diào)度線程池 /* * 應(yīng)用程序調(diào)用入口,可以是一個(gè)封裝好的job類,具體視應(yīng)用而定 * param work */ public synchron

25、ized void run(Object work) synchronized (m_RunList) /添加任務(wù)到任務(wù)鏈表中 m_RunList.add(work); m_RunList.notify(); /* * monitor 所要采取的動(dòng)作(輪詢) * */ public synchronized void checkAllThreads() /printDebugInfo(); /如果空閑線程數(shù)少于預(yù)啟動(dòng)線程數(shù)目,并且沒有達(dá)到最大的活動(dòng)線程數(shù)時(shí)則增加空閑線程 if(freeThreadCountminPools&m_ThreadList.size()(maxActive-m_Thr

26、eadList.size()?(maxActive-m_ThreadList.size()minPools-freeThreadCount); for(int i=0;iminPools & (m_ThreadList.size()maxActive) ) int count=(freeThreadCount-minPools)(m_ThreadList.size()-maxActive)?(freeThreadCount-minPools)freeThreadCount-minPools); for(int i=m_ThreadList.size()-1;i=0&count0;i-,coun

27、t-) WorkerThread thr=(WorkerThread)m_ThreadList.get(i); if(thr!=null & thr.isdo) continue; if(thr!=null) synchronized(o) m_ThreadList.remove(i); try thr.stop(); /銷毀線程 catch(Exception e) e.printStackTrace(); freeThreadCount-; for(int i=0;i=0;i-) Thread thr=(Thread)m_ReserveList.get(i); if(thr!=null &

28、 !(thr.isAlive() /m_ReserveList.remove(i); try /thr.destroy();/銷毀原先的線程 thr.stop(); thr = (Thread) Class.forName(String) FtpConfig.getProValueList(reserveList.get(i).newInstance(); m_ReserveList.remove(i);/去除原先的對(duì)象 m_ReserveList.set(i,thr); thr.start(); catch(Exception e) e.printStackTrace(); /* * 打印調(diào)

29、試信息 * */ public void printDebugInfo() System.out.println(m_ThreadList.size()= + m_ThreadList.size(); System.out.println(freeThreadCount + freeThreadCount); /* * 獲取任務(wù)鏈表 * * return */ public LinkedList getRunList() return m_RunList; /* * 增加空閑線程數(shù)目 * */ public void addFreeThreadCount() synchronized (o)

30、freeThreadCount+; /* * 減少空閑線程數(shù)目 * */ public void delFreeThreadCount() synchronized (o) freeThreadCount-; class WorkerThread extends Thread boolean running = true; boolean isdo=false; String work; public WorkerThread() setDaemon(false); /設(shè)置線程為精靈線程 /* * 設(shè)置線程的運(yùn)行狀態(tài) * * param state */ public synchronized

31、 void setRunState(boolean state) this.running = state; /* * 獲取線程運(yùn)行狀態(tài) * return */ public synchronized boolean getIsdo() return isdo; public void run() while (running) synchronized (o) freeThreadCount+; synchronized (m_RunList) while (m_RunList.size() = 0) try m_RunList.wait(); if (!running) return; c

32、atch (InterruptedException e) /* do what you want to do */ synchronized (o) /空閑線程減少 freeThreadCount-; isdo=true; /*這里傳進(jìn)來的東西可以是一個(gè)socket句柄,用于數(shù)據(jù)的交換或者是一個(gè)其他的對(duì)象,具體業(yè)務(wù)而定*/ / System.out.println(m_RunList.getFirst() + getName(); BaseCtl ctl=(BaseCtl)m_RunList.getFirst(); ctl.doIt(); m_RunList.removeFirst(); i

33、sdo=false; public static void main(String args) ThreadPool pool = new ThreadPool(); BaseCtl ctl=new LogonCtl(); pool.run(ctl); package test.threadpool;import java.util.TimerTask;/* author Administrator* version 1.0.0*/public class CheckThreadTask extends TimerTask Object obj=null; public CheckThread

34、Task(Object obj) this.obj=obj; public void run() (ThreadPool)obj).checkAllThreads(); package test.threadpool;/* author Administrator* version 1.0.0*/public abstract class BaseCtl /當(dāng)然通過這種方式你也可以把socket等句柄傳到你的子類中來處理網(wǎng)絡(luò)應(yīng)用public abstract void doIt();package test.threadpool;/* author Administrator* version

35、 1.0.0*/public class LogonCtl extends BaseCtl public void doIt() System.out.println(hello world; 附錄資料:java處理高并發(fā)高負(fù)載類網(wǎng)站的優(yōu)化方法java處理高并發(fā)高負(fù)載類網(wǎng)站中數(shù)據(jù)庫的設(shè)計(jì)方法(java教程,java處理大量數(shù)據(jù),java高負(fù)載數(shù)據(jù))一:高并發(fā)高負(fù)載類網(wǎng)站關(guān)注點(diǎn)之?dāng)?shù)據(jù)庫沒錯(cuò),首先是數(shù)據(jù)庫,這是大多數(shù)應(yīng)用所面臨的首個(gè)SPOF。尤其是Web2.0的應(yīng)用,數(shù)據(jù)庫的響應(yīng)是首先要解決的。一般來說MySQL是最常用的,可能最初是一個(gè)mysql主機(jī),當(dāng)數(shù)據(jù)增加到100萬以上,那么,MySQL的

36、效能急劇下降。常用的優(yōu)化措施是M-S(主-從)方式進(jìn)行同步復(fù)制,將查詢和操作和分別在不同的服務(wù)器上進(jìn)行操作。我推薦的是M-M-Slaves方式,2個(gè)主Mysql,多個(gè)Slaves,需要注意的是,雖然有2個(gè)Master,但是同時(shí)只有1個(gè)是Active,我們可以在一定時(shí)候切換。之所以用2個(gè)M,是保證M不會(huì)又成為系統(tǒng)的SPOF。Slaves可以進(jìn)一步負(fù)載均衡,可以結(jié)合LVS,從而將select操作適當(dāng)?shù)钠胶獾讲煌膕laves上。以上架構(gòu)可以抗衡到一定量的負(fù)載,但是隨著用戶進(jìn)一步增加,你的用戶表數(shù)據(jù)超過1千萬,這時(shí)那個(gè)M變成了SPOF。你不能任意擴(kuò)充Slaves,否則復(fù)制同步的開銷將直線上升,怎么辦

37、?我的方法是表分區(qū),從業(yè)務(wù)層面上進(jìn)行分區(qū)。最簡(jiǎn)單的,以用戶數(shù)據(jù)為例。根據(jù)一定的切分方式,比如id,切分到不同的數(shù)據(jù)庫集群去。全局?jǐn)?shù)據(jù)庫用于meta數(shù)據(jù)的查詢。缺點(diǎn)是每次查詢,會(huì)增加一次,比如你要查一個(gè)用戶nightsailer,你首先要到全局?jǐn)?shù)據(jù)庫群找到nightsailer對(duì)應(yīng)的cluster id,然后再到指定的cluster找到nightsailer的實(shí)際數(shù)據(jù)。每個(gè)cluster可以用m-m方式,或者m-m-slaves方式。這是一個(gè)可以擴(kuò)展的結(jié)構(gòu),隨著負(fù)載的增加,你可以簡(jiǎn)單的增加新的mysql cluster進(jìn)去。需要注意的是:1、禁用全部auto_increment的字段2、id需要

38、采用通用的算法集中分配3、要具有比較好的方法來監(jiān)控mysql主機(jī)的負(fù)載和服務(wù)的運(yùn)行狀態(tài)。如果你有30臺(tái)以上的mysql數(shù)據(jù)庫在跑就明白我的意思了。4、不要使用持久性鏈接(不要用pconnect),相反,使用sqlrelay這種第三方的數(shù)據(jù)庫鏈接池,或者干脆自己做,因?yàn)閜hp4中mysql的鏈接池經(jīng)常出問題。二:高并發(fā)高負(fù)載網(wǎng)站的系統(tǒng)架構(gòu)之HTML靜態(tài)化其實(shí)大家都知道,效率最高、消耗最小的就是純靜態(tài)化,所以我們盡可能使我們的網(wǎng)站上的頁面采用靜態(tài)頁面來實(shí)現(xiàn),這個(gè)最簡(jiǎn)單的方法其實(shí)也是 最有效的方法。但是對(duì)于大量?jī)?nèi)容并且頻繁更新的網(wǎng)站,我們無法全部手動(dòng)去挨個(gè)實(shí)現(xiàn),于是出現(xiàn)了我們常見的信息發(fā)布系統(tǒng)CMS

39、,像我們常訪問的各個(gè)門戶站點(diǎn) 的新聞?lì)l道,甚至他們的其他頻道,都是通過信息發(fā)布系統(tǒng)來管理和實(shí)現(xiàn)的,信息發(fā)布系統(tǒng)可以實(shí)現(xiàn)最簡(jiǎn)單的信息錄入自動(dòng)生成靜態(tài)頁面,還能具備頻道管理、權(quán)限 管理、自動(dòng)抓取等功能,對(duì)于一個(gè)大型網(wǎng)站來說,擁有一套高效、可管理的CMS是必不可少的。除了門戶和信息發(fā)布類型的網(wǎng)站,對(duì)于交互性要求很高的社區(qū)類型網(wǎng)站來說,盡可能的靜態(tài)化也是提高性能的必要手段,將社區(qū)內(nèi)的帖子、文章進(jìn)行實(shí)時(shí)的靜態(tài)化,有更新的時(shí)候再重新靜態(tài)化也是大量使用的策略,像Mop的大雜燴就是使用了這樣的策略,網(wǎng)易社區(qū)等也是如此。 同時(shí),html靜態(tài)化也是某些緩存策略使用的手段,對(duì)于系統(tǒng)中頻繁使用數(shù)據(jù)庫查詢但是內(nèi)容更新很

40、小的應(yīng)用,可以考慮使用html靜態(tài)化來實(shí)現(xiàn),比如論壇 中論壇的公用設(shè)置信息,這些信息目前的主流論壇都可以進(jìn)行后臺(tái)管理并且存儲(chǔ)再數(shù)據(jù)庫中,這些信息其實(shí)大量被前臺(tái)程序調(diào)用,但是更新頻率很小,可以考慮將這 部分內(nèi)容進(jìn)行后臺(tái)更新的時(shí)候進(jìn)行靜態(tài)化,這樣避免了大量的數(shù)據(jù)庫訪問請(qǐng)求高并發(fā)。網(wǎng)站HTML靜態(tài)化解決方案當(dāng)一個(gè)Servlet資源請(qǐng)求到達(dá)WEB服務(wù)器之后我們會(huì)填充指定的JSP頁面來響應(yīng)請(qǐng)求:HTTP請(qǐng)求Web服務(wù)器Servlet-業(yè)務(wù)邏輯處理-訪問數(shù)據(jù)-填充JSP-響應(yīng)請(qǐng)求HTML靜態(tài)化之后:HTTP請(qǐng)求Web服務(wù)器Servlet-HTML-響應(yīng)請(qǐng)求靜態(tài)訪求如下Servlet:public void

41、 doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException if(request.getParameter(chapterId) != null) String chapterFileName = bookChapterRead_+request.getParameter(chapterId)+.html; String chapterFilePath = getServletContext().getRealPath(/) + chapterFile

42、Name; File chapterFile = new File(chapterFilePath); if(chapterFile.exists()response.sendRedirect(chapterFileName);return;/如果有這個(gè)文件就告訴瀏覽器轉(zhuǎn)向 INovelChapterBiz novelChapterBiz = new NovelChapterBizImpl(); NovelChapter novelChapter = novelChapterBiz.searchNovelChapterById(Integer.parseInt(request.getParam

43、eter(chapterId);/章節(jié)信息 int lastPageId = novelChapterBiz.searchLastCHapterId(novelChapter.getNovelId().getId(), novelChapter.getId(); int nextPageId = novelChapterBiz.searchNextChapterId(novelChapter.getNovelId().getId(), novelChapter.getId(); request.setAttribute(novelChapter, novelChapter); request.

44、setAttribute(lastPageId, lastPageId); request.setAttribute(nextPageId, nextPageId); new CreateStaticHTMLPage().createStaticHTMLPage(request, response, getServletContext(), chapterFileName, chapterFilePath, /bookRead.jsp); 生成HTML靜態(tài)頁面的類:package com.jb.y2t034.thefifth.web.servlet;import java.io.ByteArr

45、ayOutputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.OutputStreamWriter;import java.io.PrintWriter;import javax.servlet.RequestDispatcher;import javax.servlet.ServletContext;import javax.servlet.ServletException;import javax.servlet.ServletOutputStream;import java

46、x.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpServletResponseWrapper;/* 創(chuàng)建HTML靜態(tài)頁面* 功能:創(chuàng)建HTML靜態(tài)頁面* 時(shí)間:2009年1011日* 地點(diǎn):home* author mavk*/public class CreateStaticHTMLPage /* * 生成靜態(tài)HTML頁面的方法 * param request 請(qǐng)求對(duì)象 * param response 響應(yīng)對(duì)象 * pa

47、ram servletContext Servlet上下文 * param fileName 文件名稱 * param fileFullPath 文件完整路徑 * param jspPath 需要生成靜態(tài)文件的JSP路徑(相對(duì)即可) * throws IOException * throws ServletException */ public void createStaticHTMLPage(HttpServletRequest request, HttpServletResponse response,ServletContext servletContext,String fileNa

48、me,String fileFullPath,String jspPath) throws ServletException, IOException response.setContentType(text/html;charset=gb2312);/設(shè)置HTML結(jié)果流編碼(即HTML文件編碼) RequestDispatcher rd = servletContext.getRequestDispatcher(jspPath);/得到JSP資源 final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputSt

49、ream();/用于從ServletOutputStream中接收資源 final ServletOutputStream servletOuputStream = new ServletOutputStream()/用于從HttpServletResponse中接收資源 public void write(byte b, int off,int len) byteArrayOutputStream.write(b, off, len); public void write(int b) byteArrayOutputStream.write(b); ; final PrintWriter p

50、rintWriter = new PrintWriter(new OutputStreamWriter(byteArrayOutputStream);/把轉(zhuǎn)換字節(jié)流轉(zhuǎn)換成字符流 HttpServletResponse httpServletResponse = new HttpServletResponseWrapper(response)/用于從response獲取結(jié)果流資源(重寫了兩個(gè)方法) public ServletOutputStream getOutputStream() return servletOuputStream; public PrintWriter getWriter

51、() return printWriter; ; rd.include(request, httpServletResponse);/發(fā)送結(jié)果流 printWriter.flush();/刷新緩沖區(qū),把緩沖區(qū)的數(shù)據(jù)輸出 FileOutputStream fileOutputStream = new FileOutputStream(fileFullPath); byteArrayOutputStream.writeTo(fileOutputStream);/把byteArrayOuputStream中的資源全部寫入到fileOuputStream中 fileOutputStream.close

52、();/關(guān)閉輸出流,并釋放相關(guān)資源 response.sendRedirect(fileName);/發(fā)送指定文件流到客戶端 三:高并發(fā)高負(fù)載類網(wǎng)站關(guān)注點(diǎn)之緩存、負(fù)載均衡、存儲(chǔ)緩存是另一個(gè)大問題,我一般用memcached來做緩存集群,一般來說部署10臺(tái)左右就差不多(10g內(nèi)存池)。需要注意一點(diǎn),千萬不能用使用swap,最好關(guān)閉linux的swap。負(fù)載均衡/加速可能上面說緩存的時(shí)候,有人第一想的是頁面靜態(tài)化,所謂的靜態(tài)html,我認(rèn)為這是常識(shí),不屬于要點(diǎn)了。頁面的靜態(tài)化隨之帶來的是靜態(tài)服務(wù)的負(fù)載均衡和加速。我認(rèn)為L(zhǎng)ighttped+Squid是最好的方式了。LVS lighttped=squ

53、id(s) =lighttpd上面是我經(jīng)常用的。注意,我沒有用apache,除非特定的需求,否則我不部署apache,因?yàn)槲乙话阌胮hp-fastcgi配合lighttpd,性能比apache+mod_php要強(qiáng)很多。squid的使用可以解決文件的同步等等問題,但是需要注意,你要很好的監(jiān)控緩存的命中率,盡可能的提高的90%以上。squid和lighttped也有很多的話題要討論,這里不贅述。存儲(chǔ)存儲(chǔ)也是一個(gè)大問題,一種是小文件的存儲(chǔ),比如圖片這類。另一種是大文件的存儲(chǔ),比如搜索引擎的索引,一般單文件都超過2g以上。小文件的存儲(chǔ)最簡(jiǎn)單的方法是結(jié)合lighttpd來進(jìn)行分布?;蛘吒纱嗍褂肦edha

54、t的GFS,優(yōu)點(diǎn)是應(yīng)用透明,缺點(diǎn)是費(fèi)用較高。我是指你購買盤陣的問題。我的項(xiàng)目中,存儲(chǔ)量是2-10Tb,我采用了分布式存儲(chǔ)。這里要解決文件的復(fù)制和冗余。這樣每個(gè)文件有不同的冗余,這方面可以參考google的gfs的論文。大文件的存儲(chǔ),可以參考nutch的方案,現(xiàn)在已經(jīng)獨(dú)立為hadoop子項(xiàng)目。(你可以google it)其他:此外,passport等也是考慮的,不過都屬于比較簡(jiǎn)單的了。四:高并發(fā)高負(fù)載網(wǎng)站的系統(tǒng)架構(gòu)之圖片服務(wù)器分離大家知道,對(duì)于Web 服務(wù)器來說,不管是Apache、IIS還是其他容器,圖片是最消耗資源的,于是我們有必要將圖片與頁面進(jìn)行分離,這是基本上大型網(wǎng)站都會(huì)采用的策略,他

55、們都有獨(dú)立的圖片服務(wù)器,甚至很多臺(tái)圖片服務(wù)器。這樣的架構(gòu)可以降低提供頁面訪問請(qǐng)求的服務(wù)器系統(tǒng)壓力,并且可以保證系統(tǒng)不會(huì)因?yàn)閳D片問題而崩潰,在應(yīng)用 服務(wù)器和圖片服務(wù)器上,可以進(jìn)行不同的配置優(yōu)化,比如apache在配置ContentType的時(shí)候可以盡量少支持,盡可能少的LoadModule, 保證更高的系統(tǒng)消耗和執(zhí)行效率。利用Apache實(shí)現(xiàn)圖片服務(wù)器的分離緣由:起步階段的應(yīng)用,都可能部署在一臺(tái)服務(wù)器上(費(fèi)用上的原因)第一個(gè)優(yōu)先分離的,肯定是數(shù)據(jù)庫和應(yīng)用服務(wù)器。第二個(gè)分離的,會(huì)是什么呢?各有各的考慮,我所在的項(xiàng)目組重點(diǎn)考慮的節(jié)約帶寬,服務(wù)器性能再好,帶寬再高,并發(fā)來了,也容易撐不住。因此,我這篇

56、文章的重點(diǎn)在這里。這里重點(diǎn)是介紹實(shí)踐,不一定符合所有情況,供看者參考吧,環(huán)境介紹:WEB應(yīng)用服務(wù)器:4CPU雙核2G, 內(nèi)存4G 部署:Win2003/Apache Http Server 2.1/Tomcat6數(shù)據(jù)庫服務(wù)器:4CPU雙核2G, 內(nèi)存4G 部署:Win2003/MSSQL2000步驟:步驟一:增加2臺(tái)配置為:2CPU雙核2G,內(nèi)存2G普通服務(wù)器,做資源服務(wù)器 部署:Tomcat6,跑了一個(gè)圖片上傳的簡(jiǎn)單應(yīng)用,(記得指定web.xml的),并指定域名為res1.*.com,res2.*.com,采用ajp協(xié)議步驟二:修改Apache httpd.conf配置 原來應(yīng)用的文件上傳功

57、能網(wǎng)址為: 1、/fileupload.html 2、/otherupload.html 在httpd.conf中增加如下配置 ServerAdmin webmaster*.com ProxyPass /fileupload.html balancer:/rescluster/fileupload lbmethod=byrequests stickysession=JSESSIONID nofailover=Off timeout=5 maxattempts=3 ProxyPass /otherupload.html balancer:/rescluster/otherupload.html

58、lbmethod=byrequests stickysession=JSESSIONID nofailover=Off timeout=5 maxattempts=3 # BalancerMember ajp:/res1.*.com:8009 smax=5 max=500 ttl=120 retry=300 loadfactor=100 route=tomcat1 BalancerMember ajp:/res2.*.com:8009 smax=5 max=500 ttl=120 retry=300 loadfactor=100 route=tomcat2 步驟三,修改業(yè)務(wù)邏輯: 所有上傳文件

59、在數(shù)據(jù)庫中均采用全url的方式保存,例如產(chǎn)品圖片路徑存成:http:/res1.*.com/upload/20090101/product120302005.jpg現(xiàn)在,你可以高枕無憂了,帶寬不夠時(shí),增加個(gè)幾十臺(tái)圖片服務(wù)器,只需要稍微修改一下apache的配置文件,即可。五:高并發(fā)高負(fù)載網(wǎng)站的系統(tǒng)架構(gòu)之?dāng)?shù)據(jù)庫集群和庫表散列大型網(wǎng)站都有復(fù)雜的應(yīng)用,這些應(yīng)用必須使用數(shù)據(jù)庫,那么在面對(duì)大量訪問的時(shí)候,數(shù)據(jù)庫的瓶頸很快就能顯現(xiàn)出來,這時(shí)一臺(tái)數(shù)據(jù)庫將很快無法滿足應(yīng)用,于是我們需要使用數(shù)據(jù)庫集群或者庫表散列。在數(shù)據(jù)庫集群方面,很多數(shù)據(jù)庫都有自己的解決方案,Oracle、Sybase等都有很好的方案,常用的

60、MySQL提供的Master/Slave也是類似的方案,您使用了什么樣的DB,就參考相應(yīng)的解決方案來實(shí)施即可。 上面提到的數(shù)據(jù)庫集群由于在架構(gòu)、成本、擴(kuò)張性方面都會(huì)受到所采用DB類型的限制,于是我們需要從應(yīng)用程序的角度來考慮改善系統(tǒng)架構(gòu),庫表散列是常用并 且最有效的解決方案。我們?cè)趹?yīng)用程序中按照業(yè)務(wù)和應(yīng)用或者功能模塊將數(shù)據(jù)庫進(jìn)行分離,不同的模塊對(duì)應(yīng)不同的數(shù)據(jù)庫或者表,再按照一定的策略對(duì)某個(gè)頁面或者 功能進(jìn)行更小的數(shù)據(jù)庫散列,比如用戶表,按照用戶ID進(jìn)行表散列,這樣就能夠低成本的提升系統(tǒng)的性能并且有很好的擴(kuò)展性。sohu的論壇就是采用了這樣的 架構(gòu),將論壇的用戶、設(shè)置、帖子等信息進(jìn)行數(shù)據(jù)庫分離,

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論