DAY03
知識回顧
2018年1月13日
8:58
1 parent和common
2 搭建了後臺系統
3 商品分類的全部內容展示(測試)
京淘中的表格設計
京淘中的所有表格都是單表設計
沒有外鍵關聯;
提高系統的性能;
涉及到多表的關係,是代碼
4 後臺的頁面跳轉
restFul傳參
商品分類樹的展示
2018年1月13日
9:07
匯通中我們使用Ztree樹
但是京淘中使用的是EasyUI的封裝
EasyUI介紹
是一組基於jquery的UI插件集合;目的是幫助開發者輕鬆
地打造豐富功能且美觀的UI界面;使用EasyUI不必瞭解複雜的js
或jquery代碼,只需要知道一些簡單的HTML標籤;
在京淘中見到最多的EasyUI當中的一個屬性
data-options
EasyUI在京淘中的使用
後臺頁面樣式就使用的是EasyUI
佈局效果
這裏直接訪問item-add沒有樣式的引入
EasyUI的頁面佈局使用的是div+css
所有的彈出子窗口或者頁夾都是一個div,div可以做頁面的局部刷新
但是css,js資源的引入div需要依賴父頁面
觀察了index.jsp並沒有發現引用的資源
include
在index.jsp最終easyUI的一些特點
1 佈局layout
data-options="region:'west',title:'菜單',split:true"
west:頁面西側
titel:div名稱
split:可否伸縮
2 靜態菜單
<li data-options="attributes:{'url':'/page/item-add'}">新增商品</li>
<li data-options="attributes:{'url':'/page/item-list'}">查詢商品</li>
<li data-options="attributes:{'url':'/page/item-param-list'}">規格參數</li>
3 頁夾
<div id="tabs" class="easyui-tabs">
<div title="首頁" style="padding:20px;">
</div>
</div>
在靜態菜單中選擇一個頁面將會自動填充到div 首頁中
4 新增頁面
選擇按鈕是一個a標籤
<a href="javascript:void(0)" class="easyui-linkbutton selectItemCat">選擇類目</a>
easyUI修飾的a標籤
5 彈出的分類窗口
6 新增商品中的一些data-options屬性
商品標題:data-options="required:true" 必填項
商品賣點:data-options="multiline:true,validType:'length[0,150]'"
multiline:多行輸入
validType:輸入大小範圍
價格:data-options="min:1,max:99999999,precision:2,required:true"
爲什麼價格沒有小數點 而且在價格下還有一個隱藏的
<input type="hidden" name="price"/>
EasyUI的樹
對於樹的數據要求
完成分類樹的展示必須滿足一個條件,返回數據符合
EasyUI的樹結構;EasyUI接收的數據(controller返回的數據)都是
json
EasyUI對數結構的要求
每個節點可以包含以下屬性:
· id: 節點id,它是重要的來加載遠程數據
· text: 節點文本來顯示 //就是name的值
· state: 節點狀態,“open”或“closed”,默認是“open”。當設置爲“closed”,節點有子節點,並將負載從遠程站點 //如果是父節點需要返回closed,如果是子節點需要返回open;
· checked: 顯示選定的節點是否選中。
· attributes: 自定義屬性可以被添加到一個節點
· children: 一個數組節點定義了一些子節點
需要改造pojo ItemCat
構建數據必須體現層級關係
id和parent_id;在state的構建中體現的
頁面的數據請求分2個情況
第一次訪問,初始化訪問,parent_id如何獲取
後續的訪問,id可以獲取
代碼步驟
1 改造pojo ItemCat
添加getText和getState
2 mapper.xml和mapper接口
我們使用排序sql,通用mapper不支持排序
SELECT * FROM tb_item_cat WHERE parent_id=0 ORDER BY sort_order
3 service
4 controller(頁面分析)
頁面分析的步驟
前臺哪裏是發起請求的位置,利用關鍵字來查找對應的js代碼
<a href="javascript:void(0)" class="easyui-linkbutton selectItemCat">選擇類目</a>
其中只有selectItemCat可能是關鍵字
可以使用eclipse中的search功能,file
// 初始化選擇類目組件
initItemCat : function(data){
$(".selectItemCat").each(function(i,e){//i= index 下標,e:element:元素
var _ele = $(e);//把jquery元素轉化成js對象
if(data && data.cid){
_ele.after("<span style='margin-left:10px;'>"+data.cid+"</span>");
}else{
_ele.after("<span style='margin-left:10px;'></span>");}
_ele.unbind('click').click(function(){//unbind解綁已經綁定到當前按鈕的click事件
$("<div>").css({padding:"5px"}).html("<ul>")//設置窗口屬性
.window({
width:'500',
height:"450",
modal:true,
closed:true,
iconCls:'icon-save',
title:'選擇類目',
onOpen : function(){ //當窗口打開後執行
var _win = this;//把當前的窗口編程js對象
$("ul",_win).tree({
url:'/item/cat/list',//三元素之一
animate:true,//easyui的修飾
onClick : function(node){//初始化窗口tree後對不同節點點擊的函數調用
if($(this).tree("isLeaf",node.target)){
// 填寫到cid中
_ele.parent().find("[name=cid]").val(node.id);
_ele.next().text(node.text).attr("cid",node.id);
$(_win).window('close');
if(data && data.fun){
data.fun.call(this,node);}}}});
},
onClose : function(){
$(this).window("destroy");
}
}).window('open');}}
三元素(接口文件)
請求地址'/item/cat/list'
請求參數當前節點id
在controller接收時的名字能隨便寫嗎
當擴展一個封閉的節點,如果節點沒有子節點加載,它將發送節點id的值作爲http請求參數命名爲“id”到服務器上面定義通過URL檢索的子節點。
返回類型:就是查詢的List對應的json數據字符串
商品列表(分頁過程)
2018年1月13日
10:37
表設計
1 商品價格
不是double,double數據類型會降低數據庫執行的效率,電商
的項目以性能最最高條件設計整個架構
利用前臺js,將真實價格*100進行傳遞;
priceView 真實價格;price:計算後的價格傳遞給數據庫
2 圖片
在數據庫中,以字符串存儲,這裏的字符串是圖片的虛擬訪問路徑
最多存儲5張,每張圖片的字符串以逗號分隔開
數據庫能否直接存儲圖片?
可以直接存儲圖片以大字段blog text
京淘中不能使用大字段存儲數據,大字段破壞索引
介紹索引:
本質上索引的存在目的是減少磁盤IO的次數
例子:查字 "李"
找到L的頁碼
找到Li的頁碼
找到李字
這裏提到的拼音法,筆畫法,偏旁部首 稱作索引
B-tree
索引的特點就是有序的
折半查詢
3 status三種正常,下架,刪除
商品列表的開發步驟
1 pojo
2 mapper(看情況)
SELECT * FROM tb_item ORDER BY updated
3 service
4 controller(頁面分析)
觀察item-list中是否有關於商品查詢的關鍵字
<table class="easyui-datagrid" id="itemList" title="商品列表"
data-options="singleSelect:false,collapsible:true,pagination:true,url:'/item/query',method:'get',pageSize:20,toolbar:toolbar">
使用的EasyUI中一個組件datagrid 可以調用data-options屬性中的連接發起ajax請求
獲取請求地址後datagrid組件調用js
/item/query來尋找js調用的代碼
參數無,查詢所有的列表信息
返回值,List的對象的json
如果引入分頁插件,json串中有沒有分頁數據的體現
在京淘中後臺分頁調用EasyUI的組件,引入分頁jar包完成數據封裝
傳遞給EasyUI的數據需要一個固定格式
爲分頁做準備,不能返回給前臺List<Item>
需要EasyUIResult的對象的json字符串
商品列表的分頁
2018年1月13日
11:11
分頁插件
實現分頁的對象PageHelper,
<!-- 分頁插件:com.github.pagehelper爲PageHelper類所在包名 -->
<plugin interceptor="com.github.pagehelper.PageHelper">
<!-- 方言 -->
<property name="dialect" value="mysql" />
<!-- 該參數默認爲false -->
<!-- 設置爲true時,使用RowBounds分頁會進行count查詢,查詢數據總條數 -->
<property name="rowBoundsWithCount" value="true" />
</plugin>
方言:分頁sql語句根據不同的數據庫執行不同數據庫的分頁語句
mysql limit
爲了滿足前臺的數據需求,需要一個分頁的list對象(20條)
還需要當前tb_item表中的總數3098
本質就是執行2條sql
select * from tb_item limit 20
select count(*) from tb_item
rowBoundsWithCount是否開啓總條數查詢
代碼需要修改ItemController
前臺商品列表的其他功能
2018年1月13日
14:31
新增
三元素
$.post("/item/save",$("#itemAddForm").serialize(), function(data){
if(data.status == 200){
$.messager.alert('提示','新增商品成功!');
}});
js代碼中找到jquery的post提交方法
其中有3個參數
第一個參數:請求地址/item/save
第二個參數$("#itemAddForm").serialize():jquery的一個序列化方法,將一個表單內的所有提交標籤序列化成
一個模擬get的字符串 username=xiao&password=123
以這種字符串進行參數的提交
在pojo發生屬性變化時(這種變化是根據需求來的)
serialize的方法自動將表單裏的所有input標籤封裝成key=value進行參數的上傳,當input標籤或者內容結構發生變化時,無需修改前臺代碼
item對象
第三個參數:回單函數,data就是controller的返回數據
需要返回的對象類型,SysReuslt的json字符串
其中status的值代表不同意義;
爲什麼要json字符串
json字符串可以被js代碼直接調用封裝成js對象
拿到三元素可以編寫代碼
討論
try catch語句能否加在當前service中?
在saveItem方法中由於事務的引入不能添加try catch否則
事務失效;但並不帶表有事務的方法永遠不能添加try catch
測試點擊提交
修改(頁面加載數據的過程)
部分數據回顯使用js代碼調用查詢list中的展示數據
有一個部分數據還是需要到後臺查詢數據庫的
請求地址:item/update
請求參數:當前表單的序列化字符串
返回值:SysResult的jsonn
刪除
"/item/delete"
參數:“ids” 也會被springmvc處理,Long[] ids
商品的增刪改查部分完成
商品詳情,ItemDesc 單獨一個表格
圖片上傳
2018年1月13日
16:26
KindEditor
與EasyUI類似都是前臺的富客戶端插件(基於jquery做的)
KindEditor(KE)優勢在於處理圖文並茂的數據
EasyUI無法處理有格式的數據
kindeditor可以展示圖片
KE可以訪問圖片的虛擬地址http://image.jt.com/2018/1/13/126341927319264.jpg;
可以解析html文本信息
圖片上傳
前臺的執行過程
最多上傳5張圖片,當點擊開始上傳時,多張圖片資源將被封裝成數據對象傳遞給Controller,
將本地數據上傳到服務器
controller
1 拿到這個文件名,擴展名,判斷是否合法有效
2 判斷是否是木馬(京淘中判斷木馬的邏輯非常簡單,應該調用第三方插件進行判斷更安全)
3 生成2個路徑;
· 服務器存儲真實路徑
c://jt-upload/*****/****/**.jpg
· KE訪問的虛擬路徑
http://image.jt.com/*****/****/**.jpg
4 圖片的存放目錄計算,上傳圖片非常多,一個文件夾無法有效管理
5 圖片文件的重命名;
6 保存圖片到服務器
7返回對象PicUpdaloadResult
private Integer error=0;,0表示無異常,1代表異常
private String url;//返回給前臺的KE進行回顯工作
private String width;//寬
private String height;//高
重新構建一個專門的上傳Controller
三元素
http://localhost:8082/pic/upload
參數 MultipartFile類型的數據 變量名稱uploadFile
PicUploadResult
當天問題
2018年1月13日
14:27
1
tomcat啓動佔用的端口8081已經被佔用了
解決辦法,找到8081的端口占用進程pid 幹掉
換個端口
2 插入數據失敗
2018-01-13 15:29:03,554 [http-bio-8082-exec-5] [org.springframework.jdbc.support.SQLErrorCodesFactory]-[DEBUG] Looking up default SQLErrorCodes for DataSource [JDBC URL = jdbc:mysql://127.0.0.1:3306/jtdb?useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true, Username = root, partitions = 1, max (per partition) = 150, min (per partition) = 5, idle max age = 30 min, idle test period = 60 min, strategy = DEFAULT]
2018-01-13 15:29:03,561 [http-bio-8082-exec-5] [org.springframework.jdbc.support.SQLErrorCodesFactory]-[WARN] Error while extracting database product name - falling back to empty error codes
org.springframework.jdbc.support.MetaDataAccessException: Error while extracting DatabaseMetaData; nested exception is java.sql.SQLException: Connection is closed!
再service的saveItem方法中初始化數據添加
3 沒有展示新添加的數據
排序使用updated沒有用倒序 desc
===========================================================================
========================================================================
DAY04
知識回顧+問題
2018年1月15日
8:55
回顧
1 商品分類樹
根據EasyUI樹來確定返回數據的結構
返回Json串中{"id":"201","text","電子書刊","state":"closed"}
2 商品列表和新增
EasyUI自定義屬性特點 data-options
參數提交:jquery的ajax的post提交$.post(參數1,參數2,參數3)
參數1:請求地址
參數3:回調函數(data) data就是SysResult的json字符串
參數2:serialize,在post提交請求體中將form當中的所有input序列化成一個模擬get請求的參數字符串
3 商品修改
回顯過程和提交過程
回顯當中使用js提取列表中的數據,對於某一個商品的回顯過程,只需要到後臺查詢部分數據(商品描述)
4 商品刪除
前臺獲取勾選的Long[] ids
5 圖片上傳
前臺使用KE(KindEditor) + flash將圖片數據從客戶端讀取進行上傳
單獨寫PicUploadController
在springmvc 接收的參數類型MultipartFile
判斷後綴,判斷木馬,
生成2個路徑一個存盤路徑,一個是url前臺頁面訪問路徑
問題:
1 圖片上傳中爲什麼做2個路徑?
真實存盤路徑c:/jt-upload
作爲真實路徑將數據(圖片)存放到服務器的位置
url:http://image.jt.com/***/***.jpg
controller返回PicUploadResult
其中4個屬性,error,width,height,url
{"error":"0","width":"100","height":"200","url":"http://image.jt.com/***/***.jpg"}
function(data){
//校驗上傳成功和失敗
data.error;
//展示圖片的大小
data.width;data.height
//KE訪問的圖片虛擬路徑
data.url
}
但是目前階段KE雖然能夠拿到URL,但是無法訪問到真實的圖片展示;url找不到
做完存盤路徑和url的映射就可以了(nginx)
2 爲什麼京淘使用單表設計?表的關聯性能爲什麼低?
何種情況使用單表?何種情況使用關聯?
外鍵關聯性能問題:
· 數據庫需要維護外鍵的內部管理(if語句,用代碼管理)
· 涉及到外鍵的操作增刪改,需要觸發相關的操作去檢查外鍵判斷外鍵,從而不得不消耗額外資源
· 外鍵的存在會導致操作數據庫的死鎖;
根據不同情況採用不同的表設計邏輯
不適合使用外鍵關聯的情況
用戶量大,併發量高,數據庫極其容易成爲整個架構體系中的性能瓶頸,而且開發成本可以較高
例子:互聯網電商項目;和不考慮開發成本的國企項目;
使用外鍵關聯
用戶量少,併發量不高,數據庫性能不會成爲瓶頸,要求開發成本低
例子:傳統行業(企業內部項目,OA,CRM)
屬性注入解耦
2018年1月15日
9:32
需求
對圖片上傳中的強耦合字符串,使用屬性注入來解耦
Properties:自行管理properties文件,使用類加載器獲取資源
京淘中使用架構引入PropertyPlaceHolderConfigurer
底層還是Properties:存儲讀取文件中的數據
REPOSITORY_PATH=c:\\jt-upload
IMAGE_BASE_URL=http://image.jt.com
架構的PropertyPlaceHolderConfigurer:分裝了Property對象,是spring架構支持的一套API,方便在配置xml時就設置文件位置,和讀取數據的其他配置信息;
京淘中的擴展類ExtendedPropertyPlaceholderConfigurer
只擴展了父類沒有的一個方法getProperty,在代碼中可以獲取讀取的數據
情景分析:
擴展類已經在加載後保存了所有的properties文件中的key-value
問題:可以不可以在圖片的controller當中直接注入擴展類,調用擴展類的getProperty方法使用,獲取key-value數據
問題:爲什麼不在controller中直接注入使用
單獨使用擴展類對象中的數據也是耦合
引入僞service對象PropertyService和後處理bean
來解決這種問題;
僞service:不參加業務邏輯的spring加載的bean,註解使用service
利用僞service中的屬性解決編譯器檢查字符串錯誤;
spring創建僞service對象時,2個屬性沒有值;
後處理bean:將擴展類對象中的數據經過bean加載後的後處理過程,將數據傳遞給僞service;利用註解來傳遞
屬性注入流程圖
NGINX
2018年1月15日
10:30
情景分析:
如何構建一個京淘項目後臺的tomcat集羣?
兩種搭建
有沒有一種可能,對於客戶端來講,訪問的服務器地址不變(對於客戶端透明)
NGINX(engin x)
是一個高性能的HTTP和反向代理服務器
上圖展示的代理稱之爲正向代理,代理的是客戶端,對客戶端的訪問處理後交給外網服務器
反向代理與正向代理相反,代理的服務器的響應;
京淘中nginx作用
解決靜態文件的訪問,圖片回顯,將url訪問連接中
image.jt.com替換成nginx所在服務器的真實存盤路徑
c://jt-upload
nginx的動靜分離
負載均衡;
負載:服務器承受的訪問壓力;
均衡:物理均衡和邏輯均衡
權重:權衡訪問的重心,根據服務器性能判斷
session黏着;根據session共享來做的均衡方式
NGINX安裝(windows版本)
環境包中nginx1.9.9
啓動:在原有包中增加了3個.bat文件,作爲windows系統的啓動
停止,重啓
start啓動;
nginx啓動會加載配置文件,conf/nginx.conf
nginx的配置文件
server {//nginx啓動是加載的虛擬機單位
listen 80; //監聽的端口
server_name manage.jt.com; //監聽的域名
location / { //當滿足監聽條件時,location後跟着匹配信息,
開始匹配域名和端口後的內容,
proxy_pass http://127.0.0.1:8081; //域名和端口的替換
也就是訪問的真正服務器,直接拼接後續的訪問路徑
proxy_connect_timeout 600;
proxy_read_timeout 600;}}
根據以上內容,將manage.jt.com/page/index用nginx訪問maven啓動的tomcat
修改hosts文件,manage.jt.com需要和nginx所在服務器地址映射 127.0.0.1
圖片回顯:
server {
listen 80;
server_name image.jt.com;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
location / {
root c:\\jt-upload;}}
補充:幾個簡單的匹配案例location
以 = 開頭表示精確匹配
location = /html{
匹配過程內容
}
/html/ 匹配以html開頭的內容,後續繼續查詢有沒有location匹配的是/html/正則 */d
^~ /html/ 匹配html開頭的內容,一旦匹配上,不在搜索下面的正則匹配
和 /html/abc.html
部署linux系統的京淘
2018年1月15日
11:41
部署結構
使用第一種部署方式,在一臺linux服務器上配置3個tomcat實例
總體步驟
1 鏡像 登錄名密碼是root root
找到解壓文件中的vmx後綴文件
2 上傳tomcat解壓安裝
[root@bogon software]# cd /root/Desktop/
[root@bogon Desktop]# mv apache-tomcat-7.0.55.tar.gz /home/software/
解壓改名
[root@bogon software]# tar -xf apache-tomcat-7.0.55.tar.gz
[root@bogon software]# mv apache-tomcat-7.0.55 t1
3 安裝jdk(略)
4 複製多個tomcat實例
需要修改對應的tomcat文件中的配置文件的端口
t1 8080 70行左右,8009 91行左右,8005 22行
t2 8081,8019,8015
t3 8082,8029,8025
[root@bogon software]# vim t2/conf/server.xml
[root@bogon software]# vim t3/conf/server.xml
啓動tomcat
到bin目錄下找到start.sh
[root@bogon bin]# ./startup.sh
配置文件 conf/server.xml
linux中查看啓動日誌
啓動日誌就在logs文件夾下,catalina.out
使用tail命令查看
繼續啓動t2和t3跟着查看catalina.out
[root@bogon logs]# tail /home/software/t2/logs/catalina.out
[root@bogon logs]# tail /home/software/t3/logs/catalina.out
5 打war包啓動
將manage工程的war包導入到tomcat3個實例中,放到webaps下,ROOT.war tomcat啓動時自動解壓
war包:
在maven工程發佈時,已經完成war的打包,將其拷貝到虛擬機使用即可
檢查tomcat進程,使用
[root@bogon logs]# ps -ef|grep tomcat
根據現實的pid使用kill命令殺掉
[root@bogon logs]# kill 5393
[root@bogon logs]# kill 5365
[root@bogon logs]# kill 5318
將文件修改成ROOT.war
[root@bogon ~]# cd /root/Desktop/
[root@bogon Desktop]# ls
jt-manage.war
[root@bogon Desktop]# mv jt-manage.war ROOT.war
[root@bogon Desktop]#
拷貝到t1,t2,t3的webapps中
[root@bogon Desktop]# cp ROOT.war /home/software/t1/webapps/
[root@bogon Desktop]# cp ROOT.war /home/software/t2/webapps/
[root@bogon Desktop]# cp ROOT.war /home/software/t3/webapps/
[root@bogon Desktop]#
啓動tocmat三個實例
使用tail檢查啓動是否成功
在虛擬機內部的瀏覽器訪問;
爲了可以在外部客戶端訪問虛擬機中3個tomcat,需要設置防火牆
service iptables stop 關閉所有防火牆
檢查防火牆命令
service ip tables status
6 實現ngnix的在3個實例中的跳轉工作
在nginx中配置如下信息
upstream jt1710{ upstream 負載均衡的服務器庫,jt1710自定義名稱
server 192.168.40.170:8081 ;
server 192.168.40.170:8082 ;
server 192.168.40.180:8080 ;}
server {
listen 80;
server_name manage.jt.com;
location / {
proxy_pass http://jt1710;//
從直接訪問本地tocmat變成訪問服務器庫;默認的並排方式排列的服務器就是輪詢
proxy_connect_timeout 600;
proxy_read_timeout 600;}}
修改每個tomcat實例的首頁內容區分
方便查詢負載均衡操作過程
[root@bogon ROOT]# vim /home/software/t1/webapps/ROOT/index.jsp
[root@bogon ROOT]# vim /home/software/t2/webapps/ROOT/index.jsp
[root@bogon ROOT]# vim /home/software/t3/webapps/ROOT/index.jsp
附錄1--nginx配置詳解
2017年12月7日
22:42
Nginx的配置文件nginx.conf配置詳解如下:
user nginx nginx ;
Nginx用戶及組:用戶 組。window下不指定
worker_processes 8;
工作進程:數目。根據硬件調整,通常等於CPU數量或者2倍於CPU。
error_log logs/error.log;
error_log logs/error.log notice;
error_log logs/error.log info;
錯誤日誌:存放路徑。
pid logs/nginx.pid;
pid(進程標識符):存放路徑。
worker_rlimit_nofile 204800;
指定進程可以打開的最大描述符:數目。
這個指令是指當一個nginx進程打開的最多文件描述符數目,理論值應該是最多打開文件數(ulimit -n)與nginx進程數相除,但是nginx分配請求並不是那麼均勻,所以最好與ulimit -n 的值保持一致。
現在在linux 2.6內核下開啓文件打開數爲65535,worker_rlimit_nofile就相應應該填寫65535。
這是因爲nginx調度時分配請求到進程並不是那麼的均衡,所以假如填寫10240,總併發量達到3-4萬時就有進程可能超過10240了,這時會返回502錯誤。
events
{
use epoll;
使用epoll的I/O 模型。linux建議epoll,FreeBSD建議採用kqueue,window下不指定。
補充說明:
與apache相類,nginx針對不同的操作系統,有不同的事件模型
A)標準事件模型
Select、poll屬於標準事件模型,如果當前系統不存在更有效的方法,nginx會選擇select或poll
B)高效事件模型
Kqueue:使用於FreeBSD 4.1+, OpenBSD 2.9+, NetBSD 2.0 和 MacOS X.使用雙處理器的MacOS X系統使用kqueue可能會造成內核崩潰。
Epoll:使用於Linux內核2.6版本及以後的系統。
/dev/poll:使用於Solaris 7 11/99+,HP/UX 11.22+ (eventport),IRIX 6.5.15+ 和 Tru64 UNIX 5.1A+。
Eventport:使用於Solaris 10。 爲了防止出現內核崩潰的問題, 有必要安裝安全補丁。
worker_connections 204800;
沒個工作進程的最大連接數量。根據硬件調整,和前面工作進程配合起來用,儘量大,但是別把cpu跑到100%就行。每個進程允許的最多連接數,理論上每臺nginx服務器的最大連接數爲。worker_processes*worker_connections
keepalive_timeout 60;
keepalive超時時間。
client_header_buffer_size 4k;
客戶端請求頭部的緩衝區大小。這個可以根據你的系統分頁大小來設置,一般一個請求頭的大小不會超過1k,不過由於一般系統分頁都要大於1k,所以這裏設置爲分頁大小。
分頁大小可以用命令getconf PAGESIZE 取得。
[root@web001 ~]# getconf PAGESIZE
4096
但也有client_header_buffer_size超過4k的情況,但是client_header_buffer_size該值必須設置爲“系統分頁大小”的整倍數。
open_file_cache max=65535 inactive=60s;
這個將爲打開文件指定緩存,默認是沒有啓用的,max指定緩存數量,建議和打開文件數一致,inactive是指經過多長時間文件沒被請求後刪除緩存。
open_file_cache_valid 80s;
這個是指多長時間檢查一次緩存的有效信息。
open_file_cache_min_uses 1;
open_file_cache指令中的inactive參數時間內文件的最少使用次數,如果超過這個數字,文件描述符一直是在緩存中打開的,如上例,如果有一個文件在inactive時間內一次沒被使用,它將被移除。
}
##設定http服務器,利用它的反向代理功能提供負載均衡支持
http
{
include mime.types;
設定mime類型,類型由mime.type文件定義
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
log_format log404 '$status [$time_local] $remote_addr $host$request_uri $sent_http_location';
日誌格式設置。
$remote_addr與$http_x_forwarded_for用以記錄客戶端的ip地址;
$remote_user:用來記錄客戶端用戶名稱;
$time_local: 用來記錄訪問時間與時區;
$request: 用來記錄請求的url與http協議;
$status: 用來記錄請求狀態;成功是200,
$body_bytes_sent :記錄發送給客戶端文件主體內容大小;
$http_referer:用來記錄從那個頁面鏈接訪問過來的;
$http_user_agent:記錄客戶瀏覽器的相關信息;
通常web服務器放在反向代理的後面,這樣就不能獲取到客戶的IP地址了,通過$remote_add拿到的IP地址是反向代理服務器的iP地址。反向代理服務器在轉發請求的http頭信息中,可以增加x_forwarded_for信息,用以記錄原有客戶端的IP地址和原來客戶端的請求的服務器地址。
access_log logs/host.access.log main;
access_log logs/host.access.404.log log404;
用了log_format指令設置了日誌格式之後,需要用access_log指令指定日誌文件的存放路徑;
server_names_hash_bucket_size 128;
#保存服務器名字的hash表是由指令server_names_hash_max_size 和server_names_hash_bucket_size所控制的。參數hash bucket size總是等於hash表的大小,並且是一路處理器緩存大小的倍數。在減少了在內存中的存取次數後,使在處理器中加速查找hash表鍵值成爲可能。如果hash bucket size等於一路處理器緩存的大小,那麼在查找鍵的時候,最壞的情況下在內存中查找的次數爲2。第一次是確定存儲單元的地址,第二次是在存儲單元中查找鍵 值。因此,如果Nginx給出需要增大hash max size 或 hash bucket size的提示,那麼首要的是增大前一個參數的大小.
client_header_buffer_size 4k;
客戶端請求頭部的緩衝區大小。這個可以根據你的系統分頁大小來設置,一般一個請求的頭部大小不會超過1k,不過由於一般系統分頁都要大於1k,所以這裏設置爲分頁大小。分頁大小可以用命令getconf PAGESIZE取得。
large_client_header_buffers 8 128k;
客戶請求頭緩衝大小。nginx默認會用client_header_buffer_size這個buffer來讀取header值,如果
header過大,它會使用large_client_header_buffers來讀取。
open_file_cache max=102400 inactive=20s;
這個指令指定緩存是否啓用。
例: open_file_cache max=1000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
open_file_cache_errors
語法:open_file_cache_errors on | off 默認值:open_file_cache_errors off 使用字段:http, server, location 這個指令指定是否在搜索一個文件是記錄cache錯誤.
open_file_cache_min_uses
語法:open_file_cache_min_uses number 默認值:open_file_cache_min_uses 1 使用字段:http, server, location 這個指令指定了在open_file_cache指令無效的參數中一定的時間範圍內可以使用的最小文件數,如果使用更大的值,文件描述符在cache中總是打開狀態.
open_file_cache_valid
語法:open_file_cache_valid time 默認值:open_file_cache_valid 60 使用字段:http, server, location 這個指令指定了何時需要檢查open_file_cache中緩存項目的有效信息.
client_max_body_size 300m;
設定通過nginx上傳文件的大小
sendfile on;
sendfile指令指定 nginx 是否調用sendfile 函數(zero copy 方式)來輸出文件,對於普通應用,必須設爲on。如果用來進行下載等應用磁盤IO重負載應用,可設置爲off,以平衡磁盤與網絡IO處理速度,降低系統uptime。
tcp_nopush on;
此選項允許或禁止使用socke的TCP_CORK的選項,此選項僅在使用sendfile的時候使用
proxy_connect_timeout 90;
後端服務器連接的超時時間_發起握手等候響應超時時間
proxy_read_timeout 180;
連接成功後_等候後端服務器響應時間_其實已經進入後端的排隊之中等候處理(也可以說是後端服務器處理請求的時間)
proxy_send_timeout 180;
後端服務器數據回傳時間_就是在規定時間之內後端服務器必須傳完所有的數據
proxy_buffer_size 256k;
設置從被代理服務器讀取的第一部分應答的緩衝區大小,通常情況下這部分應答中包含一個小的應答頭,默認情況下這個值的大小爲指令proxy_buffers中指定的一個緩衝區的大小,不過可以將其設置爲更小
proxy_buffers 4 256k;
設置用於讀取應答(來自被代理服務器)的緩衝區數目和大小,默認情況也爲分頁大小,根據操作系統的不同可能是4k或者8k
proxy_busy_buffers_size 256k;
proxy_temp_file_write_size 256k;
設置在寫入proxy_temp_path時數據的大小,預防一個工作進程在傳遞文件時阻塞太長
proxy_temp_path /data0/proxy_temp_dir;
proxy_temp_path和proxy_cache_path指定的路徑必須在同一分區
proxy_cache_path /data0/proxy_cache_dir levels=1:2 keys_zone=cache_one:200m inactive=1d max_size=30g;
#設置內存緩存空間大小爲200MB,1天沒有被訪問的內容自動清除,硬盤緩存空間大小爲30GB。
keepalive_timeout 120;
keepalive超時時間。
tcp_nodelay on;
client_body_buffer_size 512k;
如果把它設置爲比較大的數值,例如256k,那麼,無論使用firefox還是IE瀏覽器,來提交任意小於256k的圖片,都很正常。如果註釋該指令,使用默認的client_body_buffer_size設置,也就是操作系統頁面大小的兩倍,8k或者16k,問題就出現了。
無論使用firefox4.0還是IE8.0,提交一個比較大,200k左右的圖片,都返回500 Internal Server Error錯誤
proxy_intercept_errors on;
表示使nginx阻止HTTP應答代碼爲400或者更高的應答。
upstream bakend {
server 127.0.0.1:8027;
server 127.0.0.1:8028;
server 127.0.0.1:8029;
hash $request_uri;
}
nginx的upstream目前支持4種方式的分配
1、輪詢(默認)
每個請求按時間順序逐一分配到不同的後端服務器,如果後端服務器down掉,能自動剔除。
2、weight
指定輪詢機率,weight和訪問比率成正比,用於後端服務器性能不均的情況。
例如:
upstream bakend {
server 192.168.0.14 weight=10;
server 192.168.0.15 weight=10;
}
2、ip_hash
每個請求按訪問ip的hash結果分配,這樣每個訪客固定訪問一個後端服務器,可以解決session的問題。
例如:
upstream bakend {
ip_hash;
server 192.168.0.14:88;
server 192.168.0.15:80;
}
3、fair(第三方)
按後端服務器的響應時間來分配請求,響應時間短的優先分配。
upstream backend {
server server1;
server server2;
fair;
}
4、url_hash(第三方)
按訪問url的hash結果來分配請求,使每個url定向到同一個後端服務器,後端服務器爲緩存時比較有效。
例:在upstream中加入hash語句,server語句中不能寫入weight等其他的參數,hash_method是使用的hash算法
upstream backend {
server squid1:3128;
server squid2:3128;
hash $request_uri;
hash_method crc32;
}
tips:
upstream bakend{#定義負載均衡設備的Ip及設備狀態}{
ip_hash;
server 127.0.0.1:9090 down;
server 127.0.0.1:8080 weight=2;
server 127.0.0.1:6060;
server 127.0.0.1:7070 backup;
}
在需要使用負載均衡的server中增加
proxy_pass http://bakend/;
每個設備的狀態設置爲:
1.down表示單前的server暫時不參與負載
2.weight爲weight越大,負載的權重就越大。
3.max_fails:允許請求失敗的次數默認爲1.當超過最大次數時,返回proxy_next_upstream模塊定義的錯誤
4.fail_timeout:max_fails次失敗後,暫停的時間。
5.backup: 其它所有的非backup機器down或者忙的時候,請求backup機器。所以這臺機器壓力會最輕。
nginx支持同時設置多組的負載均衡,用來給不用的server來使用。
client_body_in_file_only設置爲On 可以講client post過來的數據記錄到文件中用來做debug
client_body_temp_path設置記錄文件的目錄 可以設置最多3層目錄
location對URL進行匹配.可以進行重定向或者進行新的代理 負載均衡
##配置虛擬機
server
{
listen 80;
配置監聽端口
server_name image.***.com;
配置訪問域名
location ~* \.(mp3|exe)$ {
對以“mp3或exe”結尾的地址進行負載均衡
proxy_pass http://img_relay$request_uri;
設置被代理服務器的端口或套接字,以及URL
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
以上三行,目的是將代理服務器收到的用戶的信息傳到真實服務器上
}
location /face {
if ($http_user_agent ~* "xnp") {
rewrite ^(.*)$ http://211.151.188.190:8080/face.jpg redirect;
}
proxy_pass http://img_relay$request_uri;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
error_page 404 502 = @fetch;
}
location @fetch {
access_log /data/logs/face.log log404;
rewrite ^(.*)$ http://211.151.188.190:8080/face.jpg redirect;
}
location /image {
if ($http_user_agent ~* "xnp") {
rewrite ^(.*)$ http://211.151.188.190:8080/face.jpg redirect;
}
proxy_pass http://img_relay$request_uri;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
error_page 404 502 = @fetch;
}
location @fetch {
access_log /data/logs/image.log log404;
rewrite ^(.*)$ http://211.151.188.190:8080/face.jpg redirect;
}
}
##其他舉例
server
{
listen 80;
server_name *.***.com *.***.cn;
location ~* \.(mp3|exe)$ {
proxy_pass http://img_relay$request_uri;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location / {
if ($http_user_agent ~* "xnp") {
rewrite ^(.*)$ http://i1.***img.com/help/noimg.gif redirect;
}
proxy_pass http://img_relay$request_uri;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#error_page 404 http://i1.***img.com/help/noimg.gif;
error_page 404 502 = @fetch;
}
location @fetch {
access_log /data/logs/baijiaqi.log log404;
rewrite ^(.*)$ http://i1.***img.com/help/noimg.gif redirect;
}
}
server
{
listen 80;
server_name *.***img.com;
location ~* \.(mp3|exe)$ {
proxy_pass http://img_relay$request_uri;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location / {
if ($http_user_agent ~* "xnp") {
rewrite ^(.*)$ http://i1.***img.com/help/noimg.gif;
}
proxy_pass http://img_relay$request_uri;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#error_page 404 http://i1.***img.com/help/noimg.gif;
error_page 404 = @fetch;
}
#access_log off;
location @fetch {
access_log /data/logs/baijiaqi.log log404;
rewrite ^(.*)$ http://i1.***img.com/help/noimg.gif redirect;
}
}
server
{
listen 8080;
server_name ngx-ha.***img.com;
location / {
stub_status on;
access_log off;
}
}
server {
listen 80;
server_name imgsrc1.***.net;
root html;
}
server {
listen 80;
server_name ***.com w.***.com;
# access_log /usr/local/nginx/logs/access_log main;
location / {
rewrite ^(.*)$ http://www.***.com/ ;
}
}
server {
listen 80;
server_name *******.com w.*******.com;
# access_log /usr/local/nginx/logs/access_log main;
location / {
rewrite ^(.*)$ http://www.*******.com/;
}
}
server {
listen 80;
server_name ******.com;
# access_log /usr/local/nginx/logs/access_log main;
location / {
rewrite ^(.*)$ http://www.******.com/;
}
}
location /NginxStatus {
stub_status on;
access_log on;
auth_basic "NginxStatus";
auth_basic_user_file conf/htpasswd;
}
#設定查看Nginx狀態的地址
location ~ /\.ht {
deny all;
}
#禁止訪問.htxxx文件
}
註釋:變量
Ngx_http_core_module模塊支持內置變量,他們的名字和apache的內置變量是一致的。
首先是說明客戶請求title中的行,例如$http_user_agent,$http_cookie等等。
此外還有其它的一些變量
$args此變量與請求行中的參數相等
$content_length等於請求行的“Content_Length”的值。
$content_type等同與請求頭部的”Content_Type”的值
$document_root等同於當前請求的root指令指定的值
$document_uri與$uri一樣
$host與請求頭部中“Host”行指定的值或是request到達的server的名字(沒有Host行)一樣
$limit_rate允許限制的連接速率
$request_method等同於request的method,通常是“GET”或“POST”
$remote_addr客戶端ip
$remote_port客戶端port
$remote_user等同於用戶名,由ngx_http_auth_basic_module認證
$request_filename當前請求的文件的路徑名,由root或alias和URI request組合而成
$request_body_file
$request_uri含有參數的完整的初始URI
$query_string與$args一樣
$sheeme http模式(http,https)盡在要求是評估例如
Rewrite ^(.+)$ $sheme://example.com$; Redirect;
$server_protocol等同於request的協議,使用“HTTP/或“HTTP/
$server_addr request到達的server的ip,一般獲得此變量的值的目的是進行系統調用。爲了避免系統調用,有必要在listen指令中指明ip,並使用bind參數。
$server_name請求到達的服務器名
$server_port請求到達的服務器的端口號
$uri等同於當前request中的URI,可不同於初始值,例如內部重定向時或使用index
附錄2--location匹配規則
2018年1月15日
12:59
· 已=開頭表示精確匹配
如 A 中只匹配根目錄結尾的請求,後面不能帶任何字符串。
· ^~ 匹配普通字符,不是正則匹配不能用正則表達式
· ~ 開頭表示區分大小寫的正則匹配;
· ~* 開頭表示不區分大小寫的正則匹配
· / 通用匹配, 如果沒有其它匹配,任何請求都會匹配到
location = / {
# 精確匹配 / ,主機名後面不能帶任何字符串
[ configuration A ]
}
location / {
# 因爲所有的地址都以 / 開頭,所以這條規則將匹配到所有請求
# 但是正則和最長字符串會優先匹配
[ configuration B ]
}
location /documents/ {
# 匹配任何以 /documents/ 開頭的地址,優先級比較低 [ configuration C ]
}
location ~ /documents/Abc {
# 匹配任何以 /documents/ 開頭的地址,匹配符合以後,還要繼續往下搜索
# 只有後面的正則表達式沒有匹配到時,這一條纔會採用這一條
[ configuration CC ]
}
location ^~ /images/ {
# 匹配任何以 /images/ 開頭的地址,匹配符合以後,停止往下搜索正則,採用這一條。
[ configuration D ]
}
location ~* \.(gif|jpg|jpeg)$ {
# 匹配所有以 gif,jpg或jpeg 結尾的請求
# 然而,所有請求 /images/ 下的圖片會被 config D 處理,因爲 ^~ 到達不了這一條正則
[ configuration E ]
}
location /images/ {
# 字符匹配到 /images/,繼續往下,會發現 ^~ 存在
[ configuration F ]
}
location ~* /js/.*/\.js
當前問題
2018年1月15日
15:55
1 tomcat啓動後沒法訪問manage後臺
原因:原有的ROOT下的文件和拷貝的ROOT.war衝突
解決辦法:停掉所有的tomcat
調用各自的bin下的shutdown
然後將webapps中所有文件刪除清空
[root@bogon webapps]# rm -rf /home/software/t1/webapps/*
[root@bogon webapps]# rm -rf /home/software/t2/webapps/*
[root@bogon webapps]# rm -rf /home/software/t3/webapps/*
在把ROOT.war傳入webapps中,啓動tomcat
2問題:在啓動tomcat發現不成功,tail日誌文件顯示尋找jdk1.7文件找不到
原因:/etc/profile 默認配置的1.7
解決:配置好jdk1.8然後再每次啓動tomcat時,
source /etc/profile
JAVA_HOME=/home/software/jdk1.8 /不要丟
PATH=$PATH:./:$JAVA_HOME/bin
export PATH JAVA_HOME