实验环境:rhel6.5 seliunx and iptables disabled
nginx 1.6.2
mysql 5.5.12
php 5.4.36
memcached 1.4.4
server1 172.25.12.1 tomcat nginx mysql php memcached
server2 172.25.12.2 tomcat memcached
server3 172.25.12.3 tomcat
server4 172.25.12.4 tomcat
一.nginx:
1.1安装
安装依赖性:yum install gcc openssl-devel pcre-devel -y
解压:tar zxf nginx-1.6.2.tar.gz
编译前稍作改动:
掩盖版本号,为了安全:curl -I IP/hostname 可查看服务器信息
root@server1core]# pwd
/pags/nginx-1.6.2/src/core
[root@server1core]# vim nginx.h
#definenginx_version 1006002
#defineNGINX_VERSION "1.6.2"
#defineNGINX_VER "nginx/" NGINX_VERSION
改为
#definenginx_version 1006002
#defineNGINX_VERSION "1.6.2"
#defineNGINX_VER "nginx/"
关闭gcc的debug功能,这样编译出来的内容会更小
[root@server1cc]# pwd
/pags/nginx-1.6.2/auto/cc
[root@server1cc]# vim gcc
# debug
CFLAGS="$CFLAGS-g"
改为:
# debug
#CFLAGS="$CFLAGS -g"
编译安装:
./configure--prefix=/usr/local/lnmp/nginx --with-http_ssl_module --with-http_stub_status_module
make && make install
1.2修改配置文件,加以优化
[root@server1nginx]# useradd -M -s /sbin/nologin nginx #增加nginx用户,以此身份运行
[root@server1nginx]# pwd
/usr/local/lnmp/nginx
[root@server1nginx]# vim conf/nginx.conf
user nginx; #以此身份运行
worker_processes 2; #默认启动几个进程
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
use epoll; #高效方法,用于Linux内核2.6以后版本;
worker_connections 1024;
}
软连命令到/usr/sbin 方便使用;或者写在~/.bash_profile下;source
[root@server1nginx]# pwd
/usr/local/lnmp/nginx
ln -s /usr/local/lnmp/nginx/sbin/nginx /usr/sbin/ #一定要写绝对路径
1.3检测语法;启动nginx;
[root@server1lnmp]# nginx -t
nginx: theconfiguration file /usr/local/lnmp/nginx/conf/nginx.conf syntax is ok
nginx: configurationfile /usr/local/lnmp/nginx/conf/nginx.conf test is successful
[root@server1lnmp]# nginx
[root@server1lnmp]# netstat -anltp | grep 80
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 3595/nginx
测试:
[root@server1html]# pwd
/usr/local/lnmp/nginx/html
[root@server1html]# echo "test nginx" > index.html
[root@foundation12~]# hostname
foundation12.ilt.example.com
[root@foundation12~]# curl 172.25.12.1
test nginx 成功
1.4查看nginx处理状态:
[root@server1conf]# vim nginx.conf
# redirect server error pages to thestatic page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
location /status {
stub_status on;
}
# proxy the PHP scripts to Apachelistening on 127.0.0.1:80
[root@server1conf]# nginx -s reload
在浏览器中输入http://172.25.12.1/status
可以看到:
Active connections: 1
server accepts handled requests
5 5 32
Reading: 0 Writing: 1 Waiting: 0
1.5配置https
生成证书: cd /etc/pki/tls/certs
[root@server1 certs]# make wxl_nginx.pem
umask 77 ; \
...................
Country Name (2 letter code) [XX]:cn
State or Province Name (full name) []:shaxi
Locality Name (eg, city) [Default City]:xi'an
Organization Name (eg, company) [Default Company Ltd]:Linux-lover
Organizational Unit Name (eg, section) []:Linux-lovers
Common Name (eg, your name or your server's hostname)[]:server1.example.com
Email Address []:[email protected]
[root@server1 certs]# mv wxl_nginx.pem /usr/local/lnmp/nginx/conf/
[root@server1 conf]# vim nginx.conf
server {
listen 443 ssl;
server_name server1.example.com;
ssl_certificate wxl_nginx.pem;
ssl_certificate_key wxl_nginx.pem;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
root html;
index index.html index.htm;
}
}
nginx -s reload
浏览器输入https://172.25.12.1/ 验证
1.6搭建虚拟主机:
# location / {
# root html;
# index index.html index.htm;
# }
#}
server {
listen 80;
server_name www.linux-lover.com; #在主机中做好解析
location / {
index index.html;
root/usr/local/lnmp/nginx/vhost/linux-lover;
}
}
#HTTPS server
#
[root@server1 nginx]# ls -Rvhost/
vhost/:
linux-lover
vhost/linux-lover:
index.html
1.7用nginx实现负载均衡
定义http {
include mime.types;
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"';
upstream blance {
server172.25.12.2:80 weight=2; #添加权重。
server172.25.12.3:80;
}
#access_log logs/access.log main;
#使用上面定义的负载均衡
server {
listen 80;
server_name www.loadblance.com;
location / {
proxy_pass http://blance;
}
}
1.8使用sticky模块实现session粘滞
重新编译 ./configure --prefix=/usr/local/lnmp/nginx --with-http_ssl_modul --with-http_stub_status_module --add-module=/usr/local/lnmp/nginx/nginx-sticky-module-1.0 #添加sticky模块,直接加绝对路径即可
make && make install
注意此字段表示成功加进sticky 模板
adding module in /usr/local/lnmp/nginx/nginx-sticky-module-1.0/
+ ngx_http_sticky_module wasconfigured
可以发现之前的配置文件并未改变;
注意加sticky模板就不能加权重了;
nginx: [emerg] invalid parameter"weight=2" in /usr/local/lnmp/nginx/conf/nginx.conf:27
upstream blance {
sticky;
server172.25.12.2:80;
server172.25.12.3:80;
}
效果就是,对于同一ip来源,让其访问它之前一直访问的主机;而当其中一节点down之后nginx会调度其访问online的节点;说明nginx具备健康检查功能;
二mysql安装配置
2.1安装:
安装之前移除系统已经安装的数据库;
解决依赖性: yum install -y gcc gcc-c++ make ncurses-devel bison openssl-devel zlib-devel cmake
[[email protected]]# cmake -DCMAKE_INSTALL_PREFIX=/usr/local/lnmp/mysql\
> -DMYSQL_DATADIR=/usr/local/lnmp/mysql/data \#数据库存放目录
> -DMYSQL_UNIX_ADDR=/usr/local/lnmp/mysql/data/mysql.sock \ #套接字文件位置
> -DWITH_MYISAM_STORAGE_ENGINE=1 \
> -DWITH_INNOBASE_STORAGE_ENGINE=1 \
> -DWITH_ARCHIVE_STORAGE_ENGINE=1 \
> -DWITH_BLACKHOLE_STORAGE_ENGINE=1 \
> -DWITH_PARTITION_STORAGE_ENGINE=1 \
> -DDEFAULT_CHARSET=utf8 \ #使用 utf8 字符
>-DDEFAULT_COLLATION=utf8_general_ci \ #校验字符
>-DEXTRA_CHARSETS=all
make && make install
重新编译时,需要清除旧的对象文件和缓存信息
make clean
rm -f CmakeCache.txt
2.2初始化数据库
为了方便使用命令:在~/.bash_profile声明mysql路径;
# User specific environment and startup programs
PATH=$PATH:$HOME/bin:/usr/local/lnmp/mysql/bin
source ~/.bash_profile #使之生效
建立mysql用户:useradd -M -s /sbin/nologin mysql
根据主机内存复制 mysql 配置文件;
[root@server1 support-files]# pwd
/usr/local/lnmp/mysql/support-files
cp my-medium.cnf /etc/my.cnf #之前的最好备份下
初始化数据库
chown -Rmysql.mysql .
scripts/mysql_install_db --user=mysql--basedir=/usr/local/mysql --datadir=/usr/local/mysql/data
chown -R root .
chown -Rmysql.mysql data
cpsupport-files/mysql.server /etc/init.d/mysqld
2.3启动;设秘密
[root@server1 mysql]# /etc/init.d/mysqld start
Starting MySQL.. SUCCESS
[root@server1 support-files]#mysql_secure_installation
三.php安装配置
3.1安装mcrypt(加密扩展)
3.1.1安装libmycrypt
tar jxf libmcrypt-2.5.8.tar.bz2
cdlibmcrypt-2.5.8
./configure --prefix=/usr/local/lnmp/php/modules/libmcrypt
make && make install
cd libltdl/
./configure--prefix=/usr/local/lnmp/php/modules/libmcrypt/ --enable-ltdl-install
添加系统动态连接库:
vim/etc/ld.so.conf
includeld.so.conf.d/*.conf
/usr/local/lnmp/php/module/libmcrypt/lib/
刷新;查看
ldconfig -v | grep libmcrypt
3.1.2安装mhash
tar jxf mhash-0.9.9.9.tar.bz2
cd mhash-0.9.9.9
./configure--prefix=/usr/local/lnmp/php/modules/mhash
make && make install
vim /etc/ld.so.conf
include ld.so.conf.d/*.conf
/usr/local/lnmp/php/module/libmcrypt/lib/
/usr/local/lnmp/php/modules/mhash/lib/
ldconfig -v | grep mhash
软链到系统能查找的库里
ln -s /usr/local/lnmp/php/module/mhash/lib/* /usr/local/lib/
ln -s /usr/local/lnmp/php/module/mhash/include/* /usr/local/include/
3.1.3安装mcrypt
./configure --prefix=/usr/local/lnmp/php/modules/mcrypt --with-libmcrypt-prefix=/usr/local/lnmp/php/modules/libmcrypt/
也可以直接安装在系统的库里面方便查找
3.2安装php
./configure--prefix=/usr/local/lnmp/php/ --with-config-file-path=/usr/local/lnmp/php/etc--with-mysql=/usr/local/lnmp/mysql/ --with-mysqli=/usr/local/lnmp/mysql/bin/mysql_config --with-openssl-with-gd --with-zlib --with-curl --enable-bcmath --with-libxml-dir --with-png-dir --with-jpeg-dir--with-freetype-dir --without-pear --with-gettext --with-gmp --enable-inline-optimization --enable-soap --enable-ftp --enable-sockets--enable-mbstring --enable-fpm --with-fpm-user=nginx --with-fpm-group=nginx--with-mcrypt=/usr/local/lnmp/php/modules/libmcrypt/ --with-mhash
make && make install
3.3PHP和nginx整合
创建三个文件:
[root@server1 php-5.4.36]# pwd
/pags/php-5.4.36
配置文件:cp php.ini-production /usr/local/lnmp/php/etc/php.ini
启动脚本: cpsapi/fpm/init.d.php-fpm /etc/init.d/fpm
chmod +x /etc/init.d/fpm
fpm配置文件: cpphp-fpm.conf.default php-fpm.conf
启动php /etc/init.d/fpm start
修改nginx配置,测试php
location ~ \.php$ {
root html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
#fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
include fastcgi.conf;
}
写入测试文件cat htmls/index.php
<?php
phpinfo()
?>
nginx -s reload
修改php的时间;不然nginx日志会有警告:
vim/usr/local/lnmp/php/etc/php.ini
[Date]
; Defines thedefault timezone used by the date functions
;http://php.net/date.timezone
date.timezone =Asia/Shanghai
四.lnmp平台简单测试:搭建论坛
unzip Discuz_X3.2_SC_UTF8.zip -d /usr/local/lnmp/nginx/html/
只有upload有用;改名bbs mv upload/ bbs/
chmod 777 config/ -R
chmod 777 data/ uc_* -R
浏览器输入http://172.25.12.1/bbs/install进行安装;
mysql要开启
修改nginx配置文件:
location / {
root html;
index index.html index.htm index.php;
}
五.添加memcache模块
PHP 扩展的 Memcache 实际上是连接 Memcache 的方式
为了方便使用php有关命令:
vim ~/.bash_profile
PATH=$PATH:$HOME/bin:/usr/local/lnmp/mysql/bin:/usr/local/lnmp/php/bin
source ~/.bash_profile
安装php扩展memcache:tar zxf memcache-2.2.5.tgz;
生成configure文件 [root@server1 memcache-2.2.5]# phpize
编译安装 ./configure --prefix=/usr/local/lnmp/php/modules/memcache --with-php-config=/usr/local/lnmp/php/bin/php-config
[root@server1 memcache-2.2.5]#make && make install
Installing shared extensions: /usr/local/lnmp/php/lib/php/extensions/no-debug-non-zts-20100525/
检测:ll /usr/local/lnmp/php/lib/php/extensions/no-debug-non-zts-20100525/
-rwxr-xr-x 1 root root 259040 Apr 3 08:03 memcache.so
使php加载该模块
[root@server1etc]# pwd
/usr/local/lnmp/php/etc
[root@server1etc]# vim php.ini
; ... or under UNIX:
;
; extension=msql.so
extension=memcache.so
重载生效:/etc/init.d/fpm relaod
检测是否加入:
浏览器输入 http://172.25.12.1/index.php 查看是否有memcache模板
而数据真正缓存在memcached服务端当中,上面所做的只是让php连接进memcache,使用它。所以下面真正安装memcache。
安装memcached软件:yum install memcached -y
按照生产环境修改配置文件:vim /etc/sysconfig/memcached
PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="64"
OPTIONS="
启动服务:/etc/init.d/memcached restart
pwd /root/memcache-2.2.5
cp memcache.php example.php /usr/local/lnmp/nginx/html/
vim /usr/local/lnmp/nginx/html/memcache.php
$VERSION='$Id: memcache.php,v 1.2 2008/09/11 19:21:06 mikl Exp $';
define('ADMIN_USERNAME','wxl'); // Admin Username
define('ADMIN_PASSWORD','redhat'); // Admin Password
define('DATE_FORMAT','Y/m/d H:i:s');
define('GRAPH_SIZE',200);
define('MAX_ITEM_DUMP',50);
$MEMCACHE_SERVERS[] = '172.25.12.1:11211';// add more as an array #memcache缓存服务器地址
$MEMCACHE_SERVERS[] = '172.25.12.2:11211';// add more as an array
用telnet测试下memcache
telnet localhost 11211
stats
使用测试文件测试:
[root@server1 memcache-2.2.5]# cat /usr/local/lnmp/nginx/html/test.php
<?php
$memcache = new Memcache;
$memcache->connect('172.25.12.2',11211) or die ("Could not connect");
$version = $memcache->getVersion();
echo "Server's version: ".$version."\n";
$tmp_object = new stdClass;
$tmp_object->str_attr = 'test';
$tmp_object->int_attr = 123;
$memcache->set('key', $tmp_object, false, 10) or die ("Failedto save data at the
server");
echo "Store data in the cache (data will expire in 10seconds)\n";
$get_result = $memcache->get('key');
echo "Data from the cache:\n";
var_dump($get_result);
?>
浏览器访问 http://172.25.12.1/test.php不断刷新
访问http://172.25.12.1/memcache.php 检测么么擦车命中率
六.搭建jsp平台
6.1搭建java运行平台:
下载安装;运行 chmod +x jdk-6u32-linux-x64.bin
sh jdk-6u32-linux-x64.bin
之后会生成一个包 mv jdk1.6.0_32/ /usr/local/lnmp/jdk
修改环境变量 : vim /etc/profile
unset -f pathmunge
export JAVA_HOME=/usr/local/lnmp/jdk
export CLASSPATH=.:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
export PATH=$PATH:$JAVA_HOME/bin
source /etc/profile
检测:
[root@server1 ~]# cat test.java
public class test
{
public staticvoid main(String[] args)
{
System.out.println("testjava");
}
}
编译:javactest.java
运行:[root@server1 ~]# java test #后面不接什么。自动补齐
test java
6.2安装tomcat:
tar zxf apache-tomcat-7.0.37.tar.gz
mvapache-tomcat-7.0.37 /usr/local/lnmp/tomcat
pwd /usr/local/lnmp/tomcat/
启动: cd bin/ ; ./startup.sh
检测:ss -antpl | grep 8080
浏览访问 http://172.25.12.1:8080/
6.3把tomact部署在nginx的后端
tomcat的端口是8080 nginx的端口是80 用户自己是不会输入端口号的。所以请求先到 达nginx,nginx再交给tomacat
创建测试文件:[root@server1 ROOT]# cattest.jsp
Time is : <%= new java.util.Date()
nginx配置文件:
location ~ \.jsp$ {
proxy_pass http://127.0.0.1:8080;
}
6.4 tomcat和nginx发布目录统一起来:
pwd /usr/local/lnmp/tomcat
vimconf/server.xml
改为 <Hostname="localhost" appBase="/usr/local/lnmp/nginx/html"
unpackWARs="true"autoDeploy="true">
<Context path=""docBase="" debug="0"/>
重启tomcat
./bin/shutdown.sh
./bin/startup.sh
测试:把test.jsp 移动到/usr/local/lnmp/nginx/html;
6.5用nginx实现tomcat后端的负载均衡
用server1和server2 测试;同步server1的配置到sever2
scp -r tomcat/ jdk/ 172.25.12.2:/usr/local/lnmp/
scp /etc/profile 172.25.12.2:/etc/profile
在server2上:source /etc/profile;
因为之前在server1上的tomcat默认目录被改过,现在server2上没有之前的目录;所以改过来:
vim conf/server.xml
<Hostname="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<!--Context path=""docBase="" debug="0"/-->
./bin/startup.sh
scp测试文件:scp test.jsp 172.25.12.2:/usr/local/lnmp/webapps/ROOT
在server1. server2 上的测试文件应做相应的改动;便于负载均衡测试。
配置server1 上nginx
#tomcat loadblance
upstream tomcat {
server 172.25.12.1:8080;
server 172.25.12.2:8080;
}
# location ~ \.jsp$ {
# proxy_pass http://127.0.0.1:8080;
# }
#
location ~ \.jsp$ {
proxy_pass http://tomcat;
}
6.6使用memcached保持session会话
为什么要保持session会话;
会话保持是指在负载均衡器上有一种机制,在作负载均衡的同时,还保证同一用户相关连的访问请求会被分配到同一台服务器上;
说明:
如果有一个用户访问请求被分配到服务器A,并且在服务器A登录了,并且在很短的时间,这个用户又发出了一个请求,如果没有会话保持功能的话,这个用户的 请求很有可能会被分配到服务器B去,这个时候在 服务器B上是没有登录的,所以你要重新登录,但是用户并不知道自己的请求被分配到了哪里,用户的感觉就是登录了,怎么又要登录,用户体验很不好。
还有你在淘宝上面买东西,从登录->拍得东西->添加地址->付款,这是一个一系 列的过程,应当由一台服务器完成,而不能被负载均衡器分配到不同的服务器上。
会话保持都会有时间的限制(映射到固定某一台的服务器除外,如:ip_hash),各 种负载均衡工具都会提供这种会话保持时间的设置,LVS,apache等。连php语言都提供了会话保持时间的设定 session.gc_maxlifetime
web集群时session同步的3种方法:
1.利用cookie同步session
session是文件的形式存放在服务器端的,cookie是文件的形式存在客户端的。当客户端浏览器向某个站点第一次发送请求的时候,WEB服务器这个时候,会判断是否是第一次请求,如果确定是第一次,那么web服务器会自己生成一个Session_Id,保存到内存中。并且在返回响应头(Response Header)的时候,会把这个Session_Id带回客户端(如浏览器),这时候浏览器接收到sessionId后,会把它保存在客户端cookie。第二次请求站点的时候,会把Session_Id封装到request中去。这样服务器端就能判断这个是已建立的会话还是新的会话。怎么实现同步呢?方法很简单,就是把用户访问页面产生的session放到cookie里面,就是以cookie为中转站。你访问web服务器A,产生了session把它放到cookie里面了,你访问被分配到web服务器B,这个时候web服务器B先判断服务器有没有这个session,如果没有,在去看看客户端的cookie里面有没有这个session,如果也没有,说明session真的不存,如果cookie里面有,就把cookie里面的sessoin同步到web服务器B,这样就可以实现session的同步了。
说明:这种方法实现起来简单,方便,也不会加大数据库的负担,但是如果客户端把cookie禁掉了的话,那么session就无从同步了,这样会给网站带来损失;cookie的安全性不高,虽然它已经加了密,但是还是可以伪造的;
2.利用memcache同步session
memcache可以做分布式,如果没有这功能,他也不能用来做session同步。他可以把 web服务器中的内存组合起来,成为一个"内存池",不管是哪个服务器产生的sessoin都可以放到这个"内存池"中,其他的都可以使用。
优点:以这种方式来同步session,不会加大数据库的负担,并且安全性比用cookie大 大的提高,把session放到内存里面,比从文件中读取要快很多。
缺点:memcache把内存分成很多种规格的存储块,有块就有大小,这种方式也就决定 了,memcache不能完全利用内存,会产生内存碎片,如果存储块不足,还会产生内存溢出。
3.利用数据库同步session:影响系统性能,不推荐使用;
6.6.1创建测试网页:
[root@server1 html]# cat test.jsp
<%@page contentType="text/html; charset=GBK" %>
<%@ page import="java.util.*" %>
<html><head><title>Cluster AppTest</title></head>
<body>
Server Info:
<%
out.println(request.getLocalAddr() + " : " +request.getLocalPort()+"<br>");%>
<%
out.println("<br> ID " +session.getId()+"<br>");
String dataName = request.getParameter("dataName");
if (dataName != null && dataName.length() > 0) {
String dataValue = request.getParameter("dataValue");
session.setAttribute(dataName, dataValue);
}
out.print("<b>Session list</b>");
Enumeration e = session.getAttributeNames();
while (e.hasMoreElements()) {
String name = (String)e.nextElement();
String value = session.getAttribute(name).toString();
out.println( name + " = " + value+"<br>");
System.out.println( name + " = " + value);
}
%>
<form action="test.jsp" method="POST">
name:<input type=text size=20 name="dataName">
<br>
key:<input type=text size=20 name="dataValue">
<br>
<input type=submit>
</form>
</body>
</html>
6.6.2配置msm(memcached-session-manager)创建交叉存储,避免但点故障;
原理:
Tomcat-1 (T1) 将 session 存储在 memcached-2 (T2)上。只有当 M2 不可用时,T1 才将 session存储在memcached-1 上(M1 是 T1 failoverNode)。使用这种配置的好处是,当 T1 和 M1 同时崩溃时也不会丢失 session 会话,避免单点故障。
nginx加入sticky;粘滞会话
配置tomcat使用msm
<ManagerclassName="de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes="n1:172.25.12.1:11211,n2:172.25.12.2:11211"
failoverNodes="n1"#server2上改成n2
requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
/>
</Context>
重启tomcat: ./bin/shutdown.sh; ./bin/startup.sh
日志文件中出现下面的内容代表memcache成功:
INFO:MemcachedSessionService finished initialization, sticky true, operation timeout1000, with node ids [n2] andfailover node ids [n1]
效果是即使server1的tomcat down掉或者memcached down掉 或者都down掉。会话都能保持;
另外测试如果加入4个节点tomcat。tomcatdown掉会话依然正常;
server3:
<ManagerclassName="de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes="n1:172.25.12.1:11211,n2:172.25.12.2:11211"
failoverNodes="n1" #server4改成n2
requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
/>