主頁 > 軟體設計 > java-Nginx與Tomcat安裝,配置及優化

java-Nginx與Tomcat安裝,配置及優化

2021-11-10 08:08:40 軟體設計

java-Nginx與Tomcat安裝,配置及優化

1. java-Nginx安裝,配置及優化

1.1 Nginx的安裝

linux服務器三種安裝方式:

1.rpm(或pkg)安裝,類似以與Windows安裝程式,是預編譯好的程式,

  • 使用的是通用引數編譯,配置引數部署最佳
  • 可控制性不強,比如對程式特定組件的定制性安裝
  • 通常安裝包間有復雜依賴關系,操作比較復雜

2.yum(或者apt-get)安裝,改良版的rpm,自動聯網下載安裝包,自動管理依賴關系

3.編譯安裝(方式在各類Linux發行版中差異不大)

  • 可控制性強,config是可根據當前系統環境優化引數,可定制組件及安裝引數
  • 易出錯,難度略高

1.2 nginx 安裝 啟動 關閉自動啟動

sbin目錄下:

啟動: ./nginx

關閉: ./nginx -s stop

多載組態檔: ./nginx -s reload

1.3 Nginx的配置

組態檔位置: conf/nginx.conf

全域塊

events塊

http塊

include: 引入組態檔

#頂層配置資訊管理服務器級別行為
#一般一個行程足夠了,你可以把連接數設得很大,如果有SSL、gzip這些比較消耗CPU的作業,而且是多核CPU的話,可以設為和CPU的數量一樣,或者要處理很多很多的小檔案,而且檔案總大小比記憶體大很多的時候,也可以把行程數增加,以充分利用IO帶寬(主要似乎是IO操作有block)
worker_processes 1;

#event指令與時間模型有關,配置處理連接有關資訊
events{
    #單個作業行程可以允許同時建立外部連接的數量
    worker_connections 1024;
}

#http指令處理http請求:接受請求
http{
    #mime type 映射
    include             mime.types; #引入另外一個組態檔
    default_type        application/octet-stream; #在mime.type不存在的時候, 默認的檔案型別
    
    sendfile            on;
    #tcp_nopush         on;
    
    #keepalive_timeout  0;
    keepalive_timeout   65;
    
    #gzip          on;
    
    
    #server 處理請求 表示一個虛擬主機,一臺服務器可配置多個虛擬主機
    #第一個server 除了匹配本身 server_name 指定的域名外, 還匹配其他server都不匹配的域名
    server{
        #監聽埠
        listen         80;
        #識別的域名
        server_name    localhost;
        
        #一個關鍵設定,與url引數亂碼問題有關
        charset        utf-8;
        
        #access_log    logs/host.access.log   main;
        
        #一個server下面可以有多個location,每個location有不同的處理行為,根據運算式匹配,請求交個哪個location,
        #根據location里面的運算式,映射到具體的處理行為
        #location  
        
        
        #location運算式:
        #syntax: location [=|~|~*|^~|@] /uri/ {...}
        #分為兩種匹配模式,普通字串匹配,正則匹配
        #無開頭引導字符或以=開頭標識普通字串匹配
        #以~或~*開頭標識正則匹配,~*標識不區分大小寫
        #多個location時匹配規則
        #總體是先普通后正則原則,只識別URI部分,例如請求為/test/1/abc.do?arg=xxx
        #1. 先查找是否有=開頭的精確匹配,即location = /test/1/abc.do {...}
        #2. 再查找普通匹配,以最大前綴為規則,如有以下兩個location
        #      location /test/ {...}
        #      location /test/1/ {...}
        #   則匹配最后一項
        #3. 匹配到一個普通格式后,搜索并未結束,而是暫存當前結果,并繼續再搜索正則模式
        #4. 在所有正則模式location中找到第一個匹配項后,以此匹配項為最終結果
        #   所以正則匹配項規則受定義前后順序影響,但普通匹配不會
        #5. 如果未找到匹配項,則以3中快取的結果為最終結果
        #6. 如果一個匹配都沒有,回傳404
        
        #location =/ {...}  與  location / {...}的差別
        #前一個是精確匹配,只回應/請求,所有/xxx類請求,不會以,前綴匹配形式匹配到它,
        #后一個正相反,所有請求必然都是以/開頭,所以沒有其他匹配結果的時候一定會執行到它
        
        #location ^~ / {...} ^~意思是非正則,標識匹配到此模式不再繼續正則搜索
        #所有如果這樣配置,相當于關閉了正則匹配功能
        #因為一個請求在普通匹配規則下沒得到其他普通匹配結果時,最終匹配到這里
        #而這個 ^~指令又相當于不允許正則,相當于匹配到此為止
        
        #精確匹配
        location =/test {
            ...
        }
        #普通字符匹配
        location /test {
            ...
        }
        
        location / {
            root       html;  #指定根目錄  絕對路徑或者相對路徑
            index      index.html  index.htm; #請求到達后沒有指定具體檔案,默認用index指定的順序,查找檔案
            #deny all;  拒絕請求,回傳403
            #allow all; 允許請求
        }
        
        location ^~ /test/ {
            deny all;
        }
        
        
        #正則匹配
        location ~ /test/.+\.jsp$ {
            #代理
            proxy_pass   http://192.168.1.62:8080;
        }
        
        #正則匹配
        location ~* \.jsp$ {
            proxy_pass  http://192.168.1.61:8080;
        }
        
        
        #定義各類錯誤頁
        error_page   404     /404.html;
        
        #redirect server error pages to the static page /50x.html
        #
        error_page  500 502 503 504   /50x.html;
        location = /50x/html {
            root   html;
        }
        
        # @類似于變數定義
        # 錯誤執行另外一個代理服務器的時候,location 定義一個變數名, 用@符號
        # error_page  403  http://www.121212.com這種定義不允許,所以利用@實作
        error_page  403   @page403;
        location @page403 {
            proxy_pass = http://www.121212.com;
        }
        
    }
}

mime.types

Nginx 會根據mime type定義的對應關系來告訴瀏覽器如何處理服務器傳給瀏覽器的這個檔案,是打開還是下載;如果Web程式沒設定,Nginx也沒對應檔案的擴展名,就用Nginx 里默認的 default_type定義的處理方式,

比如Nginx默認的配置中default_type application/octet-stream; 這個就是默認為下載,瀏覽器訪問到未定義的擴展名的時候,就默認為下載該檔案;如果將這個設定改成default_type text/html;那就是告訴瀏覽器默認的打開方式是把所有未設定的擴展名當HTML檔案打開,雖然可能這樣設定會很多打不開,

mime type 和檔案擴展名的對應關系一般放在 mime.types這個檔案里,然后用 include mime.types; 來加載

mime.types檔案里是用types指令來定義的,下面是一個完整的定義:

mime.types檔案

types {
    text/html                             html htm shtml;
    text/css                              css;
    text/xml                              xml;
    image/gif                             gif;
    image/jpeg                            jpeg jpg;
    #application/x-javascript              js;
    application/javascript              js;
    application/atom+xml                  atom;
    application/rss+xml                   rss;

    text/mathml                           mml;
    text/plain                            txt;
    text/vnd.sun.j2me.app-descriptor      jad;
    text/vnd.wap.wml                      wml;
    text/x-component                      htc;

    image/png                             png;
    image/tiff                            tif tiff;
    image/vnd.wap.wbmp                    wbmp;
    image/x-icon                          ico;
    image/x-jng                           jng;
    image/x-ms-bmp                        bmp;
    image/svg+xml                         svg;

    application/java-archive              jar war ear;
    application/mac-binhex40              hqx;
    application/msword                    doc;
    application/pdf                       pdf;
    application/postscript                ps eps ai;
    application/rtf                       rtf;
    application/vnd.ms-excel              xls;
    application/vnd.ms-powerpoint         ppt;
    application/vnd.wap.wmlc              wmlc;
    application/vnd.wap.xhtml+xml         xhtml;
    application/vnd.google-earth.kml+xml  kml;
    application/vnd.google-earth.kmz      kmz;
    application/x-7z-compressed           7z;
    application/x-cocoa                   cco;
    application/x-java-archive-diff       jardiff;
    application/x-java-jnlp-file          jnlp;
    application/x-makeself                run;
    application/x-perl                    pl pm;
    application/x-pilot                   prc pdb;
    application/x-rar-compressed          rar;
    application/x-redhat-package-manager  rpm;
    application/x-sea                     sea;
    application/x-shockwave-flash         swf;
    application/x-stuffit                 sit;
    application/x-tcl                     tcl tk;
    application/x-x509-ca-cert            der pem crt;
    application/x-xpinstall               xpi;
    application/zip                       zip;

    application/octet-stream              bin exe dll;
    application/octet-stream              deb;
    application/octet-stream              dmg;
    application/octet-stream              eot;
    application/octet-stream              iso img;
    application/octet-stream              msi msp msm;

    audio/midi                            mid midi kar;
    audio/mpeg                            mp3;
    audio/x-realaudio                     ra;

    video/3gpp                            3gpp 3gp;
    video/mpeg                            mpeg mpg;
    video/quicktime                       mov;
    video/x-flv                           flv;
    video/x-mng                           mng;
    video/x-ms-asf                        asx asf;
    video/x-ms-wmv                        wmv;
    video/x-msvideo                       avi;
}

一般在Nginx的組態檔nginx.conf里面的http{}欄位中配置即可,注意mime.types是在你的nginx的安裝目錄下,如果目錄不是下面的,那你要自己手工修改:

參考博客: https://blog.csdn.net/qq_37788558/article/details/78621592

location

url匹配規則
location [=|~|~*|^~|@] /uri/ {
  ...
} 
  • = : 表示精確匹配后面的url
  • ~ : 表示正則匹配,但是區分大小寫
  • ~* : 正則匹配,不區分大小寫
  • ^~ : 表示普通字符匹配,如果該選項匹配,只匹配該選項,不匹配別的選項,一般用來匹配目錄
  • @ : “@” 定義一個命名的 location,使用在內部定向時,例如 error_page

上述匹配規則的優先匹配順序:

  1. = 前綴的指令嚴格匹配這個查詢,如果找到,停止搜索;
  2. 所有剩下的常規字串,最長的匹配,如果這個匹配使用 ^~ 前綴,搜索停止;
  3. 正則運算式,在組態檔中定義的順序;
  4. 如果第 3 條規則產生匹配的話,結果被使用,否則,使用第 2 條規則的結果,

location運算式:

syntax: location [=|~|~*|^~|@] /uri/ {...}

分為兩種匹配模式,普通字串匹配,正則匹配
無開頭引導字符或以=開頭標識普通字串匹配

~~*開頭標識正則匹配,~*標識不區分大小寫

多個location時匹配規則

總體是先普通后正則原則,只識別URI部分,例如請求為/test/1/abc.do?arg=xxx

  1. 先查找是否有=開頭的精確匹配,即location = /test/1/abc.do {…}
  2. 再查找普通匹配,以最大前綴為規則,如有以下兩個location
    location /test/ {…}
    location /test/1/ {…}
    則匹配最后一項
  3. 匹配到一個普通格式后,搜索并未結束,而是暫存當前結果,并繼續再搜索正則模式
  4. 在所有正則模式location中找到第一個匹配項后,以此匹配項為最終結果
    所以正則匹配項規則受定義前后順序影響,但普通匹配不會
  5. 如果未找到匹配項,則以3中快取的結果為最終結果
  6. 如果一個匹配都沒有,回傳404

location =/ {…} 與 location / {…}的差別
前一個是精確匹配,只回應/請求,所有/xxx類請求,不會以,前綴匹配形式匹配到它,
后一個正相反,所有請求必然都是以/開頭,所以沒有其他匹配結果的時候一定會執行到它

location ^~ / {...} ^~意思是非正則,標識匹配到此模式不再繼續正則搜索
所有如果這樣配置,相當于關閉了正則匹配功能

因為一個請求在普通匹配規則下沒得到其他普通匹配結果時,最終匹配到這里
而這個 ^~指令又相當于不允許正則,相當于匹配到此為止

#精確匹配
        location =/test {...}
        #普通字符匹配
        location /test {...}
        
        location / {
            root       html;  #指定根目錄  絕對路徑或者相對路徑
            index      index.html  index.htm; #請求到達后沒有指定具體檔案,默認用index指定的順序,查找檔案
            #deny all;  拒絕請求,回傳403
            #allow all; 允許請求
        }
        
        location ^~ /test/ {
            deny all;
        }
        
        
        #正則匹配
        location ~ /test/.+\.jsp$ {
            #代理
            proxy_pass   http://192.168.1.62:8080;
        }
        
        #正則匹配
        location ~* \.jsp$ {
            proxy_pass  http://192.168.1.61:8080;
        }
        
        
        #定義各類錯誤頁
        error_page   404     /404.html;
        
        #redirect server error pages to the static page /50x.html
        #
        error_page  500 502 503 504   /50x.html;
        location = /50x/html {
            root   html;
        }
        
        # @類似于變數定義
        # 錯誤執行另外一個代理服務器的時候,location 定義一個變數名, 用@符號
        # error_page  403  http://www.121212.com這種定義不允許,所以利用@實作
        error_page  403   @page403;
        location @page403 {
            proxy_pass = http://www.121212.com;
        }

@ 類似于變數定義

 # @類似于變數定義
 # 錯誤執行另外一個代理服務器的時候,location 定義一個變數名, 用@符號
 # error_page  403  http://www.121212.com這種定義不允許,所以利用@實作
 error_page  403   @page403;
 location @page403 {
      proxy_pass = http://www.121212.com;
 }

1.4 Nginx的優化

nginx.conf組態檔

全域塊

nginx不同于apache服務器,當apache進行了大量優化設定后會有魔術般的明顯提升性能效果,nginx在安裝完成后,大部分引數都是最優化了,我們需要管理的東西并不多

阻塞和非阻塞網路模型:

同步阻塞模型,一請求一進(線)程,當進(線)程增加到一定程度后,更多的CPU時間浪費到切換CPU,性能急劇下降,所以負載率并不高

Nginx基于事件的非阻塞多路復用(epoll或kquene)模型,一個行程在段時間內可以回應大量的請求

案例:

#user   nobody;

#作業行程數量:接受和處理用戶請求
#建議值 <= CPU核心數量,一般高于cpu數量不會帶來好處,也許還有行程切換開銷的負面影響
worker_processes   4;

#將work process 系結到特定的CPU上,避免行程在cpu間切換的開銷
#多少個cpu,每組數字就有多少個數字 0/1
worker_cpu_affinity   0001 0010 0100 1000;
#8核4行程時的設定方法  worker_cpu_affinity   00000001 00000010 00000100 10000000


# 每個行程最大可打開檔案描述符數量(linux上檔案描述符比較廣泛,網路埠,設備,磁盤檔案都是)
# 檔案描述符用完了,新的連接會拒絕,產生502類錯誤
# linux 最大可打開檔案數可通過ulimit -n FILECNT或 /etc/security/limits.conf配置
# 理論值: 系統最大數量 / 行程數,但行程間作業量并不是平均分配的,所以可以設定的大一些
#越大越好
worker_rlimit_nofile   655350;

events{
    ...
}

worker_processes

作業行程數量:接受和處理用戶請求

#作業行程數量:接受和處理用戶請求
#建議值 <= CPU核心數量,一般高于cpu數量不會帶來好處,也許還有行程切換開銷的負面影響
worker_processes   4;
worker_cpu_affinity

將work process 系結到特定的CPU上

#將work process 系結到特定的CPU上,避免行程在cpu間切換的開銷
#多少個cpu,每組數字就有多少個數字 0/1
worker_cpu_affinity   0001 0010 0100 1000;
#8核4行程時的設定方法  worker_cpu_affinity   00000001 00000010 00000100 10000000
worker_rlimit_nofile

每個行程最大可打開檔案描述符數量

# 每個行程最大可打開檔案描述符數量(linux上檔案描述符比較廣泛,網路埠,設備,磁盤檔案都是)
# 檔案描述符用完了,新的連接會拒絕,產生502類錯誤
# linux 最大可打開檔案數可通過ulimit -n FILECNT或 /etc/security/limits.conf配置
# 理論值: 系統最大數量 / 行程數,但行程間作業量并不是平均分配的,所以可以設定的大一些
#越大越好
worker_rlimit_nofile   655350;

events塊

....

events {
    #并發回應能力的關鍵配置值 
    #每個行程允許的最大同時連接數,worker_connections * worker_processes = maxConnection;
    #要注意maxConnection不等于可回應的用戶數量,
    #因為一般一個瀏覽器會同時開兩條連接,如果反向代理,nginx到后端服務器的連接也要占用連接數
    #所以,做靜態服務器時,一般 maxClient = worker_connections * worker_processes /2
    #做反向代理服務器時,maxClient = worker_connections * worker_processes /4
    
    #這個值理論上越大越好,但最多可承受多少請求與配置和網路相關,也可最大可打開檔案,最大可用sockets數量
    worker_connections 200000;
    
    #指明使用 epoll 或 kqueue (*BSD)
    use epoll;
    
    #備注:要達到超高負載下最好的網路回應能力,還有必要優化與網路相關的linux 引數
    
}

....
worker_connections

并發回應能力的關鍵配置值,每個行程允許的最大同時連接數

    #并發回應能力的關鍵配置值 
    #每個行程允許的最大同時連接數,worker_connections * worker_processes = maxConnection;
    #要注意maxConnection不等于可回應的用戶數量,
    #因為一般一個瀏覽器會同時開兩條連接,如果反向代理,nginx到后端服務器的連接也要占用連接數
    #所以,做靜態服務器時,一般 maxClient = worker_connections * worker_processes /2
    #做反向代理服務器時,maxClient = worker_connections * worker_processes /4
    
    #這個值理論上越大越好,但最多可承受多少請求與配置和網路相關,也可最大可打開檔案,最大可用sockets數量
    worker_connections 200000;

maxClient:最大客戶可用連接數

maxClient = worker_connections * worker_processes /2

做反向代理服務器時,maxClient = worker_connections * worker_processes /4

use

指定事件處理的時候,指定網路模型

基本不需要設定,nginx自動識別,

windows無法使用多路復用模型,這也是為什么nginx在windows上,性能不夠好的原因

 #指明使用 epoll 或 kqueue (*BSD)
 use epoll;

http塊

....

events{
    ...
}

https {
    include         mime.types;
    dafault_type    application/octet-stream;
    
    #訪問日式是否記錄
    #關閉此項可減少IO開銷,但也無法記錄訪問資訊,不利于業務分析,一般運維情況不建議使用
    access_log      off;
    
    #錯誤日志
    #crit:只記錄更為嚴重的錯誤日志,可減少IO壓力,或者關閉
    error_log  logs/error.log   crit;
    #access_log  logs/access.log    main;
    
    #啟用內核復制模式,應該保持開啟達到最快IO效率,從磁盤級IO復制到網路級IO,不經過用戶級,減少了幾次復制程序【零拷貝技術】
    sendfile        on;
    
    #簡單說,啟動如下兩項配置,會在資料包達到一定大小后再發送資料
    #這樣會較少網路通信次數,降低阻塞概率,但也會影響回應及時性
    #比較合適于檔案下載這類的大資料包通信場景
    #tcp_nohush     on;
    #tcp_nodelay  on|off  on禁用Nagle演算法
    
    #HTTP1.1支持持久連接alive
    #連接存活時間: 降低每個連接的alive時間,可在一定程度上提高回應連接數量,所以一般可適當降低此值
    keepalive_timeout  30s;
    
    #啟動內容壓縮,有效降低網路流量,生產環境打開
    gzip               on;
    
    #內容壓縮最小長度:過短的就不要壓縮,因為 過短的內容壓縮效果不佳,壓縮程序還會浪費系統資源
    gzip_min_length    1000;
    
    #可選值1~9,壓縮級別越高,壓縮率越高,但對系統性能要求越高
    gzip_comp_level    4;
   
    #壓縮的內容類別
    gzip_types    text/plain  text/css application/json   application/x-javascript  text/xml ...;
    
    
    #靜態檔案快取
    #最大快取數量,檔案未使用存活期
    #open_file_cache 打開檔案,max:快取檔案最大個數,
    #"inactive":檔案存活期,"open_file_cache_min_uses"快取檔案在20s內使用至少2次,那么快取檔案不會被替換,是一個命中率有效的檔案
    #"open_file_cache_valid":表示多久驗證快取,會釋放使用次數少的檔案
    open_file_cache max=655350  inactive=20s;
    
    #驗證快取有效期時間間隔
    open_file_cache_valid  30s;
    
    #有效期內檔案最少使用次數
    open_file_cache_min_uses  2;
    
    
    server {
        ...
    } 
    
}
日志
    #訪問日式是否記錄
    #關閉此項可減少IO開銷,但也無法記錄訪問資訊,不利于業務分析,一般運維情況不建議使用
    access_log      off;
    
    #錯誤日志
    #crit:只記錄更為嚴重的錯誤日志,可減少IO壓力,或者關閉
    error_log  logs/error.log   crit;
    #access_log  logs/access.log    main;
內核復制
#啟用內核復制模式,應該保持開啟達到最快IO效率,從磁盤級IO復制到網路級IO,不經過用戶級,減少了幾次復制程序【零拷貝技術】
    sendfile        on;
壓縮
    #啟動內容壓縮,有效降低網路流量,生產環境打開
    gzip               on;
    
    #內容壓縮最小長度:果斷的就不要壓縮,因為 過短的內容壓縮效果不佳,壓縮程序還會浪費系統資源
    gzip_min_length    1000;
    
    #可選值1~9,壓縮級別越高,壓縮率越高,但對系統性能要求越高
    gzip_comp_level    4;
   
    #壓縮的內容類別
    gzip_types    text/plain  text/css application/json   application/x-javascript  text/xml;
靜態檔案快取
    #靜態檔案快取
    #最大快取數量,檔案未使用存活期
    #open_file_cache 打開檔案,max:快取檔案最大個數,
    #"inactive":檔案存活期,"open_file_cache_min_uses"快取檔案在20s內使用至少2次,那么快取檔案不會被替換,是一個命中率有效的檔案
    #"open_file_cache_valid":表示多久驗證快取,回釋放使用次數少的檔案
    open_file_cache max=655350  inactive=20s;
    
    #驗證快取有效期時間間隔
    open_file_cache_valid  30s;
    
    #有效期內檔案最少使用次數
    open_file_cache_min_uses  2;

2. Tomcat安裝,配置及優化

2.1 安裝JDK

下載 jdk1.8.0_51.tar.gz 解壓…在下面添加配置

/etc/profile.d/ 系統啟動的時候,會執行這里面的 .sh檔案

#/etc/profile.d/java.sh

JAVA_HOME=/opt/jdk1.8.0_51
#參考原PATH方式::$PATH
PATH=$JAVA_HOME/bin:$PATH
#匯出路徑:
export JAVA_HOME PATH

設定立即生效: source /etc/profile

2.2 Tomcat安裝

日志: /logs/catalina.out

啟動: /bin/start.sh

關閉: /bin/shutdown.sh

開機啟動:/etc/rc.d/rc.local 檔案 :用來設定開機自動運行

touch /var/lock/subsys/local
/opt/nginx/sbin/nginx

export  JAVA_HOME=/opt/jdk1.8.0_51
$JAVA_HOME/bin/startup.sh

rc.local 比 profile.d 檔案夾里面的控制腳本啟動的更早,所以上面需要重新匯出一遍JAVA_HOME命令

2.3 Tomcat的優化配置

記憶體使用配置

/bin/catalina.sh

......

#Windows下配置方法
#set JAVA_OPTS=%JAVA_OPTS% -server -Xms2048m -Xmx2048m -XX:PermSize=256m -XX:MaxPermSize=512m -Djava.awt.headless=true
#通過記憶體設定充分利用服務器記憶體
#-server模式啟動應用慢,但可以極大程度提高運行性能
#java 8開始,PermSize 被 MetaspaceSize 代替,MetaspaceSize共享heap,不會再有java.lang.outofMemoryError:PermGen space,可以不設定PermSize
#headless=true 適用于linux系統,于圖形操作有關,如生成驗證碼,含義是當前適用的是無顯示幕的服務器,應用中如果獲取系統顯示有關引數會拋例外
#可通過 jmap -heap process_id查看設定是否成功
JAVA_OPTS=$JAVA_OPTS -server -Xms2048m -Xmx2048m -XX:PermSize=256m -XX:MaxPermSize=512m -Djava.awt.headless=true

......

最大連接數配置

server.xml

<!-- 埠連接  protocol : bio  nio apr 三種網路模型-->
<!-- protocol 啟用nio模式,(tomcat8默認使用的是nio)(apr模式利用系統異步io) -->
<!-- minProcessors 最小空閑連接執行緒數 -->
<!-- maxProcessors 最大連接執行緒數 -->
<!-- acceptCount 允許的最大連接數,應大于等于 maxProcessors -->
<!-- enableLookups 如果為true,request.getRemoteHost 會執行DNS 查找,反向決議ip 對應域名或主機名 -->
<Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"
           connectionTimetoue="20000"
           redirectPort="8443"
           
           maxThreads="500"      #最大連接執行緒數
           minSpareThreads="100" #最小空閑執行緒
           maxSpareThreads="200" #最大空閑執行緒
           acceptCount="200"     #所有執行緒啟動后,還允許接受的連接數量,也就是等待的執行緒數 ,最大可接受的任務:maxThreads+acceptCount
           enableLookups="false" #是否允許DNS反查
 />

3. Nginx+Tomcat負載均衡詳細配置

3.1 負載均衡配置的實作

正向代理和反向代理

**正向代理:如果把局域網外的 Internet 想象成一個巨大的資源庫,則局域網中的客戶端要訪問 Internet,則需要通過代理服務器來訪問,這種代理服務就稱為正向代理,**對于反向代理,客戶端對代理是無感知的,因為客戶端不需要任何配置就可以訪問,我們只需要將請求發送到反向代理服務器,由反向代理服務器去選擇目標服務器獲取資料后,在回傳給客戶端,此時反向代理服務器和目標服務器對外就是一個服務器,暴露的是代理服務器地址,隱藏了真實服務器 IP 地址,

代理一般分為正向代理和反向代理,

正向代理是一個位于客戶端和原始服務器之間的服務器,為了從原始服務器取得內容,客戶端向代理發送一個請求并指定目標(原始服務器),然后代理向原始服務器轉交請求并將獲得的內容回傳給客戶端,

反向代理實際運行方式是代理服務器接受網路上的連接請求,它將請求轉發給內部網路上的服務器,并將從服務器上得到的結果回傳給網路上請求連接的客戶端,此時代理服務器對外就表現為一個服務器,

可以這么認為,對于正向代理,代理服務器和客戶端處于同一個局域網內;而反向代理,代理服務器和源站則處于同一個局域網內,

參考博客:https://blog.csdn.net/u010039418/article/details/80011127

https://www.cnblogs.com/xudong-bupt/p/8661523.html

nginx 充當代理服務器: 瀏覽器->Nginx->Tomcat,原理如下:

請添加圖片描述

192.168.1.61服務器請求轉到192.168.1.62中的tomcat

192.168.1.61中nginx配置如下:
nginx.conf檔案里面設定代理

worker_processes 1;
events {
    worker_connections 1024;
}
http {
    include    mime.types;
    default_type  application/octet-stream;
    sendfile   on;
    keepalive_timeout  65;
    
    server {
        listen    80;
        server_name   localhost;
        location / {
            #root    html;
            index   index.html  index.htm;
            #代理配置
            proxy_pass  http://192.168.1.62:8080;
        }
        
        error_page  500 502 503 504  /50x.html;
        location = /50x.html {
            root html;
        }
    }
}

修改完成后,組態檔生效:sbin/nginx -s reload

負載均衡

示意圖如下:
請添加圖片描述
三個要素:

1.服務器組

2.nginx配置

3.負載均衡策略

首先要有多個服務器,形成服務器組,nginx通過反向代理,將請求發送到服務器組上,根據負載均衡策略,分配請求到具體的服務器上,

打開nginx檔案,實作負載均衡配置:

worker_processes 1;
events {
    worker_connections 1024;
}
http {
    include    mime.types;
    default_type  application/octet-stream;
    sendfile   on;
    keepalive_timeout  65;
    
    #定義服務器組,默認輪訓方式發送請求
    upstream tomcats {
        server 192.168.1.62:8080;
        server 192.168.1.63:8080;
    }
    
    server {
        listen    80;
        server_name   localhost;
        location / {
            #root    html;
            index   index.html  index.htm;
            #代理配置:  服務器組名,請求發送給服務器組
            proxy_pass  http://tomcats;
        }
        
        error_page  500 502 503 504  /50x.html;
        location = /50x.html {
            root html;
        }
    }
}
upstream 引數
...
#配置用于負載均衡的服務器集群資訊
upstream backends {
    #均衡策略
    #none 輪訓(權重由weight決定)
    #ip_hash
    #fair
    #url_hash
    
    server 192.168.1.62:8080;
    server 192.168.1.63;
    
    #weight:權重,值越高負載越大;
    #server 192.168.1.64 weigth=5;
    
    #backup: 備份機,只有非備份機都掛掉,才啟用:
    server 192.168.1.64 backup;
    
    #down: 停機標志,不會被訪問
    server 192.168.1.64 down;
    
    #max_fails:達到指定次數認為服務器掛掉;
    #fail_timeout:掛掉之后過多久再去測驗是否已恢復
    server 192.168.1.66 max_fails=2 fail_timeout=60s;
    
}

...
均衡策略
平均輪訓 默認

1:1

權重

根據權重不大, 分配的ip數量不同,默認1:1

upstream backends {
    server 192.168.1.62:8080 weight=5;
    server 192.168.1.63:8080 weight=3;
}
ip_hash

用戶訪問的ip第一次訪問的時候,會系結到某一個均衡策略里面,指定的服務器上面,后續該ip的請求的,都會訪問這個系結的服務器ip地址,

使用方式:

upstream backends {
    ip_hash; #在這指定使用了ip_hash方式
    server 192.168.1.62:8080 ;
    server 192.168.1.63:8080 ;
}
fair

第三方擴展的

下載: nginx-upstream-fair-master.zip

編譯第三方檔案:

在編譯nginx的時候,

./configure --prefix=/opt/nginx --add-module=/tmp/nginx-upstream-fair-master

make & make install #如果第一次編譯,

make #如果nginx之前已經編譯過了, make:只是編譯

cd objs #里面是擴展包,用里面的nginx替換掉外部的nginx

(用nginx檔案帶著第三方擴展模塊,重新編譯,然后編譯的nginx替換掉之前的nginx檔案,即可)

動態自動的,對服務器負載高的的服務器增加請求數量,自動調節

upstream backends {
    fair;
    server 192.168.1.62:8080 ;
    server 192.168.1.63:8080 ;
}
url_hash

第三方擴展的

根據用戶的url進行hash運算

電子商務網站,對于不同商品的,不同路徑,在快取了商品的獨一無二的url之后,用戶訪問的話,都會映射到一個服務器上,如果資料在服務器上面快取的話, 會極大提供并發,大量不同的商品在不同的服務器上面快取起來,

3.2 負載均衡是Session的處理策略

問題

分布式負載均衡情況下 session存在的問題:

服務訪問集群的時候,負載均衡策略把回應轉發到不同的tomcat中,會導致下次訪問請求,如果訪問的不是之前的保存session的那個tomcat,那么此次就會獲取不到session的值,

解決方式

三種策略,

1. 粘性session

用戶鎖定到某個tomcat中,

同一個用戶的請求鎖定到固定的某一個tomcat中,不存在session丟失的問題,

方式:ip_hash

優點:簡單,session無需額外處理

缺點:缺乏容錯性,這個tomcat一旦掛了,用戶立刻感知到

2. session復制

session改變,會在集群里面廣播,所有服務器同步session資料

優點:實時性好

缺點:網路負荷嚴重,可能造成后端性能低下

實作方式:

1.在tomcat的server.xml中開啟 session復制開關

找到模塊Engine

<Engine name="Catalina" defaultHost="localhost">

 <!-- For clustering, please take a look at document at: 
/docs/cluster-howto.html(simple how to)
 /docs/config/cluster.html(reference documentation)
-->
 #打開注釋  打開了tomcat的集群功能, tomcat7以后的版本,有默認值,可以無需配置,只需要打開這個即可
<Cuslter className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
    
    <!-- 基于網路廣播的策略,一個節點的session變化,其他節點同步復制,節點多或資料量大時性能低下 -->
    <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" >
     <Channel className="org.apache.catalina.tries.group.GroupChannel">
         <Receiver className="org.apcache.catalina.tribes.transport.nio.NioReceiver" address="auto" port="4000" />
        </Channel>
    </Cluster>
</Engine>

2.在應用中通知tomcat,當前應用處于集群中

在web.xml中增加選項

<?xml version="1.0" encoding="UTF-8" ?>
...
#增加這個,標識當前應用可以處于集群當中
<distributable/>

...

在TOMCAT7以后,SERVER.XML取消CLUSTER這行注釋之后表示TOMCAT開啟了集群功能.TOMCAT的集群功能配備了發送器,接收器,內容轉換器,還有各種監聽借口,事件顯示幕等一系列功能.以上是在TOMCAT中的要進行修改的,對應的在開發的應用中要在WEB.XML中添加這么一條配置選項,位置如下圖.添加完這兩項配置后,這個應用就有了SESSION復制的功能了.

需要說明的是,因為在一臺服務器上可能不止有一個TOMCAT,在配置引數的時候,不要使用默認引數,要自行進行手動配置.首先要考慮的就是埠沖突問題.比如上方的示例,如果一臺服務器上有兩個TOMCAT,默認指定不同埠.地址也是一樣,因為開啟該項功能,如果設定的是AUTO,會自動選擇,如果選擇錯了,那么也就不能進行.通常服務器有兩個網卡,一個是內網網卡,一個是外網的,我們的接收器是系結在內網上的.因為我們的服務器集群是在內網的,所以接收器自然系結的是內網的網卡,如果綁錯了就會接收不到訊息.

接收器Receiver修改:

多個tomcat存在沖突,埠修改,另外,需要指定網路

<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" >
     <Channel className="org.apache.catalina.tries.group.GroupChannel">
         <Receiver className="org.apcache.catalina.tribes.transport.nio.NioReceiver" address="192.16.1.62" port="4002" />
        </Channel>
    </Cluster>


#另外一個:
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster" >
     <Channel className="org.apache.catalina.tries.group.GroupChannel">
         <Receiver className="org.apcache.catalina.tribes.transport.nio.NioReceiver" address="192.16.1.63" port="4003" />
        </Channel>
    </Cluster>
3. 共享空間保存session

對于Session來說,肯定是頻繁使用的,雖然你可以把它存放在資料庫中,但是真正生產環境中我更推薦存放在性能更快的分布式KV資料中,例如:Memcached和Redis,

借助分布式快取: memched,redis等,

粘性模式 MSM原理 sticky

請添加圖片描述

將用戶的每次請求固定到同一臺服務器,需要一到多個memcached存盤器,主從備份,資料一樣,

一個tomcat指定一個memcached存盤器,不同tomcat指定不同的memcached存盤器,

用戶請求到達tomcat,session會復制一份到memcached存盤器,下次來如果是讀取session,那么不需要讀取memcached存盤器,直接讀取tomcat上面的session資訊,

如果是修改session,tomcat修改完,資料保存到memcached存盤器,

如果tomcat宕機,用戶請求會轉移到另外一個tomcat上面,

如果用戶請求訪問了另外一個tomcat,tomcat沒有session,會去存盤器上訪問,資料保存到tomcat中,,相當于資料同步到tomcat中,

以tomcat為主存盤,備份session到存盤器中,tomcat中沒有資料的時候,從存盤器中獲取,

非粘性模式 MSM原理non-sticky

請添加圖片描述

memcached有多個服務,其中一個是主存盤,其他是備份,資料是實時同步,

session資料寫入備份存盤器,同步到主存盤,tomcat不保存session,讀取的時候,從主存盤獲取,

msm配置:

1.復制jar包到tomcat/lib目錄,jar分三類

  1. spymemcached.har memcached java客戶端

  2. msm相關包

memcached-session-manager-{version}.jar 核心包

memcached-session-manager-tc{tomcat-version}-{version}.jar tomcat版本相關的包

  1. 序列化相關包,有多種可選方法,不設定時使用jdk自帶序列化,其他可選kryo,javaolution,xstream

msm-{tools}-serializer-{version}.jar

2.配置Context,加入處理session的Manager MemcachedBackupSessionManager

Context查找順序:

  1. conf/context.xml 全域配置,作用于所用應用
  2. conf/[enginename]/[hostname]/context.xml.default 全域配置,作用于指定host下全部應用
  3. conf/[enginename]/[hostname]/[contextpath].xml 只作用于contextpath指定的應用
  4. 應用META-INF/context.xml 只作用于本應用
  5. conf/server.xml 的模塊下, 作用于Context docBase指定的應用

所以,只希望session管理作用于特定應用,最好用3,4方式設定,希望作用于全體,可用1,2,5設定

舉個例子,

context-msm.xml

<?xml version="1.0" encoding="UTF-8"?>
<Context>

    <WatchedResource>WEB-INF/web.xml</WatchedResource>
    <WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
    
    <!-- 
       sticky session最小配置
       className 管理器型別
       memcachedNodes memcached服務器節點,以節點名:主機:埠形式表示,其中節點名稱隨意命名,但不同tomcat之間名稱,應該同步
       sticky隱含默認值為true,此時為sticky session模式
       failoverNodes僅適用于sticky模式,n1表示主要將session備份到n2,如果n2不可用,再用n1
       failoverNodes="n1",說明n2是這個tomcat主要用來備份(粘性模式,session主要存盤在tomcat中)的存盤器,n1是n2不可用的時候的被迫選擇,
       另外一臺服務器配置,正好相反,這樣保證將session保存到其他機器,避免整個集群崩潰時tomcat與session都不可用
    -->
    <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
             memcachedNodes="n1:192.168.1.62:11211,n2:192.168.1.63:11211"
             failoverNodes="n1"
             />
    
    <!-- 經常用到的生產環境sticky模式配置 -->
    <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
             memcachedNodes="n1:192.168.1.62:11211,n2:192.168.1.63:11211"
             failoverNodes="n1"
             #忽略的模式
             requestUriIgnorePattern=".*\.(jpg|png|css|js)$"
             #二進制的協議,效率更高
             memcachedProtocol="binary"
             #指定第三方的序列化工具,性能比jdk自帶的更高
             transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
             />
    
    <!-- 經常用到的生產環境non-sticky模式配置 -->
    <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
             memcachedNodes="n1:192.168.1.62:11211,n2:192.168.1.63:11211"
             sticky="false"
             #粘性模式的時候, session異步備份模式,非粘性,需要同步
             sessionBackupAsync="false"
             #鎖模式,session備份寫入的時候,session才可以讀取等操作,防止session操作混亂
             lockingMode="auto"
             #忽略的模式
             requestUriIgnorePattern=".*\.(jpg|png|css|js)$"
             #二進制的協議,效率更高
             memcachedProtocol="binary"
             #指定第三方的序列化工具,性能比jdk自帶的更高
             transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
             />
    
</Context>

4. 集群環境中應用代碼應注意的問題

4.1 物體類序列化支持

實作 介面 Serializable

session里面的物件想,需要序列化

// 可能會放到session中的物體類應實作Serializable介面
// 這樣才能保證成功使用jdk進行序列化
//第三方序列化工具一般不需要實作該介面
//但對無參構造,某些型別(如Map)序列化有特殊要求
//如果程式運行時出現序列化例外,需要參考工具相關檔案進行處理
public class User implements Serializable {
    //實作了 介面 Serializable 的類建議生成一個serialVersionUID,他相當于一個類版本號,當類成員改變時,修改這個ID,這樣,jdk能正確識別已序列化實體與當前類定義是否版本一致
    private static final long serialVersionUID= 1L;
    
    ...
}

4.2 獲取客戶端IP地址

如果是nginx反向代理,tomcat服務器以為nginx是客戶端,所以獲取了nginx服務器的地址,

如果要獲取真是的客戶端的IP地址,需要在nginx代理配置引數

server {
    listen  80;
    server_name  localhost;
    location / {
        #root html;
        index index.html index.htm;
        proxy_pass http://tomcats;
        # 增加這個配置 ,把真實地客戶端Ip地址放到請求頭中,nginx 內置的環境變數:$remote_addr
        proxy_set_header X-Real-IP $remote_addr;        
    }
    
    ...

}

設定了nginx從客戶端中讀取的ip,放到了請求頭:"X-Real-IP"中,讀取如下:

//獲取真實IP
public static String getIp(HttpServletRequest request){
    String remoteIp = request.GetRemoteAddr();
    String headIp = request.getheader("X-Real-IP");
    return headIp == null ? remoteIp : headIp;
}

4.3 nginx 中其他的資訊

#負載均衡設定,將所有jsp請求發送到upstream backends 指定的服務器群上
location ~ \.jsp$ {
    proxy_pass http://backends;
    
    #真實的客戶端IP
    proxy_set_header  X-Real_IP    $remote_addr;
    #請求頭中Host資訊, http://www.test.tt/index.jsp,用戶可以取到客戶端真實正確的host地址
    proxy_set_header  Host         $host;
    #代理路由資訊,此處取IP有安全隱患,整個代理的路由資訊,是各個nginx 等的ip資訊
    proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
    #真實的用戶訪問協議
    proxy_set_header  X-Forwarded-Proto  $scheme;
    
    #默認值是default
    #后端response 302時,tomcat header中location的host是http://192.168.1.62:8080
    #因為tomcat收到的請求是nginx發過去的,nginx發起的請求url host是http://192.168.1.62:80
    #設定default后,nginx自動把回應有中的location host部分替換成當前用戶請求的host部分
    #網上很多教程,將此值設定為 off 禁止了替換
    #這樣用戶瀏覽器收到302后,跳到http://192.168.1.62:8080,直接將后端服務器暴露給瀏覽器
    #所以除非特殊設定,否則不要做這種畫蛇添足的操作
    proxy_redirect  default;
    
}

4.4 動靜分離結果的預規劃

高并發,資源類的檔案,腳本,樣式表,檔案,

靜態檔案放到靜態服務器,

tomcat放到動態服務器中

開發之前規劃好,

總結:

負載均衡實作

session管理

5. 其他

Nginx 配置中nginx和alias的區別分析

root和alias都可以定義在location模塊中,都是用來指定請求資源的真實路徑;

root: *真實的路徑是root指定的值加上location指定的值 ,*

alias: 正如其名,alias指定的路徑是location的別名,不管location的值怎么寫,資源的 *真實路徑都是 alias 指定的路徑*

1、 alias 只能作用在location中,而root可以存在server、http和location中,

2、 alias 后面必須要用 “/” 結束,否則會找不到檔案,而 root 則對 ”/” 可有可無,

本小節參考博客: https://blog.csdn.net/tuoni123/article/details/79712246

本文參考來源:極客學院
如有侵權,聯系速刪

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/354585.html

標籤:其他

上一篇:Linux網路編程——UDP通信 代碼實作

下一篇:手把手教你打包一個自己的Vivado IP核

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more