JT项目-2

DAY03

知识回顾

2018113

8:58

 

1 parent和common

2 搭建了后台系统

3 商品分类的全部内容展示(测试)

京淘中的表格设计

京淘中的所有表格都是单表设计

没有外键关联;

提高系统的性能;

涉及到多表的关系,是代码

4 后台的页面跳转

restFul传参

 

 

商品分类树的展示

2018113

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数据字符串

 

 

 

 

商品列表(分页过程)

2018113

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字符串

 

 

商品列表的分页

2018113

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

 

 

前台商品列表的其他功能

2018113

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

请求参数:当前表单的序列化字符串

返回值:SysResultjsonn

 

删除

"/item/delete"

参数:“ids” 也会被springmvc处理,Long[] ids

 

商品的增删改查部分完成

商品详情,ItemDesc 单独一个表格

 

 

图片上传

2018113

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

 

 

当天问题

2018113

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

 

知识回顾+问题

2018115

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)

 

 

属性注入解耦

2018115

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

2018115

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系统的京淘

2018115

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配置详解

2017127

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内核下开启文件打开数为65535worker_rlimit_nofile就相应应该填写65535

这是因为nginx调度时分配请求到进程并不是那么的均衡,所以假如填写10240,总并发量达到3-4万时就有进程可能超过10240了,这时会返回502错误。

 

events

{

use epoll;

使用epollI/O 模型。linux建议epollFreeBSD建议采用kqueuewindow下不指定。

补充说明:

apache相类,nginx针对不同的操作系统,有不同的事件模型

A)标准事件模型

Selectpoll属于标准事件模型,如果当前系统不存在更有效的方法,nginx会选择selectpoll

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 用来记录请求的urlhttp协议;

$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;

此选项允许或禁止使用sockeTCP_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_pathproxy_cache_path指定的路径必须在同一分区

 

proxy_cache_path /data0/proxy_cache_dir levels=1:2 keys_zone=cache_one:200m inactive=1d max_size=30g;

#设置内存缓存空间大小为200MB1天没有被访问的内容自动清除,硬盘缓存空间大小为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;

}

nginxupstream目前支持4种方式的分配

1、轮询(默认)

每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。

2weight

指定轮询机率,weight和访问比率成正比,用于后端服务器性能不均的情况。

例如:

upstream bakend {

server 192.168.0.14 weight=10;

server 192.168.0.15 weight=10;

}

2ip_hash

每个请求按访问iphash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。

例如:

upstream bakend {

ip_hash;

server 192.168.0.14:88;

server 192.168.0.15:80;

}

3fair(第三方)

按后端服务器的响应时间来分配请求,响应时间短的优先分配。

upstream backend {

server server1;

server server2;

fair;

}

4url_hash(第三方)

按访问urlhash结果来分配请求,使每个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.weightweight越大,负载的权重就越大。

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层目录

locationURL进行匹配.可以进行重定向或者进行新的代理 负载均衡

 

 

##配置虚拟机

server

{

listen 80;

配置监听端口

 

server_name image.***.com;

配置访问域名

 

location ~* \.(mp3|exe)$ {

对以“mp3exe”结尾的地址进行负载均衡

 

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等同于requestmethod,通常是“GET”“POST”

$remote_addr客户端ip

$remote_port客户端port

$remote_user等同于用户名,由ngx_http_auth_basic_module认证

$request_filename当前请求的文件的路径名,由rootaliasURI 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到达的serverip,一般获得此变量的值的目的是进行系统调用。为了避免系统调用,有必要在listen指令中指明ip,并使用bind参数。

$server_name请求到达的服务器名

$server_port请求到达的服务器的端口号

$uri等同于当前request中的URI,可不同于初始值,例如内部重定向时或使用index

 

 

 

附录2--location匹配规则

2018115

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

 

 

 

 

 

当前问题

2018115

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

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章