实验目标:

1.反向代理服务器将用户请求负载均衡到后端tomcat节点;

2.配置基于nginx的负载均衡,实现会话绑定;

3.配置基于mod_jk的负载均衡,实现会话绑定;

4.基于mod_proxy实现负载均衡,实现会话绑定;

网络架构图:

网络主机规划表:

实验步骤:

前提配置:

1、tom1和tom2节点时间必须同步;

建议使用ntp协议进行;

参考博客:http://sohudrgon.blog.51cto.com/3088108/1598314

2、节点之间必须要通过主机名互相通信;

建议使用hosts文件;

通信中使用的名字必须与其节点为上“uname -n”命令展示出的名字保持一致;

# cat /etc/hosts

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4

::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

172.16.0.1  server.magelinux.com server

172.16.31.52 www.stu31.com proxy.stu31.com proxy

172.16.31.50 tom1.stu31.com tom1

172.16.31.51 tom2.stu31.com tom2

3、节点之间彼此root用户能基于ssh密钥方式进行通信;

节点tom1:

# ssh-keygen -t rsa -P ""

# ssh-copy-id -i .ssh/id_rsa.pub tom1

节点tom2:

# ssh-keygen -t rsa -P ""

# ssh-copy-id -i .ssh/id_rsa.pub tom2

测试ssh无密钥通信:

[root@tom1 ~]# date ;ssh tom2 date

Wed Jan 14 21:52:46 CST 2015

Wed Jan 14 21:52:46 CST 2015

4.设置proxy为其他节点的管理端

# ssh-keygen -t rsa -P ""

# ssh-copy-id -i .ssh/id_rsa.pub root@172.16.31.50

# ssh-copy-id -i .ssh/id_rsa.pub root@172.16.31.51

管理其他节点,传递节点tom1和tom2都需要的软件包:

# for i in {1..2}; do scp jdk-7u67-linux-x64.rpm tom$i:/root ; done

一.配置后端tomcat节点服务器

两个节点同时安装

1.安装jdk,节点tom1和tom2存放jdk;

jdk-7u67-linux-x64.rpm

[root@proxy ~]# for i in {1..2}; do ssh tom$i "rpm -ivh jdk-7u67-linux-x64.rpm" ;done

查看安装情况:

[root@tom1 ~]# ls /usr/java/

default  jdk1.7.0_67  latest

[root@tom1 ~]# cd /usr/java/jdk1.7.0_67/

[root@tom1 jdk1.7.0_67]# ls

bin        lib          src.zip

COPYRIGHT  LICENSE      THIRDPARTYLICENSEREADME-JAVAFX.txt

db         man          THIRDPARTYLICENSEREADME.txt

include    README.html

jre        release

2.配置jdk环境变量

# vim /etc/profile.d/java.sh

export JAVA_HOME=/usr/java/latest

export PATH=$JAVA_HOME/bin:$PATH

加载变量:

# source /etc/profile.d/java.sh

运行命令显示java的版本和jre运行时环境:

# java -version

java version "1.7.0_67"

Java(TM) SE Runtime Environment (build 1.7.0_67-b01)

Java HotSpot(TM) 64-Bit Server VM (build 24.65-b04, mixed mode)

3.开始安装tomcat软件

获得tomcat软件:

apache-tomcat-7.0.55.tar.gz

安装tomcat:

[root@proxy ~]# for i in {1..2}; do ssh tom$i "tar xf apache-tomcat-7.0.55.tar.gz -C /usr/local" ; done

创建软链接:

[root@tom1 ~]# cd /usr/local/

[root@tom1 local]# ln -sv apache-tomcat-7.0.55/ tomcat

`tomcat' -> `apache-tomcat-7.0.55/'

[root@tom1 local]# cd tomcat

[root@tom1 tomcat]# ls

bin   lib      logs    RELEASE-NOTES  temp     work

conf  LICENSE  NOTICE  RUNNING.txt    webapps

4.配置tomcat环境变量:

# vim /etc/profile.d/tomcat.sh

export CATALINA_HOME=/usr/local/tomcat

export PATH=$CATALINA_HOME/bin:$PATH

加载环境变量:

# source /etc/profile.d/tomcat.sh

5.默认tomcat是root身份运行的,这样不安全,我们设置来用普通用户

注意:生产环境中运行tomcat尽量不要使用root

[root@proxy ~]# for i in {1..2}; do ssh tom$i "groupadd -g 280 tomcat;useradd -g 280 -u 280 tomcat" ; done

查看节点tom1和tom2用户tomcat的ID:

[root@proxy ~]# for i in {1..2}; do ssh tom$i "id tomcat" ; done

uid=280(tomcat) gid=280(tomcat) groups=280(tomcat)

uid=280(tomcat) gid=280(tomcat) groups=280(tomcat)

6.将tomcat的安装目录的权限更改为tomcat用户

[root@proxy ~]# for i in {1..2}; do ssh tom$i "chown -R tomcat:tomcat /usr/local/tomcat/" ; done

7.构建tomcat服务脚本

在proxy管理节点创建tomcat的脚本:

#!/bin/bash

#chkconfig: - 95 5

#description : tomcat serverlet container.

JAVA_HOME=/usr/java/latest

CATALINA_HOME=/usr/local/tomcat

export JAVA_HOME CATALINA_HOME

case $1 in

start)

exec $CATALINA_HOME/bin/catalina.sh start

;;

stop)

exec $CATALINA_HOME/bin/catalina.sh stop

;;

restart)

$CATALINA_HOME/bin/catalina.sh stop

sleep 1

exec $CATALINA_HOME/bin/catalina.sh start

;;

*)

exec $CATALINA_HOME/bin/catalina.sh $*

;;

esac

赋予执行权限:

[root@proxy ~]# chmod +x tomcat

拷贝到tomcat节点:

[root@proxy ~]# for i in {1..2}; do scp tomcat tom$i:/etc/init.d/ ; done

加入系统服务:

[root@proxy ~]# for i in {1..2}; do ssh tom$i "chkconfig --add tomcat" ; done

[root@proxy ~]# for i in {1..2}; do ssh tom$i "chkconfig --list tomcat" ; done

tomcat          0:off   1:off   2:off   3:off   4:off   5:off   6:off

tomcat          0:off   1:off   2:off   3:off   4:off   5:off   6:off

8.启动tomcat服务测试

如果切换到tomcat用户可以启动tomcat服务,但是我们为了方便这里就使用root直接启动啦。

[root@proxy ~]# for i in {1..2}; do ssh tom$i "service tomcat start" ; done

Tomcat started.

Tomcat started.

访问节点tom1和tom2的tomcat测试页:

9.部署一个webapp

在管理节点创建webapp的目录,及webapp所需的目录:

[root@proxy ~]# for i in {1..2}; do ssh tom$i "mkdir /usr/local/tomcat/webapps/testapp; cd /usr/local/tomcat/webapps/testapp; mkdir lib classes WEB-INF" ; done

到节点tom1和tom2创建tomcat的测试页:

节点tom1:

[root@tom1 testapp]# pwd

/usr/local/tomcat/webapps/testapp

[root@tom1 testapp]# vim index.jsp

<%@ page language="java" %>

<html>

<head><title>TomcatA</title></head>

<body>

<h1><font color="red">TomcatA.stu31.com</font></h1>

<table align="centre" border="1">

<tr>

<td>Session ID</td>

<% session.setAttribute("stu31.com","stu31.com"); %>

<td><%= session.getId() %></td>

</tr>

<tr>

<td>Created on</td>

<td><%= session.getCreationTime() %></td>

</tr>

</table>

</body>

</html>

节点tom2:

[root@tom2 testapp]# pwd

/usr/local/tomcat/webapps/testapp

[root@tom2 testapp]# vim index.jsp

<%@ page language="java" %>

<html>

<head><title>TomcatB </title></head>

<body>

<h1><font color="red">TomcatB.stu31.com</font></h1>

<table align="centre" border="1">

<tr>

<td>Session ID</td>

<% session.setAttribute("stu31.com","stu31.com"); %>

<td><%= session.getId() %></td>

</tr>

<tr>

<td>Created on</td>

<td><%= session.getCreationTime() %></td>

</tr>

</table>

</body>

</html>

配置节点tom1和tom2的虚拟主机配置文件:

节点tom1:

[root@tom1 ~]# cd /usr/local/tomcat

[root@tom1 tomcat]# vim conf/server.xml

[root@tom1 tomcat]# cat conf/server.xml

<?xml version='1.0' encoding='utf-8'?>

<!--

Licensed to the Apache Software Foundation (ASF) under one or more

contributor license agreements.  See the NOTICE file distributed with

this work for additional information regarding copyright ownership.

The ASF licenses this file to You under the Apache License, Version 2.0

(the "License"); you may not use this file except in compliance with

the License.  You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software

distributed under the License is distributed on an "AS IS" BASIS,

WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

See the License for the specific language governing permissions and

limitations under the License.

-->

<!-- Note:  A "Server" is not itself a "Container", so you may not

define subcomponents such as "Valves" at this level.

Documentation at /docs/config/server.html

-->

<Server port="8005" shutdown="SHUTDOWN">

<!-- Security listener. Documentation at /docs/config/listeners.html

<Listener className="org.apache.catalina.security.SecurityListener" />

-->

<!--APR library loader. Documentation at /docs/apr.html -->

<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />

<!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html -->

<Listener className="org.apache.catalina.core.JasperListener" />

<!-- Prevent memory leaks due to use of particular java/javax APIs-->

<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />

<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />

<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />

<!-- Global JNDI resources

Documentation at /docs/jndi-resources-howto.html

-->

<GlobalNamingResources>

<!-- Editable user database that can also be used by

UserDatabaseRealm to authenticate users

-->

<Resource name="UserDatabase" auth="Container"

type="org.apache.catalina.UserDatabase"

description="User database that can be updated and saved"

factory="org.apache.catalina.users.MemoryUserDatabaseFactory"

pathname="conf/tomcat-users.xml" />

</GlobalNamingResources>

<!-- A "Service" is a collection of one or more "Connectors" that share

a single "Container" Note:  A "Service" is not itself a "Container",

so you may not define subcomponents such as "Valves" at this level.

Documentation at /docs/config/service.html

-->

<Service name="Catalina">

<!--The connectors can use a shared executor, you can define one or more named thread pools-->

<!--

<Executor name="tomcatThreadPool" namePrefix="catalina-exec-"

maxThreads="150" minSpareThreads="4"/>

-->

<!-- A "Connector" represents an endpoint by which requests are received

and responses are returned. Documentation at :

Java HTTP Connector: /docs/config/http.html (blocking & non-blocking)

Java AJP  Connector: /docs/config/ajp.html

APR (HTTP/AJP) Connector: /docs/apr.html

Define a non-SSL HTTP/1.1 Connector on port 8080

-->

#tomcat服务监听端口不用更改,我们的反向代理服务直接反向代理到这个8080端口

<Connector port="8080" protocol="HTTP/1.1"

connectionTimeout="20000"

redirectPort="8443" />

<!-- A "Connector" using the shared thread pool-->

<!--

<Connector executor="tomcatThreadPool"

port="8080" protocol="HTTP/1.1"

connectionTimeout="20000"

redirectPort="8443" />

-->

<!-- Define a SSL HTTP/1.1 Connector on port 8443

This connector uses the BIO implementation that requires the JSSE

style configuration. When using the APR/native implementation, the

OpenSSL style configuration is required as described in the APR/native

documentation -->

<!--

<Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol"

maxThreads="150" SSLEnabled="true" scheme="https" secure="true"

clientAuth="false" sslProtocol="TLS" />

-->

<!-- Define an AJP 1.3 Connector on port 8009 -->

<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />

<!-- An Engine represents the entry point (within Catalina) that processes

every request.  The Engine implementation for Tomcat stand alone

analyzes the HTTP headers included with the request, and passes them

on to the appropriate Host (virtual host).

Documentation at /docs/config/engine.html -->

<!-- You should set jvmRoute to support load-balancing via AJP ie :

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

-->

#更改默认主机名

<Engine name="Catalina" defaultHost="tom1.stu31.com">

<!--For clustering, please take a look at documentation at:

/docs/cluster-howto.html  (simple how to)

/docs/config/cluster.html (reference documentation) -->

<!--

<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>

-->

<!-- Use the LockOutRealm to prevent attempts to guess user passwords

via a brute-force attack -->

<Realm className="org.apache.catalina.realm.LockOutRealm">

<!-- This Realm uses the UserDatabase configured in the global JNDI

resources under the key "UserDatabase".  Any edits

that are performed against this UserDatabase are immediately

available for use by the Realm.  -->

<Realm className="org.apache.catalina.realm.UserDatabaseRealm"

resourceName="UserDatabase"/>

</Realm>

#更改主机名,并添加一个Context为新输入的webapp

<Host name="tom1.stu31.com"  appBase="webapps"

unpackWARs="true" autoDeploy="true">

<Context path="" docBase="testapp" reloadable="true" />

<!-- SingleSignOn valve, share authentication between web applications

Documentation at: /docs/config/valve.html -->

<!--

<Valve className="org.apache.catalina.authenticator.SingleSignOn" />

-->

<!-- Access log processes all example.

Documentation at: /docs/config/valve.html

Note: The pattern used is equivalent to using pattern="common" -->

<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"

prefix="localhost_access_log." suffix=".txt"

pattern="%h %l %u %t &quot;%r&quot; %s %b" />

</Host>

</Engine>

</Service>

</Server>

节点tom2的配置:

[root@tom2 ~]# cd /usr/local/tomcat

[root@tom2 tomcat]# vim conf/server.xml

[root@tom2 tomcat]# cat conf/server.xml

<?xml version='1.0' encoding='utf-8'?>

<!--

Licensed to the Apache Software Foundation (ASF) under one or more

contributor license agreements.  See the NOTICE file distributed with

this work for additional information regarding copyright ownership.

The ASF licenses this file to You under the Apache License, Version 2.0

(the "License"); you may not use this file except in compliance with

the License.  You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software

distributed under the License is distributed on an "AS IS" BASIS,

WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

See the License for the specific language governing permissions and

limitations under the License.

-->

<!-- Note:  A "Server" is not itself a "Container", so you may not

define subcomponents such as "Valves" at this level.

Documentation at /docs/config/server.html

-->

<Server port="8005" shutdown="SHUTDOWN">

<!-- Security listener. Documentation at /docs/config/listeners.html

<Listener className="org.apache.catalina.security.SecurityListener" />

-->

<!--APR library loader. Documentation at /docs/apr.html -->

<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />

<!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html -->

<Listener className="org.apache.catalina.core.JasperListener" />

<!-- Prevent memory leaks due to use of particular java/javax APIs-->

<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />

<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />

<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />

<!-- Global JNDI resources

Documentation at /docs/jndi-resources-howto.html

-->

<GlobalNamingResources>

<!-- Editable user database that can also be used by

UserDatabaseRealm to authenticate users

-->

<Resource name="UserDatabase" auth="Container"

type="org.apache.catalina.UserDatabase"

description="User database that can be updated and saved"

factory="org.apache.catalina.users.MemoryUserDatabaseFactory"

pathname="conf/tomcat-users.xml" />

</GlobalNamingResources>

<!-- A "Service" is a collection of one or more "Connectors" that share

a single "Container" Note:  A "Service" is not itself a "Container",

so you may not define subcomponents such as "Valves" at this level.

Documentation at /docs/config/service.html

-->

<Service name="Catalina">

<!--The connectors can use a shared executor, you can define one or more named thread pools-->

<!--

<Executor name="tomcatThreadPool" namePrefix="catalina-exec-"

maxThreads="150" minSpareThreads="4"/>

-->

<!-- A "Connector" represents an endpoint by which requests are received

and responses are returned. Documentation at :

Java HTTP Connector: /docs/config/http.html (blocking & non-blocking)

Java AJP  Connector: /docs/config/ajp.html

APR (HTTP/AJP) Connector: /docs/apr.html

Define a non-SSL HTTP/1.1 Connector on port 8080

-->

#tomcat服务监听端口不用更改,我们的反向代理服务直接反向代理到这个8080端口

<Connector port="8080" protocol="HTTP/1.1"

connectionTimeout="20000"

redirectPort="8443" />

<!-- A "Connector" using the shared thread pool-->

<!--

<Connector executor="tomcatThreadPool"

port="8080" protocol="HTTP/1.1"

connectionTimeout="20000"

redirectPort="8443" />

-->

<!-- Define a SSL HTTP/1.1 Connector on port 8443

This connector uses the BIO implementation that requires the JSSE

style configuration. When using the APR/native implementation, the

OpenSSL style configuration is required as described in the APR/native

documentation -->

<!--

<Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol"

maxThreads="150" SSLEnabled="true" scheme="https" secure="true"

clientAuth="false" sslProtocol="TLS" />

-->

<!-- Define an AJP 1.3 Connector on port 8009 -->

<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />

<!-- An Engine represents the entry point (within Catalina) that processes

every request.  The Engine implementation for Tomcat stand alone

analyzes the HTTP headers included with the request, and passes them

on to the appropriate Host (virtual host).

Documentation at /docs/config/engine.html -->

<!-- You should set jvmRoute to support load-balancing via AJP ie :

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

-->

#更改默认主机名

<Engine name="Catalina" defaultHost="tom2.stu31.com">

<!--For clustering, please take a look at documentation at:

/docs/cluster-howto.html  (simple how to)

/docs/config/cluster.html (reference documentation) -->

<!--

<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>

-->

<!-- Use the LockOutRealm to prevent attempts to guess user passwords

via a brute-force attack -->

<Realm className="org.apache.catalina.realm.LockOutRealm">

<!-- This Realm uses the UserDatabase configured in the global JNDI

resources under the key "UserDatabase".  Any edits

that are performed against this UserDatabase are immediately

available for use by the Realm.  -->

<Realm className="org.apache.catalina.realm.UserDatabaseRealm"

resourceName="UserDatabase"/>

</Realm>

#更改主机名,并添加一个Context为新输入的webapp

<Host name="tom2.stu31.com"  appBase="webapps"

unpackWARs="true" autoDeploy="true">

<Context path="" docBase="testapp" reloadable="true" />

<!-- SingleSignOn valve, share authentication between web applications

Documentation at: /docs/config/valve.html -->

<!--

<Valve className="org.apache.catalina.authenticator.SingleSignOn" />

-->

<!-- Access log processes all example.

Documentation at: /docs/config/valve.html

Note: The pattern used is equivalent to using pattern="common" -->

<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"

prefix="localhost_access_log." suffix=".txt"

pattern="%h %l %u %t &quot;%r&quot; %s %b" />

</Host>

</Engine>

</Service>

</Server>

10.节点所有配置部署完毕后,启动tomcat服务进行访问测试:

到管理节点检查配置文件:

[root@proxy ~]# for i in {1..2} ; do ssh tom$i "catalina.sh configtest" ; done

Jan 15, 2015 8:37:57 AM org.apache.catalina.core.AprLifecycleListener init

INFO: The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: /usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib

Jan 15, 2015 8:37:59 AM org.apache.coyote.AbstractProtocol init

INFO: Initializing ProtocolHandler ["http-bio-8080"]

Jan 15, 2015 8:37:59 AM org.apache.coyote.AbstractProtocol init

INFO: Initializing ProtocolHandler ["ajp-bio-8009"]

Jan 15, 2015 8:37:59 AM org.apache.catalina.startup.Catalina load

INFO: Initialization processed in 3987 ms

Jan 15, 2015 8:38:05 AM org.apache.catalina.core.AprLifecycleListener init

INFO: The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: /usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib

Jan 15, 2015 8:38:07 AM org.apache.coyote.AbstractProtocol init

INFO: Initializing ProtocolHandler ["http-bio-8080"]

Jan 15, 2015 8:38:07 AM org.apache.coyote.AbstractProtocol init

INFO: Initializing ProtocolHandler ["ajp-bio-8009"]

Jan 15, 2015 8:38:07 AM org.apache.catalina.startup.Catalina load

INFO: Initialization processed in 4235 ms

在管理节点启动tomcat服务:

[root@proxy ~]# for i in {1..2} ; do ssh tom$i "catalina.sh start" ; done

Tomcat started.

Tomcat started.

在管理节点查看tomcat服务监听的端口:

[root@proxy ~]# for i in {1..2} ; do ssh tom$i "ss -tnul |grep 800* " ; done

tcp    LISTEN     0      1       ::ffff:127.0.0.1:8005                 :::*

tcp    LISTEN     0      100                   :::8009                 :::*

tcp    LISTEN     0      100                   :::8080                 :::*

tcp    LISTEN     0      1       ::ffff:127.0.0.1:8005                 :::*

tcp    LISTEN     0      100                   :::8009                 :::*

tcp    LISTEN     0      100                   :::8080                 :::*

客户端windows xp访问测试;

节点tom1和tom2的tomcat环境就搭建完毕!下面就进行负载均衡的实验了。

Tom2节点在本实验中是DNS服务节点;提供DNS解析服务,有关DNS服务器的配置请参考博客:http://sohudrgon.blog.51cto.com/3088108/1588344

二.proxy节点反向服务器的配置(1):使用nginx实现负载均衡请求到后端tomcat节点

1.安装nginx

[root@proxy ~]# yum install nginx-1.6.2-1.el6.ngx.x86_64.rpm

2.配置nginx服务器实现反向代理功能

[root@proxy nginx]# pwd

/etc/nginx

配置主配置文件添加后端tomcat节点:

[root@proxy nginx]# vim nginx.conf

http {

include       /etc/nginx/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"';

access_log  /var/log/nginx/access.log  main;

sendfile        on;

#tcp_nopush     on;

keepalive_timeout  65;

#gzip  on;

upstream tcsrvs {

server 172.16.31.50:8080

server 172.16.31.51:8080

}

include /etc/nginx/conf.d/*.conf;

}

配置nginx默认配置文件反向代理用户请求到后端tomcat节点:

[root@proxy nginx]# vim conf.d/default.conf

server {

listen       80;

server_name  localhost;

#charset koi8-r;

#access_log  /var/log/nginx/log/host.access.log  main;

location / {

proxy_pass http://tcsrvs;

}

#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   /usr/share/nginx/html;

}

3.检查配置文件语法,启动nginx服务,访问测试

检查语法:

[root@proxy nginx]# nginx -t

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok

nginx: configuration file /etc/nginx/nginx.conf test is successful

启动nginx服务:

[root@proxy nginx]# service nginx start

Starting nginx:                                            [  OK  ]

4.实现基于ip_hash绑定会话的负载均衡调度

[root@proxy nginx]# vim nginx.conf

upstream tcsrvs {

ip_hash;

server 172.16.31.50:8080;

server 172.16.31.51:8080;

}

检查语法:

[root@proxy nginx]# nginx -t

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok

nginx: configuration file /etc/nginx/nginx.conf test is successful

5.重启nginx服务器访问测试;

[root@proxy nginx]# service nginx restart

Stopping nginx:                                            [  OK  ]

Starting nginx:                                            [  OK  ]

至此,使用nginx实现负载均衡请求到后端tomcat节点就实现了!

三..proxy节点反向服务器的配置(2):使用httpd实现负载均衡请求的后端tomcat节点

前提:配置后端tomcat节点tom1和tom2的server.xml文件

确保Engine组件中存在jvmRoute属性,其值要与mod_jk配置中使用worker同名;

tom1:

<Engine name="Catalina" defaultHost="tom1.stu31.com" jvmRoute="TomcatA">

tom2:

<Engine name="Catalina" defaultHost="tom2.stu31.com" jvmRoute="TomcatB">

为了更好的区分两个tomcat节点,我们将tom1节点的主页测试文件更改为蓝色:

[root@tom1 testapp]# pwd

/usr/local/tomcat/webapps/testapp

[root@tom1 testapp]# vim index.jsp

<%@ page language="java" %>

<html>

<head><title>TomcatA</title></head>

<body>

<h1><font color="blue">TomcatA.stu31.com</font></h1>

<table align="centre" border="1">

<tr>

<td>Session ID</td>

<% session.setAttribute("stu31.com","stu31.com"); %>

<td><%= session.getId() %></td>

</tr>

<tr>

<td>Created on</td>

<td><%= session.getCreationTime() %></td>

</tr>

</table>

</body>

</html>

配置成功后重启tomcat服务。

1.停止nginx服务器,防止其占用80端口。

[root@proxy nginx]# service nginx stop

Stopping nginx:                                            [  OK  ]

2.配置apache通过proxy_http_module模块与Tomcat连接:

检测当前的apache是否支持mod_proxy、mod_proxy_http、mod_proxy_ajp和proxy_balancer_module模块:

# httpd -M

……………………

proxy_module (shared)

proxy_balancer_module (shared)

proxy_ftp_module (shared)

proxy_http_module (shared)

proxy_ajp_module (shared)

proxy_connect_module (shared)

……………………

3.在httpd.conf的全局配置段或虚拟主机中添加如下内容:

[root@proxy ~]# vim /etc/httpd/conf/httpd.conf

#注释掉如下内容

#DocumentRoot "/var/www/html"

4.创建虚拟主机配置文件,实现负载均衡调度用户请求到后端tomcat服务器;

[root@proxy ~]# vim /etc/httpd/conf.d/mod_proxy_http.conf

NameVirtualHost *:80

<VirtualHost *:80>

ServerName www.stu31.com

ProxyVia on

ProxyRequests off

ProxyPreserveHost on

<proxy balancer://tcsrvs>

BalancerMember http://172.16.31.50:8080 loadfactor=1 route=TomcatA

BalancerMember http://172.16.31.51:8080 loadfactor=1 route=TomcatB

</proxy>

ProxyPass / balancer://tcsrvs/

ProxyPa***everse / balancer://tcsrvs/

<Proxy *>

Order deny,allow

Allow from all

</Proxy>

<Location />

Order deny,allow

Allow from all

</Location>

</VirtualHost>

关于如上apache指令的说明:

ProxyPreserveHost {On|Off}:如果启用此功能,代理会将用户请求报文中的Host:行发送给后端的服务器,而不再使用ProxyPass指定的服务器地址。如果想在反向代理中支持虚拟主机,则需要开启此项,否则就无需打开此功能。

ProxyVia  {On|Off|Full|Block}:用于控制在http首部是否使用Via:,主要用于在多级代理中控制代理请求的流向。默认为Off,即不启用此功能;On表示每个请求和响应报文均添加Via:;Full表示每个Via:行都会添加当前apache服务器的版本号信息;Block表示每个代理请求报文中的Via:都会被移除。

ProxyRequests {On|Off}:是否开启apache正向代理的功能;启用此项时为了代理http协议必须启用mod_proxy_http模块。同时,如果为apache设置了ProxyPass,则必须将ProxyRequests设置为Off。

ProxyPass  [path]  !|url  [key=value key=value ...]]:将后端服务器某URL与当前服务器的某虚拟路径关联起来作为提供服务的路径,path为当前服务器上的某虚拟路径,url为后端服务器上某URL路径。使用此指令时必须将ProxyRequests的值设置为Off。需要注意的是,如果path以“/”结尾,则对应的url也必须以“/”结尾,反之亦然。

另外,mod_proxy模块在httpd 2.1的版本之后支持与后端服务器的连接池功能,连接在按需创建在可以保存至连接池中以备进一步使用。连接池大小或其它设定可以通过在ProxyPass中使用key=value的方式定义。常用的key如下所示:

◇ min:连接池的最小容量,此值与实际连接个数无关,仅表示连接池最小要初始化的空间大小。

◇ max:连接池的最大容量,每个MPM都有自己独立的容量;都值与MPM本身有关,如Prefork的总是为1,而其它的则取决于ThreadsPerChild指令的值。

◇ loadfactor:用于负载均衡集群配置中,定义对应后端服务器的权重,取值范围为1-100。

◇ retry:当apache将请求发送至后端服务器得到错误响应时等待多长时间以后再重试。单位是秒钟。

如果Proxy指定是以balancer://开头,即用于负载均衡集群时,其还可以接受一些特殊的参数,如下所示:

◇lbmethod:apache实现负载均衡的调度方法,默认是byrequests,即基于权重将统计请求个数进行调度,bytraffic则执行基于权重的流量计数调度,bybusyness通过考量每个后端服务器的当前负载进行调度。

◇ maxattempts:放弃请求之前实现故障转移的次数,默认为1,其最大值不应该大于总的节点数。

◇ nofailover:取值为On或Off,设置为On时表示后端服务器故障时,用户的session将损坏;因此,在后端服务器不支持session复制时可将其设置为On。

◇ stickysession:调度器的sticky session的名字,根据web程序语言的不同,其值为JSESSIONID或PHPSESSIONID。

上述指令除了能在banlancer://或ProxyPass中设定之外,也可使用ProxySet指令直接进行设置,如:

<Proxy balancer://tcsrvs>

BalancerMember  http://172.16.31.50:8080 loadfactor=1

BalancerMember  http://172.16.31.51:8080 loadfactor=2

ProxySet  lbmethod=byrequests

</Proxy>

ProxyPa***everse:用于让apache调整HTTP重定向响应报文中的Location、Content-Location及URI标签所对应的URL,在反向代理环境中必须使用此指令避免重定向报文绕过proxy服务器。

5.配置文件语法检查,启动httpd服务器;

[root@proxy conf.d]# httpd -t

Syntax OK

[root@proxy conf.d]# service httpd start

Starting httpd:                                            [  OK  ]

6.访问测试:

至此,使用httpd实现负载均衡请求的后端tomcat节点的实验就完成了。

7.绑定session会话和开启负载均衡管理界面:

[root@proxy conf.d]# pwd

/etc/httpd/conf.d

[root@proxy conf.d]# vim mod_proxy_http1.conf

NameVirtualHost *:80

<VirtualHost *:80>

ServerName www.stu31.com

ProxyVia on

ProxyRequests off

ProxyPreserveHost on

<proxy balancer://tcsrvs>

BalancerMember http://172.16.31.50:8080 loadfactor=1 route=TomcatA

BalancerMember http://172.16.31.51:8080 loadfactor=1 route=TomcatB

</proxy>

<Location /lbmanager>                 #定义负载均衡管理界面

SetHandler balancer-manager

</Location>

ProxyPass /lbmanager !               #该界面是不做代理

ProxyPass / balancer://tcsrvs/ stickysession=JSESSIONID            #开启session绑定

ProxyPa***everse / balancer://tcsrvs/

<Proxy *>

Order deny,allow

Allow from all

</Proxy>

<Location />

Order deny,allow

Allow from all

</Location>

</VirtualHost>

8.重启httpd服务,访问测试:

[root@proxy conf.d]# service httpd restart

Stopping httpd:                                            [  OK  ]

Starting httpd:                                            [  OK  ]

测试负载均衡管理界面也是正常的。可以在此处做简单的管理操作。

观察其中发送的数据发现只有tom2节点;实现了会话绑定;

9.配置apache通过mod_proxy_ajp模块与Tomcat连接

备份httpd_proxy配置文件

[root@proxy conf.d]# cp mod_proxy_http.conf mod_proxy_ajp.conf

[root@proxy conf.d]# ls

mod_dnssd.conf  mod_proxy_ajp.conf  mod_proxy_http.conf  README  welcome.conf

#需要将前面的http连接器的配置文件更改名称,不然httpd服务器加载。

[root@proxy conf.d]# mv mod_proxy_http.conf mod_proxy_http.conf.bak

配置ajp的配置文件,将协议由http更改为ajp协议即可:

[root@proxy conf.d]# vim mod_proxy_ajp.conf

NameVirtualHost *:80

<VirtualHost *:80>

ServerName www.stu31.com

ProxyVia on

ProxyRequests off

ProxyPreserveHost on

<proxy balancer://tcsrvs>

BalancerMember ajp://172.16.31.50:8009 loadfactor=1 route=TomcatA

BalancerMember ajp://172.16.31.51:8009 loadfactor=1 route=TomcatB

</proxy>

<Location /lbmanager>

SetHandler balancer-manager

</Location>

ProxyPass /lbmanager !

ProxyPass / balancer://tcsrvs/

ProxyPa***everse / balancer://tcsrvs/

<Proxy *>

Order deny,allow

Allow from all

</Proxy>

<Location />

Order deny,allow

Allow from all

</Location>

</VirtualHost>

10.检查语法,重启服务,访问测试;

#httpd -t

#service httpd restart

11.通过tcpdump在后端tomcat节点的8009端口抓包

[root@tom1 ~]# tcpdump -nn -i eth0 port 8009

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode

listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes

10:12:50.441165 IP 172.16.31.52.43213 > 172.16.31.50.8009: Flags [S], seq 3134086892, win 14600, options [mss 1460,sackOK,TS val 4063808 ecr 0,nop,wscale 5], length 0

10:12:50.441201 IP 172.16.31.50.8009 > 172.16.31.52.43213: Flags [S.], seq 1267158001, ack 3134086893, win 14480, options [mss 1460,sackOK,TS val 4×××174 ecr 4063808,nop,wscale 6], length 0

10:12:50.441481 IP 172.16.31.52.43213 > 172.16.31.50.8009: Flags [.], ack 1, win 457, options [nop,nop,TS val 4063809 ecr 4×××174], length 0

10:12:50.441676 IP 172.16.31.52.43213 > 172.16.31.50.8009: Flags [P.], seq 1:433, ack 1, win 457, options [nop,nop,TS val 4063809 ecr 4×××174], length 432

10:12:50.441688 IP 172.16.31.50.8009 > 172.16.31.52.43213: Flags [.], ack 433, win 243, options [nop,nop,TS val 4×××175 ecr 4063809], length 0

10:12:50.444041 IP 172.16.31.50.8009 > 172.16.31.52.43213: Flags [P.], seq 1:130, ack 433, win 243, options [nop,nop,TS val 4×××177 ecr 4063809], length 129

10:12:50.444581 IP 172.16.31.50.8009 > 172.16.31.52.43213: Flags [P.], seq 130:514, ack 433, win 243, options [nop,nop,TS val 4×××178 ecr 4063809], length 384

10:12:50.444718 IP 172.16.31.50.8009 > 172.16.31.52.43213: Flags [P.], seq 514:520, ack 433, win 243, options [nop,nop,TS val 4×××178 ecr 4063809], length 6

10:12:50.446793 IP 172.16.31.52.43213 > 172.16.31.50.8009: Flags [.], ack 130, win 490, options [nop,nop,TS val 4063813 ecr 4×××177], length 0

10:12:50.446807 IP 172.16.31.52.43213 > 172.16.31.50.8009: Flags [.], ack 514, win 524, options [nop,nop,TS val 4063814 ecr 4×××178], length 0

10:12:50.446810 IP 172.16.31.52.43213 > 172.16.31.50.8009: Flags [.], ack 520, win 524, options [nop,nop,TS val 4063814 ecr 4×××178], length 0

至此,基于mod_proxy_ajp代理客户端访问到后端服务器的负载均衡实现。

12.绑定session会话

配置session会话绑定更上面mod_proxy的会话绑定配置一致,只需要在反向代理服务器组tcsrvs后加stickysession=JSESSIONID 即可:

如图配置:

NameVirtualHost *:80

<VirtualHost *:80>

ServerName www.stu31.com

ProxyVia on

ProxyRequests off

ProxyPreserveHost on

<proxy balancer://tcsrvs>

BalancerMember ajp://172.16.31.50:8009 loadfactor=1 route=TomcatA

BalancerMember ajp://172.16.31.51:8009 loadfactor=1 route=TomcatB

</proxy>

<Location /lbmanager>

SetHandler balancer-manager

</Location>

ProxyPass /lbmanager !

ProxyPass / balancer://tcsrvs/ stickysession=JSESSIONID

ProxyPa***everse / balancer://tcsrvs/

<Proxy *>

Order deny,allow

Allow from all

</Proxy>

<Location />

Order deny,allow

Allow from all

</Location>

</VirtualHost>

13.重启httpd服务,访问测试,刷新页面都是tomcatA:

#httpd -t

#service httpd restart

可以查看一下负载均衡管理界面:

至此,基于mod_proxy_ajp代理客户端访问到后端服务器的会话保持就实现了。


四.proxy节点反向服务器的配置(3):使用mod_jk实现负载均衡请求到后端tomcat节点,并实现session绑定

mod_jk是ASF的一个项目,是一个工作于apache端基于AJP协议与Tomcat通信的连接器,它是apache的一个模块,是AJP协议的客户端(服务端是Tomcat的AJP连接器)。

1.开发环境部署

# yum groupinstall Development Tools

# yum install -y httpd-devel

2.安装第三方的mod_jk模块

[root@proxy ~]# tar xf tomcat-connectors-1.2.40-src.tar.gz

[root@proxy ~]# cd tomcat-connectors-1.2.40-src

[root@proxy tomcat-connectors-1.2.40-src]# cd native/

[root@proxy native]# ./configure --with-apxs=`which apxs`

[root@proxy native]# make && make install

3.查看安装的mod_jk模块

# ls /usr/lib64/httpd/modules/ | grep mod_jk

mod_jk.so

4.装载mod_jk模块到httpd服务器

先备份原来的mod_proxy_ajp的配置文件;

[root@proxy conf.d]# pwd

/etc/httpd/conf.d

[root@proxy conf.d]# mv mod_proxy_ajp.conf mod_proxy_ajp.conf.bak

apache要使用mod_jk连接器,需要在启动时加载此连接器模块。为了便于管理与mod_jk模块相关的配置,这里使用一个专门的配置文件/etc/httpd/conf.d/mod_jk.conf来保存相关指令及其设置。其内容如下:

#vim /etc/httpd/conf.d/mod_jk.conf

LoadModule jk_module modules/mod_jk.so

JkWorkersFile /etc/httpd/conf.d/workers.properties

JkLogFile logs/mod_jk.log

JkLogLevel debug

JkMount /jkstatus StatA

JkMount /* tcsrvs

使用/etc/httpd/conf.d/workers.properties来定义一个名为tcsrvs的worker,并为其指定几个属性。文件内容如下:

#vim /etc/httpd/conf.d/workers.properties

worker.list=tcsrvs,StatA

worker.TomcatA.type=ajp13

worker.TomcatA.host=172.16.31.50

worker.TomcatA.port=8009

worker.TomcatA.lbfactor=1

worker.TomcatB.type=ajp13

worker.TomcatB.host=172.16.31.51

worker.TomcatB.port=8009

worker.TomcatB.lbfactor=1

worker.tcsrvs.type=lb

worker.tcsrvs.sticky_session=0

worker.tcsrvs.balance_workers=TomcatA,TomcatB

worker.StatA.type=status

5.配置后端tomcat节点tom1和tom2的server.xml文件

确保Engine组件中存在jvmRoute属性,其值要与mod_jk配置中使用worker同名;

tom1节点:

<Engine name="Catalina" defaultHost="tom1.stu31.com" jvmRoute="TomcatA">

tom2节点:

<Engine name="Catalina" defaultHost="tom2.stu31.com" jvmRoute="TomcatB">

配置成功后重启tomcat服务。

#service tomcat stop

#service tomcat start

6.检查语法,重启httpd服务,访问测试:

检查语法:

[root@proxy conf.d]# httpd -t

Syntax OK

重启httpd服务:

[root@proxy conf.d]# service httpd restart

Stopping httpd:                                            [  OK  ]

Starting httpd:                                            [  OK  ]

访问测试:

7.通过tcpdump在后端tomcat节点的8009端口抓包

[root@tom2 tomcat]# tcpdump -nn -i eth0 port 8009

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode

listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes

22:09:29.951504 IP 172.16.31.52.47390 > 172.16.31.51.8009: Flags [S], seq 90832382, win 14600, options [mss 1460,sackOK,TS val 52439866 ecr 0,nop,wscale 5], length 0

22:09:29.951553 IP 172.16.31.51.8009 > 172.16.31.52.47390: Flags [S.], seq 99107550, ack 90832383, win 14480, options [mss 1460,sackOK,TS val 43542063 ecr 52439866,nop,wscale 6], length 0

22:09:29.951826 IP 172.16.31.52.47390 > 172.16.31.51.8009: Flags [.], ack 1, win 457, options [nop,nop,TS val 52439866 ecr 43542063], length 0

22:09:29.952466 IP 172.16.31.52.47390 > 172.16.31.51.8009: Flags [P.], seq 1:500, ack 1, win 457, options [nop,nop,TS val 52439867 ecr 43542063], length 499

22:09:29.952478 IP 172.16.31.51.8009 > 172.16.31.52.47390: Flags [.], ack 500, win 243, options [nop,nop,TS val 43542064 ecr 52439867], length 0

22:09:29.954260 IP 172.16.31.51.8009 > 172.16.31.52.47390: Flags [P.], seq 1:122, ack 500, win 243, options [nop,nop,TS val 43542066 ecr 52439867], length 121

22:09:29.954573 IP 172.16.31.52.47390 > 172.16.31.51.8009: Flags [.], ack 122, win 457, options [nop,nop,TS val 52439869 ecr 43542066], length 0

22:09:29.954965 IP 172.16.31.51.8009 > 172.16.31.52.47390: Flags [P.], seq 122:498, ack 500, win 243, options [nop,nop,TS val 43542067 ecr 52439869], length 376

22:09:29.954991 IP 172.16.31.51.8009 > 172.16.31.52.47390: Flags [P.], seq 498:504, ack 500, win 243, options [nop,nop,TS val 43542067 ecr 52439869], length 6

22:09:29.956549 IP 172.16.31.52.47390 > 172.16.31.51.8009: Flags [.], ack 498, win 490, options [nop,nop,TS val 52439871 ecr 43542067], length 0

22:09:29.956558 IP 172.16.31.52.47390 > 172.16.31.51.8009: Flags [.], ack 504, win 490, options [nop,nop,TS val 52439871 ecr 43542067], length 0

至此,基于mod_jk代理客户端访问到后端服务器的负载均衡实现。

8.基于mod_jk代理客户端访问到后端服务器的负载均衡实现session绑定;

只需要在workers.properties将会话保持打开:

worker.tcsrvs.sticky_session=1

重启httpd服务器;

[root@proxy conf.d]# service httpd restart

Stopping httpd:                                            [  OK  ]

Starting httpd:                                            [  OK  ]

9.访问测试

可以看出会话实现了绑定。

至此,使用apache的proxy_http_module和proxy_ajp_module,第三方模块mod_jk,nginx反向代理请求到后端实现负载均衡和session保持的实验就完成了。

转载于:https://blog.51cto.com/dengaosky/1964893

Tomcat高级部分-使用特定模块和软件反向代理请求到后端tomcat实现负载均衡和session保持...相关推荐

  1. nginx+tomcat+redis负载均衡及session共享

    概述 本文档是用来详细描述 nginx+tomcat+redis负载均衡实现session共享 所需软件及下载地址 软件名称 下载地址 功能说明 Nginx-v1.6.0 http://nginx.o ...

  2. Linux环境,手把手带你实现一个Nginx模块,深入了解Nginx丨惊群效应|error|负载均衡|Openresty丨C/C++Linux服务器开发丨中间件

    Linux环境,手把手带你实现一个Nginx模块,深入了解Nginx 视频讲解如下,点击观看: Linux环境,手把手带你实现一个Nginx模块,深入了解Nginx丨惊群效应|error|负载均衡|O ...

  3. Apache+Tomcat +mod_proxy集群负载均衡及session

      序言: 在玩Apache+Tomcat +mod_jk集群负载均衡及session的时候发现,还有一种方式可以实现,就是网上各位大牛们说的mod_proxy反向代理. 实在弄的我的知识细胞洋洋.实 ...

  4. Nginx+Tomcat+Redis负载均衡实现Session共享

    Nginx+Tomcat+Redis负载均衡实现Session共享 环境描述 tomcat1:192.168.194.100:18080 tomcat2:192.168.194.100:28080 N ...

  5. nginx配置禁特定路径下的反向代理

    近期因为项目需要再一次配置了nginx 这次的的需求设计到字符串处理 需要把<域名或ip>/xhr_api/开头的请求转发到内网某机器,同时移除掉xhr_api,这里直接记录下结果,配置非 ...

  6. MemCache在tomcat中的负载均衡和session交叉存放

    一.安装jdk 1.下载软件,并解压到指定目录/usr/local/ [root@server1 ~]# tar zxf jdk-7u79-linux-x64.tar.gz -C /usr/local ...

  7. nginx+tomcat+memcache实现负载均衡、session共享

    实验架构图: Table of Contents 1.配置tomcat 2.安装memcache 3.查看tomcat和memcache是否配置好 4.nginx实现负载均衡: 5.客户端进行测试: ...

  8. nginx+tomcat实现集群负载均衡(实现session复制)

    架构描述 前端一台nginx服务器做负载均衡器,后端放N台tomcat组成集群处理服务,通过nginx转发到后面(注:没做动静分离,静态动态全部都转给tomcat) 优点:实现了可弹性化的架构,在压力 ...

  9. Tomcat+nginx+keepalived+memcached实现双VIP负载均衡及Session会话保持

    准备好tomcat 第一台 tar vxf apache-tomcat-7.0.54.tar.gz mv apache-tomcat-7.0.54 /usr/local/tomcat tar vxf ...

最新文章

  1. GitHub开源的ImageAI 库:几行代码可实现目标对象识别
  2. [置顶]       设计模式之创建类模式——原型模式
  3. Android:安卓布局分类及布局和页面的关系
  4. 计算机排线知识,一种计算机排线梳理装置制造方法及图纸
  5. php 获取一年的月份_php 根据日期获取星座
  6. 【AI视野·今日NLP 自然语言处理论文速览 第十二期】Tue, 22 Jun 2021
  7. python查询最高分_精通 Oracle+Python,第 1 部分:查询最佳应践
  8. mongodb启动时报错ERROR: child process failed, exited with error number 1
  9. Linux开发_printf打印无消息或末尾带“#“or“%“
  10. [改善Java代码]使用CyclicBarrier让多线程齐步走
  11. Atitit 字符串模板与 字符串插值 目录 1.1. 字符串插值是将字符串中的占位符替换为局域变量的过程 1 1.2. 模板字面量 是允许嵌入表达式的字符串字面量 1 1.3. 格式化字符串[编辑
  12. Raki的读paper小记:ELECTRA: PRE-TRAINING TEXT ENCODERS AS DISCRIMINATORS RATHER THAN GENERATORS
  13. 车机没有carlife可以自己下载吗_雷克萨斯NX 原车carlife转换无线carplay
  14. 康佳电视应用助手服务器连接超时,康佳电视程序无响应怎么办?详细解决方法...
  15. linux vi 拷贝多行,vi 整行 多行 复制与粘贴
  16. linux系统在当前目录下创建子目录,linux根目录下一级子目录
  17. Vue粒子特效使用教程(vue-particles插件)
  18. 正则表达式之密码验证
  19. 【python基础】python中常用字符串函数详解
  20. oracle安装成功验证

热门文章

  1. mycncart不同地区不同固定运费
  2. android控制wifi状态
  3. Win7在IIS7中启用CGI
  4. 局域网与网络工程课堂笔记(1)(2)
  5. 一个母婴电子商务网站贝贝网的大数据平台及机器学习实践【转】
  6. 实现给一个DIV加阴影效果!
  7. Canvas VS . SVG
  8. Java IO学习笔记四
  9. Linux内核自旋锁使用笔记
  10. Android 数据库之Cursor