java web開發之高併發處理

java處理高併發高負載類網站中數據庫的設計方法(java教程,java處理大量數據,java高負載數據)

一:高併發高負載類網站關注點之數據庫

沒錯,首先是數據庫,這是大多數應用所面臨的首個SPOF。尤其是Web2.0的應用,數據庫的響應是首先要解決的。
一般來說MySQL是最常用的,可能最初是一個mysql主機,當數據增加到100萬以上,那麼,MySQL的效能急劇下降。常用的優化措施是 M-S(主-從)方式進行同步複製,將查詢和操作和分別在不同的服務器上進行操作。我推薦的是M-M-Slaves方式,2個主Mysql,多個 Slaves,需要注意的是,雖然有2個Master,但是同時只有1個是Active,我們可以在一定時候切換。之所以用2個M,是保證M不會又成爲系 統的SPOF。
Slaves可以進一步負載均衡,可以結合LVS,從而將select操作適當的平衡到不同的slaves上。
以上架構可以抗衡到一定量的負載,但是隨着用戶進一步增加,你的用戶表數據超過1千萬,這時那個M變成了SPOF。你不能任意擴充Slaves, 否則複製同步的開銷將直線上升,怎麼辦?我的方法是表分區,從業務層面上進行分區。最簡單的,以用戶數據爲例。根據一定的切分方式,比如id,切分到不同 的數據庫集羣去。

全局數據庫用於meta數據的查詢。缺點是每次查詢,會增加一次,比如你要查一個用戶nightsailer,你首先要到全局數據庫羣找到nightsailer對應的cluster id,然後再到指定的cluster找到nightsailer的實際數據。
每個cluster可以用m-m方式,或者m-m-slaves方式。這是一個可以擴展的結構,隨着負載的增加,你可以簡單的增加新的mysql cluster進去。

需要注意的是:
1、禁用全部auto_increment的字段
2、id需要採用通用的算法集中分配
3、要具有比較好的方法來監控mysql主機的負載和服務的運行狀態。如果你有30臺以上的mysql數據庫在跑就明白我的意思了。
4、不要使用持久性鏈接(不要用pconnect),相反,使用sqlrelay這種第三方的數據庫鏈接池,或者乾脆自己做,因爲php4中mysql的鏈接池經常出問題。

二:高併發高負載網站的系統架構之HTML靜態化

其實大家都知道,效率最高、消耗最小的就是純靜態化 http://www.ablanxue.com/shtml/201207/776.shtml的html頁面,所以我們儘可能使我們的網站上的頁面採 用靜態頁面來實現,這個最簡單的方法其實也是 最有效的方法。但是對於大量內容並且頻繁更新的網站,我們無法全部手動去挨個實現,於是出現了我們常見的信息發佈系統CMS,像我們常訪問的各個門戶站點 的新聞頻道,甚至他們的其他頻道,都是通過信息發佈系統來管理和實現的,信息發佈系統可以實現最簡單的信息錄入自動生成靜態頁面,還能具備頻道管理、權限 管理、自動抓取等功能,對於一個大型網站來說,擁有一套高效、可管理的CMS是必不可少的。
  
  除了門戶和信息發佈類型的網站,對於交互性要求很高的社區類型網站來說,儘可能的靜態化也是提高性能的必要手段,將社區內的帖子、文章進行實時的靜態化,有更新的時候再重新靜態化也是大量使用的策略,像Mop的大雜燴就是使用了這樣的策略,網易社區等也是如此。
  
   同時,html靜態化也是某些緩存策略使用的手段,對於系統中頻繁使用數據庫查詢但是內容更新很小的應用,可以考慮使用html靜態化來實現,比如論壇 中論壇的公用設置信息,這些信息目前的主流論壇都可以進行後臺管理並且存儲再數據庫中,這些信息其實大量被前臺程序調用,但是更新頻率很小,可以考慮將這 部分內容進行後臺更新的時候進行靜態化,這樣避免了大量的數據庫訪問請求高併發。
  

網站HTML靜態化解決方案
當一個Servlet資源請求到達WEB服務器之後我們會填充指定的JSP頁面來響應請求:

HTTP請求---Web服務器---Servlet--業務邏輯處理--訪問數據--填充JSP--響應請求

HTML靜態化之後:

HTTP請求---Web服務器---Servlet--HTML--響應請求

靜態訪求如下

Servlet:

public void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    if(request.getParameter("chapterId") != null){
        String chapterFileName = "bookChapterRead_"+request.getParameter("chapterId")+".html";
        String chapterFilePath = getServletContext().getRealPath("/") + chapterFileName;
        File chapterFile = new File(chapterFilePath);
        if(chapterFile.exists()){response.sendRedirect(chapterFileName);return;}//如果有這個文件就告訴瀏覽器轉向 
        INovelChapterBiz novelChapterBiz = new NovelChapterBizImpl();
        NovelChapter novelChapter = novelChapterBiz.searchNovelChapterById(Integer.parseInt(request.getParameter("chapterId")));// 章節信息 
        int lastPageId = novelChapterBiz.searchLastCHapterId(novelChapter.getNovelId().getId(), novelChapter.getId());
        int nextPageId = novelChapterBiz.searchNextChapterId(novelChapter.getNovelId().getId(), novelChapter.getId());
        request.setAttribute("novelChapter", novelChapter);
        request.setAttribute("lastPageId", lastPageId);
        request.setAttribute("nextPageId", nextPageId);
        new CreateStaticHTMLPage().createStaticHTMLPage(request, response, getServletContext(), 
                chapterFileName, chapterFilePath, "/bookRead.jsp");
    }
}
生成HTML靜態頁面的類:

package com.jb.y2t034.thefifth.web.servlet;
import java.io.ByteArrayOutputStream;
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 javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;

public class CreateStaticHTMLPage {
   
    public void createStaticHTMLPage(HttpServletRequest request, HttpServletResponse response,ServletContext servletContext,String fileName,String fileFullPath,String jspPath) throws ServletException, IOException{
        response.setContentType("text/html;charset=gb2312");//設置HTML結果流編碼(即HTML文件編碼) 
        RequestDispatcher rd = servletContext.getRequestDispatcher(jspPath);//得到JSP資源 
        final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();//用於從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 printWriter = new PrintWriter(new OutputStreamWriter(byteArrayOutputStream));//把轉換字節流轉換成字符流 
        HttpServletResponse httpServletResponse = new HttpServletResponseWrapper(response){//用於從response獲取結果流資源(重寫了兩個方法) 
  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章