web站点架构
image.pngJava技术体系
image.png image.pngJava运行过程
image.png image.pngGC 线程
image.png image.png image.pngJAVA
SRE--运维工程师Ops
bash--调用内部命令(机器码)--运行很多进程--资源损耗
c--"编译器"作为一个进程--内部运行多个进程
python/go--"解释器"作为一个进程--内部运行多个进程
网站开发所用语言--php/jsp/asb.net(cshark)
jsp--主流互联网开发语言
底层不兼容--加中间层(抵消差异)--简洁一致的输出
java虚拟机(中间层的一部分)
提供一个程序运行环境
系统级接口(不统一)--变为-->虚拟接口(统一的接口)
没有调用系统本地"方法"--任何平台都可以运行--write once,run anywhere
写程序--拥有的条件
c库组件--存放程序员用到的代码(编码库)--提供的调用编程接口--即API
编程语言本身组件--关键字
调式和运行组件--检查错误(如:语法检查)
程序员:调用编码+语言+调式运行-->在jvm上跑起来
GC(gabage collection)
垃圾回收(我们在不断的分配内存空间--垃圾回收--防止内存被消耗空)
计数器(哪些内存需要回收,开始0,使用+1,完成-1,0--回收)
数据装载到内存中--执行完成后--释放
c--两个系统调用
malloc() 低效-->jemalloc() 并行内存分配(varnish)
free()
类加载器(class loader)--代码调用到公共库中的内容--需要装载类文件
JVM=类加载器+执行引擎
Java编写的程序--elasticsearch,hadoop...
运行Java程序,部署JRE|JDK
部署JDK两种方式:
1 Oracle官方下载:
www.bing.com--搜索JDK--Oracle官方下载--JDK下载(Java SE)
以运行程序为目的--建议使用JRE,否则可以使用JDK
二进制程序--不是源代码--OpenJDK(开源)
点击"Accept License Agreement"
下载rpm包--无多余的依赖关系--直接安装即可--Linux x64 jdk-8u171-linux-x64.rpm
centos7.3
rz 上传
cd /usr/java/ 非标准路径
ll 符号链接--可以多版本并存--但使用最新版本
cd /usr/java/latest/bin 有很多程序(Java命令)
jps 显示进程编号
设定环境变量--告诉系统级应用程序(如:tomcat--java编程),去哪里找Java
vim /etc/profile.d/java.sh
export JAVA_HOME=/usr/java/latest JAVA_HOME,指定java的家目录路径
export PATH=$JAVA_HOME/bin:$PATH 在bash中可以运行Java命令
. /etc/profile.d/java.sh
echo $JAVA_HOME
java -version
2 OpenJDK(开源--centos自带)
centos7.4
yum info java-1.8.0-openjdk 显示"The OpenJDK runtime environment."--JRE
yum info java-1.8.0-openjdk-devel
yum info java-1.8.0-openjdk-headless
不包含"audio and video"相关功能,需要音频处理--安装额外组件即可
yum install java-1.8.0-openjdk-devel
安装此包,可以自动解决依赖关系--安装openjdk(主包)和openjdk-devel
java -h
java -version
JDK三种模式
server mode:为服务器端程序运行而优化
client mode:为客户端程序运行而优化--内存分配的策略不同
mixed mode:
javac Java编译器
javadoc Java文档管理工具
javac编译完成后,使用java运行,启动一个java进程
tomcat运行--也启动一个java进程,不是tomcat进程
http协议--CGI--服务器端开发(后端开发)
无CGI
静态页面(内嵌java代码)--客户端展示(静态页面+插件JRE--执行java代码)--applet
有CGI
java后端服务--解析用户请求(http协议)+http响应
client--http服务器--CGI----severlet(解析CGI协议)--Java后端服务(应用)
severlet(解析整个页面内容)--太头疼
jsp(解析静态页面,java代码不动)--severlet(解析java代码)
.jsp -->jasper--> .java --> javac --> .class --> jvm
jasper--翻译静态页面代码,java代码不动--代码变为纯java程序文件--前后分开:
前端程序员--写前端代码--静态页面
后端程序员--写后端代码--内嵌的java代码
javac--把java代码编译为类文件
serverlet--JDK没有--要想开发jsp格式的网页页面
1 安装JDK--基础
2 把别人实现好的serverlet类库装进来--?
3 把jsp类库装进来--?
JSP Container: JDK+2个解决方案(serverlet和jsplet类库解决方案)
代码-->翻译-->执行
serverlet和jsplet类库解决方案
开源--tomcat
收费--IBM webSphere | Oracle weblogic
---------------------------------------------------------------------------------------------
tomcat
一个web server--支持http和https
server端(都支持)--client端(httpd支持,nginx不支持)
运行为一个Java进程,即:java(jvm)--内部主程序是tomcat,即:server
server(进程本身)--内部是帮助解析运行jsp页面程序文件
请求--server--connector(类)--service--engine--host--context
组件的层级关系 如下图1
除了这些组件,帮助完成其他功能--还有其他组件
connector(3种连接器组件):http https ajp(二进制协议,类似于fpm-fastcgi)
engine(引擎): 运行jsp代码的组件(tomcat最核心组件)
service(服务): 把一个或多个连接器与引擎绑定关联在一起
1个连接器只能属于1个引擎,但1个引擎可以有多个连接器(需要有对应关系)--service
1个service只能有1个engine
host: 虚拟主机
engine内部可以有多个host--一个host表示一个虚拟主机
engine-->主机名和端口-->host
一个host可以部署多个应用程序(pma+wordpress+...),每个应用放在一个url中
与PHP不同,java代码都是类文件,可能依赖类库中的其他类文件--类加载器加载完成后才能运行
a|b|c不同应用--加载不同的类文件--不好管理
context(上下文): 分开独立管理配置每一个应用程序及其环境--url实现 /path
单tomcat使用的内存空间不能超过32G
服务器128G--只运行tomcat--多起几个tomcat,充分利用资源
端口不是80
应用不能以管理员的身份运行--非管理员--不能用1024内的特权端口--默认8080
普通用户身份运行--改为80--也没有权限去监听--使用代理服务器代理tomcat
热部署--不停机可以增删host
内键的图形接口 host manager
管理应用程序 manager app
tomcat使用手册 docs
tomcat测试页面 使用jsp写程序的事例
图1
image.png
centos7.4--OpenJDK(yum安装)--192.168.1.6
yum list all tomcat*
tomcat.noarch 主程序
tomcat-lib.noarch 库文件
tomcat-admin-webapps.noarch 管理程序--host manager 和 manager app
tomcat-docs-webapp.noarch 文档documentation
tomcat-webapps.noarch 样例测试页面
tomcat-jsp-2.2-api.noarch jsp类库(程序包)
tomcat-servlet-3.0-api.noarch serverlet类库
tomcat--java程序--需要先编译成类文件
安装方式
1 yum直接安装(rpm包)
2 官方下载--编译好的版本--展开即用
下载源码(未编译)--需要先下载Maven构建器--把tomcat构建成字节码--头疼
项目管理器(项目构建工具):编译顺序,一个程序由不同的程序文件组成,很多依赖关系
c--make
java--ant(早期脚本管理工具)--Maven(xml文件格式定义)--grade(yaml格式定义其配置文件)
yum -y install tomcat-admin-webapps tomcat-docs-webapp tomcat-lib tomcat-webapps
less /usr/lib/systemd/system/tomcat.service
ExecStart=/usr/libexec/tomcat/server start
less /usr/libexec/tomcat/server
向Java虚拟机传递参数--启动一个类
MAIN_CLASS Bootstrap自举
CATALINA_HOME tomcat自己安装目录,应用程序类文件存放处
systemctl start tomcat
ss -ntlp 8080,8005,8009端口
浏览器:http://192.168.1.6:8080/ 测试页面
rpm -ql tomcat
/etc/tomcat 配置文件路径
/etc/sysconfig/tomcat 环境配置文件,修改JDK内存空间--上限和初始值
/usr/lib/systemd/system/tomcat.service unit-file
/usr/share/tomcat 默认安装路径
/usr/share/tomcat/conf-->/etc/tomcat-->主配置文件:server.xml
/usr/share/tomcat/lib-->/usr/share/java/tomcat 关键
/usr/share/tomcat/logs-->/var/log/tomcat
/usr/share/tomcat/temp-->/var/cache/tomcat/temp
/usr/share/tomcat/webapps-->/var/lib/tomcat/webapps webapps存放位置
/usr/share/tomcat/work-->/var/cache/tomcat/work 关键
/usr/share/tomcat/bin/bootstrap.jar tomcat启动
centos7.3--OracleJDK--192.168.1.5
官网下载:http://tomcat.apache.org/
rz 上传apache-tomcat-7.0.86.tar.gz
tar xf apache-tomcat-7.0.86.tar.gz -C /usr/local/
cd /usr/local/ ; ll
ln -sv apache-tomcat-7.0.86/ tomcat ; ll 创建符号链接,便于操作
cd /usr/local/tomcat ; ls bin/
shutdown.sh startup.sh configtest.sh version.sh
catalina.sh(可以调用其他脚本,放在path变量里)
bin/version.sh 显示版本
vim /etc/profile.d/tomcat.sh
export CATALINA_BASE=/usr/local/tomcat
export PATH=$CATALINA_BASE/bin:$PATH
. /etc/profile.d/tomcat.sh
echo $CATALINA_BASE
catalina.sh --help
catalina.sh run 运行在当前窗口
catalina.sh start 非加载安全策略的方式启动(运行在后端)
catalina.sh start -security 额外加载安全策略/usr/local/tomcat/conf/catalina.policy
catalina.sh version
catalina.sh start
ss -ntlp 8080,8005,8009端口
浏览器:http://192.168.1.5:8080/ 测试页面
ps aux 不要以root运行,切换到普通用户运行
useradd -r tomcat
chown -R tomcat:tomcat /usr/local/tomcat/*
ll /usr/local/tomcat/
su - tomcat -c "catalina.sh start" tomcat运行命令,并退出
ss -ntl 8080端口
ps aux tomcat身份运行tomcat
centos7.4 rpm包安装
vim /etc/tomcat/server.xml
Server
Service
Connector|...
Engine
Host 只有一个实现类
Valve(过滤) 有多个实现类--className类|... 属性赋值(把类实例化为一个对象)
访问控制,记录不同级别的访问日志,......
基于日志/IP/主机名/basic认证--做访问控制
详细内容参考文档
手动提供一测试类应用,并冷部署
centos7.4
systemctl status tomcat
systemctl stop tomcat
ll /usr/share/tomcat/
/usr/share/tomcat/webapps/-->/var/lib/tomcat/webapps/ 链接,一样内容
mkdir -p /usr/share/tomcat/webapps/test/{classes,lib,WEB-INF,META-INF}
vim /usr/share/tomcat/webapps/test/index.jsp
<%@ page language="java" %>
<%@ page import="java.util.*" %>
<html>
<head>
<title>Test Page</title>
</head>
<body>
<% out.println("hello world");
%>
</body>
</html>
systemctl restart tomcat ; ss -ntlp 8080端口
浏览器:http://192.168.1.6:8080/test/ ok,如图1
less /usr/share/tomcat/work/Catalina/localhost/test/org/apache/jsp/index_jsp.java
jsp--把页面中的非Java代码转换为Java代码后,存放在work目录下
jsp程序第一次访问--比较慢(内容较大的尤其如此)--需要编译为类文件.class
写一个脚本--主要页面都请求一次--让其编译完成
程序发生改变--需要重新编译
tomcat自动比较index.jsp和index_jsp.java时间戳(index.jsp较新,tomcat重新编译)
jsp程序的性能比php高2~6倍
浏览器:http://192.168.1.5:8080/ 测试页面--通过接口管理应用程序
点击"Manager App" 需要认证登陆
vim /etc/tomcat/tomcat-users.xml
在<tomcat-users>...</tomcat-users>标签内部定义
<role rolename="manager-gui"/>
允许用户通过图形界面访问状态页面和管理界面
<role rolename="manager-script"/>
允许用户通过文本接口(命令行操作)访问状态页面和管理界面
<role rolename="manager-jmx"/>
允许通过jmx代理访问状态页面和管理界面
jmx--Java-Management-Extension 扩展
JVM内部信息数据--(各个属性:内存空间/对象种类/垃圾收集...)
外部系统(监控系统)获取这些信息需要通过jmx接口--授权访问--防止信息泄露
<role rolename="manager-status"/> 查看状态信息
vim /etc/tomcat/tomcat-users.xml 如下图2
<role rolename="manager-gui"/>
<user username="tomcat" password="tomcat" roles="manager-gui"/>
systemctl restart tomcat
浏览器:http://192.168.1.5:8080/ 测试页面
点击"Manager App" 输入账号和密码--认证登陆
Expire session: 过期会话,超过多长时间就删除 leaks:查找漏洞
浏览(上传war文件"solo-2.8.0.war")并deploy(部署)--页面显示solo-2.8.0,如下图3
centos7.4 图形界面 firefox 192.168.1.7:8080
点击"Manager App"--点击"/solo-2.8.0"--如下图4
点击"Server Status" 如下图5
图1
image.png
图2
image.png
图3
image.png
图4
image.png
图5
image.png
centos7.3 IP变为192.168.1.6
centos7.4 IP变为192.168.1.7
浏览器:http://192.168.1.7:8080/ 测试页面
"Host Manager" 控制虚拟主机--添加|删除(无需删除即可部署)--热部署
ss -ntl 8005,8009,8080
8005端口监听在本机127.0.0.1上
yum -y install telnet
telnet 127.0.0.1 8005
SHUTDOWN
ss -ntl 8005,8009,8080所有端口关闭
不安全--更改端口或者更改命令
vim /etc/tomcat/server.xml
<Server port="8005" shutdown="SHUTDOWN">
openssl rand -hex 20
72572204d1e5b059898caf984970149ccd13468f
把"SHUTDOWN"命令替换为输出的20个16进制字符
LDAP/JDBC--用户认证系统(此处不做深究)
vim /etc/tomcat/server.xml
Connector配置 如下图1
Host配置 如下图2
<Host name="www.fgq.io" appBase="/data/webapps"
unpackWARs="true" autoDeploy="true">
</Host>
mkdir -p /data/webapps/ROOT/{classes,lib,WEB-INF,META-INF}
/data/webapps/ROOT/ 主程序存放此处,没有创建ROOT,会自动找ROOT目录
其他程序存放在/data/webapps下,清晰,将来移除会更加简单
vim /data/webapps/ROOT/index.jsp 测试页面
<%@ page language="java" %>
<html>
<head><title>TomcatA</title></head>
<body>
<h1><font color="red">TomcatA.fgq.io</font></h1>
<table align="centre" border="1">
<tr>
<td>Session ID</td>
<% session.setAttribute("fgq.io","fgq.io"); %>
<td><%= session.getId() %></td>
</tr>
<tr>
<td>Created on</td>
<td><%= session.getCreationTime() %></td>
</tr>
</table>
</body>
</html>
更改程序后,可以自动部署
systemctl restart tomcat ; ss -ntlp 处于正常监听状态,配置没问题
centos7.4-2
vim /etc/hosts
192.168.1.7 www.fgq.io
firefox http://www.fgq.io:8080/ 图形界面 如图3
部署应用程序javaee-bbs在context路径下
rz 上传文件
unzip javaee_v2.1.zip
把解压后的目录移动到我们创建的Host目录下
mv javaee_v2.1 /data/webapps 或
mv bbs /data/webapps
cd /data/webapps
ln -sv javaee_v2.1 bbs
ln -sv javaee_v2.1 javaee 创建链接-利于部署-出现错误-可以回滚-此处就不改了
ls bbs/WebRoot/
vim /etc/tomcat/server.xml
在设定的Host虚拟主机内部添加Context 如下图4
<Context path="/bbs" docBase="bbs/WebRoot" reloadable="true" />
systemctl restart tomcat ; ss -ntlp
centos7.4-2
firefox http://www.fgq.io:8080/bbs/ 图形界面-不能访问,此处配置ok即可,不多做了
注释掉添加的"Context"内容
浏览器:192.168.1.7:8080/
点击"Host Managr" 需要认证登陆
admin-gui - allows access to the HTML GUI 图形界面操作
admin-script - allows access to the text interface 命令行操作
vim /etc/tomcat/tomcat-users.xml 如图5
<role rolename="manager-gui"/>
<role rolename="admin-gui"/>
<user username="tomcat" password="tomcat" roles="manager-gui,admin-gui"/>
生产中,安全起见,最好分开(tomcat--后台,仅内网访问,可略)
systemctl restart tomcat ; ss -ntlp
点击"Host Managr" 登陆 如下图6
部署一个虚拟主机前,需要下面的操作
mkdir -p /data/feng/webapps/ROOT/{classes,lib,WEB-INF,META-INF}
vim /data/feng/webapps/ROOT/index.jsp
<%@ page language="java" %>
<html>
<head><title>TomcatB</title></head>
<body>
<h1><font color="blue">TomcatB.feng.io</font></h1>
<table align="centre" border="1">
<tr>
<td>Session ID</td>
<% session.setAttribute("feng.io","feng.io"); %>
<td><%= session.getId() %></td>
</tr>
<tr>
<td>Created on</td>
<td><%= session.getCreationTime() %></td>
</tr>
</table>
</body>
</html>
点击"Add"部署上线后,我们可以看到增加了一个虚拟主机
centos7.4-2
vim /etc/hosts
192.168.1.7 www.fgq.io www.feng.io
firefox http://www.feng.io:8080/ 图形界面 blue颜色变化 如图7
浏览器中点击"stop",停掉www.feng.io
systemctl stop tomcat ; ss -ntl
systemctl start tomcat ; ss -ntl
刷新浏览器界面,www.feng.io虚拟主机消失,即图形界面的配置是保存在内存中的
永久生效--更改配置文件
热部署--临时增加一个虚拟主机使其生效--也是一个方法
ls /var/log/tomcat/ 没有我们定义的主机的日志--需要设置
在Host主机内部定义Valve--虚拟主机的专用日志
vim /etc/tomcat/server.xml 如下图8
<Host name="www.fgq.io" appBase="/data/webapps"
unpackWARs="true" autoDeploy="true">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="fgq_access_log." suffix=".log"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
systemctl restart tomcat ; ss -ntl
centos7.4-2
firefox http://www.fgq.io:8080/
centos7.4
ls /var/log/tomcat/ 显示我们定义的日志--fgq_access_log.2018-04-24.log
图1
image.png
图2
image.png
图3
image.png
图4
image.png
图5
image.png
图6
image.png
图7
image.png
图8
image.png
反代用户请求 如下图1和2(不常用)
nt: nginx+tomcat 同一台机器上
centos7.4
yum -y install nginx
vim /etc/nginx/conf.d/tomcat.conf
server {
server_name www.feng.io;
listen 80;
location / {
proxy_pass http://192.168.1.7:8080;
}
}
请求www.feng.io,代理至192.168.1.7:8080
本机没有192.168.1.7这个主机--请求被代理至默认主机
nginx -t ; systemctl start nginx.service ; ss -ntl 80端口
centos7.4-2
firefox浏览器:www.feng.io--默认主机的测试页面(index.jsp)
vim /etc/nginx/conf.d/tomcat.conf
server {
server_name www.feng.io;
listen 80;
location / {
proxy_pass http://www.fgq.io:8080;
}
}
vim /etc/hosts
192.168.1.7 www.fgq.io 主机名解析--否则出错
nginx -t ; nginx -s reload
centos7.4-2
firefox浏览器:www.feng.io
代理至www.fgq.io:8080主机的测试页面(/data/webapps/ROOT/index.jsp)
注意:代理主机名和代理IP有区别的
vim /etc/nginx/conf.d/tomcat.conf
两个主机名都可以访问,定义2个server
:1,$y 第一行到最后一行复制,p粘贴
server {
server_name www.feng.io;
listen 80;
location / {
proxy_pass http://127.0.0.1:8080; 更改
}
}
server {
server_name www.fgq.io; 更改
listen 80;
location / {
proxy_pass http://www.fgq.io:8080;
}
}
nginx -t ; nginx -s reload
centos7.4-2
firefox浏览器:
www.feng.io 代理至默认主机127.0.0.1
www.fgq.io 代理至www.fgq.io:8080(测试页面/data/webapps/ROOT/index.jsp)
把所有请求都代理给tomcat,负担过重
只把动态内容代理给tomcat
静态内容--nginx处理
vim /etc/nginx/conf.d/tomcat.conf
如下图3 不完善
centos7.4-2 firefox浏览器
www.feng.io nginx测试页面
www.feng.io/index.jsp 动态页面
systemctl stop nginx
systemctl status nginx.service disabled不会自动启动
------------------------------------------------------------------------
at: httpd+tomcat 同一台机器上
centos7.4
yum -y install httpd
httpd -M
proxy_module (shared) proxy_ajp_module (shared) proxy_http_module (shared)
vim /etc/httpd/conf.d/tomcat_http.conf
<VirtualHost *:80>
ServerName www.fgq.io
ServerAlias www.feng.io 为一个主机提供多个主机名
ProxyRequests Off
ProxyVia On
ProxyPreserveHost On 把客户端请求的主机名传递至后端主机
<Proxy *>
Require all granted
</Proxy>
ProxyPass / http://127.0.0.1:8080
ProxyPassReverse / http://127.0.0.1:8080
<Location />
Require all granted
</Location>
</VirtualHost>
systemctl start httpd ; ss -ntl 80端口
centos7.4 firefox浏览器
www.fgq.io 第二个主机响应(后端Host有www.fgq.com)
www.fgq.io 默认主机响应--前提是"ProxyPreserveHost Off"--请求传递至192.168.1.7
www.feng.io 都是默认主机响应--不论"ProxyPreserveHost Off/On"
一个主机,2个主机名,响应时,使用不同的虚拟主机--灵活性
ajp协议
cp /etc/httpd/conf.d/tomcat_http.conf /etc/httpd/conf.d/tomcat_ajp.conf
vim /etc/httpd/conf.d/tomcat_ajp.conf
<VirtualHost *:80>
ServerName www.fgq.io
ServerAlias www.feng.io
ProxyRequests Off
ProxyVia On
ProxyPreserveHost On
<Proxy *>
Require all granted
</Proxy>
ProxyPass / ajp://127.0.0.1:8009
ProxyPassReverse / ajp://127.0.0.1:8009
<Location />
Require all granted
</Location>
</VirtualHost>
systemctl start httpd ; ss -ntl 80端口
centos7.4 firefox浏览器
www.fgq.io 第二个主机响应
www.feng.io 默认主机响应
浏览器:192.168.1.7:8080--host manager--server status--ajp
------------------------------------------------------------------------
nat: nginx httpd+tomcat 两台主机
centos7.4-3(192.168.1.9)
yum -y install nginx
vim /etc/nginx/conf.d/tomcat.conf
server {
listen 80;
server_name www.fgq.io www.feng.io;
index index.jsp index.html;
location / {
proxy_pass http://www.fgq.io; 把请求都代理至www.fgq.io
}
}
vim /etc/hosts
192.168.1.7 www.fgq.io www.feng.io
systemctl start nginx ; ss -ntl
centos7.4-2
vim /etc/hosts
192.168.1.9 www.fgq.io www.feng.io
firefox浏览器:
www.fgq.io和www.feng.io 都是第二个主机响应
没有把主机名真正的传递至与之对应的主机上
centos7.4-3
vim /etc/nginx/conf.d/tomcat.conf
要把主机名传递过去(不同主机名,响应不同内容)--再添加一个server
server {
listen 80;
server_name www.fgq.io ; 更改
index index.jsp index.html;
location / {
proxy_pass http://www.fgq.io;
}
}
server {
listen 80;
server_name www.feng.io;
index index.jsp index.html;
location / {
proxy_pass http://www.feng.io;
}
}
nginx -t ; nginx -s reload
centos7.4-2 firefox浏览器:
www.fgq.io 第二个主机响应
www.feng.io 默认主机响应
图1
image.png
图2
image.png
图3
image.png
图4
image.png
图5
image.png
如上图4--web架构
如上图5--实验拓扑
系统--不在物理服务器上--而是托管在云端--很多组件不需要自己构建
LBaaS(云端的负载均衡服务)--可以代替"负载均衡器"
DBaaS(云端的数据存储服务)--可以代替DBA--不需要自己维护存储系统
混合云--私有云和公有云都存储一份--备用
公有云+自己搞--存储公有云(七牛云)
3种环境
开发环境
测试环境
线上环境 云端/机房
centos7.4 192.168.1.7 tomcat
centos7.4-2 192.168.1.8 tomcat
centos7.4-3 192.168.1.6 nginx/httpd/haproxy
centos7.4-4 192.168.1.12 client
先同步时间,再配置,此处执行了计划任务
centos7.4,centos7.4-2 jdk,tomcat配置
yum -y install java-1.8.0-openjdk-devel tomcat-admin-webapps tomcat-webapps tomcat-lib tomcat-docs-webapp
mkdir -p /data/webapps/ROOT/{classes,lib,WEB-INF}
vim /etc/tomcat/server.xml 如下图1
<Host name="www.fgq.io" appBase="/data/webapps"
unpackWARs="true" autoDeploy="true">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="fgq_access_log." suffix=".log"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
注意:此处的主机名,centos7.4和centos7.4-2都是www.fgq.io
vim /data/webapps/ROOT/index.jsp--centos7.4
<%@ page language="java" %>
<html>
<head><title>TomcatA</title></head>
<body>
<h1><font color="red">TomcatA.fgq.io</font></h1>
<table align="centre" border="1">
<tr>
<td>Session ID</td>
<% session.setAttribute("fgq.io","fgq.io"); %>
<td><%= session.getId() %></td>
</tr>
<tr>
<td>Created on</td>
<td><%= session.getCreationTime() %></td>
</tr>
</table>
</body>
</html>
vim /data/webapps/ROOT/index.jsp--centos7.4-2
<%@ page language="java" %>
<html>
<head><title>TomcatB</title></head>
<body>
<h1><font color="blue">TomcatB.feng.io</font></h1>
<table align="centre" border="1">
<tr>
<td>Session ID</td>
<% session.setAttribute("feng.io","feng.io"); %>
<td><%= session.getId() %></td>
</tr>
<tr>
<td>Created on</td>
<td><%= session.getCreationTime() %></td>
</tr>
</table>
</body>
</html>
systemctl start tomcat ; ss -ntl 8080,8005,8009
浏览器:192.168.1.7:8080 ok; 192.168.1.8:8080 ok 没区别看不出来
cp -r /data/webapps/ROOT/ /usr/share/tomcat/webapps/test
浏览器:192.168.1.7:8080/test ok; 192.168.1.8:8080/test ok 区别出来
centos7.4-4
vim /etc/hosts
192.168.1.7 www.fgq.io
192.168.1.8 www.fgq.io
firefox浏览器:192.168.1.7:8080/test ok; 192.168.1.8:8080/test ok 可以区别出来
centos7.4-3 192.168.1.6 nginx负载均衡(调度)
yum -y install nginx
vim /etc/nginx/nginx.conf
添加upstream和location,如下图2
nginx -t ; systemctl start nginx.service
ss -ntl 80端口
浏览器:
192.168.1.6 ok
192.168.1.6/test ok
刷新会轮询出现192.168.1.7和192.168.1.8的内容,而且session id变化,会话丢失
ip_hash/cookie(此处不做会话保持),后面有简便的
systemctl stop nginx.service
centos7.4-3 192.168.1.6 haproxy负载均衡(调度)
yum -y install haproxy
vim /etc/haproxy/haproxy.cfg
删除原来的frontend和backend,添加新的frontend和backend 如下图3
光标移动至main上面的一行
.,$-2d 删除当前行至倒数第二行
frontend http-in
bind *:80
default_backend appsrvs
backend appsrvs
balance roundrobin
server app1 192.168.1.7:8080 check
server app2 192.168.1.8:8080 check
listen stats
bind *:9009
stats enable
systemctl start haproxy.service ; ss -ntl 9009和80端口
浏览器:
192.168.1.6:9009/haproxy?stats ok
192.168.1.6/test ok
刷新会轮询出现192.168.1.7和192.168.1.8的内容,而且session id变化
cookie会话保持(不做,参考haproxy文章)
systemctl stop haproxy.service
centos7.4-3 192.168.1.6 httpd负载均衡(调度)
yum -y install httpd
httpd -M
proxy_module proxy_ajp_module proxy_http_module
proxy_balancer_module
vim /etc/httpd/conf.d/tomcat_http.conf 如下图4
<proxy balancer://appsrvs>
BalancerMember http://192.168.1.7:8080
BalancerMember http://192.168.1.8:8080
ProxySet lbmethod=byrequests
</Proxy>
<VirtualHost *:80>
ServerName www.fgq.io
ProxyVia On
ProxyRequests Off
ProxyPreserveHost On
<Proxy *>
Require all granted
</Proxy>
ProxyPass / balancer://appsrvs/
ProxyPassReverse / balancer://appsrvs/
<Location />
Require all granted
</Location>
</VirtualHost>
httpd -t ; systemctl start httpd ; ss -ntl 80端口
浏览器:192.168.1.6/test ok
刷新会轮询出现192.168.1.7和192.168.1.8的内容,而且session id变化
使用ajp协议
cp /etc/httpd/conf.d/tomcat_http.conf /etc/httpd/conf.d/tomcat_ajp.conf
vim /etc/httpd/conf.d/tomcat_ajp.conf 如下图5
<proxy balancer://appsrvs>
BalancerMember ajp://192.168.1.7:8009
BalancerMember ajp://192.168.1.8:8009
ProxySet lbmethod=byrequests
</Proxy>
<VirtualHost *:80>
ServerName www.fgq.io
ProxyVia On
ProxyRequests Off
ProxyPreserveHost On
<Proxy *>
Require all granted
</Proxy>
ProxyPass / balancer://appsrvs/
ProxyPassReverse / balancer://appsrvs/
<Location />
Require all granted
</Location>
</VirtualHost>
httpd -t ; systemctl restart httpd ; ss -ntl 80端口
浏览器:192.168.1.6/test ok
刷新会轮询出现192.168.1.7和192.168.1.8的内容,而且session id变化
ajp协议的会话保持--增加首部信息--session sticky
vim /etc/httpd/conf.d/tomcat_ajp.conf 如下图6
Header add Set-Cookie "ROUTEID=.%{BALANCER_WORKER_ROUTE}e; path=/" env=BALANCER_ROUTE_CHANGED
<proxy balancer://appsrvs>
BalancerMember ajp://192.168.1.7:8009 route=tcA
BalancerMember ajp://192.168.1.8:8009 route=tcB
ProxySet lbmethod=byrequests
ProxySet stickysession=ROUTEID
</Proxy>
<VirtualHost *:80>
ServerName www.fgq.io
ProxyVia On
ProxyRequests Off
ProxyPreserveHost On
<Proxy *>
Require all granted
</Proxy>
ProxyPass / balancer://appsrvs/
ProxyPassReverse / balancer://appsrvs/
<Location />
Require all granted
</Location>
</VirtualHost>
httpd -t ; systemctl restart httpd ; ss -ntl 80端口
浏览器:192.168.1.6/test ok 刷新--session id无变化--会话保持
centos7.4-4:firefox浏览器: 192.168.1.6/test ok 刷新--session id无变化--会话保持
F12--cookie--.tcA/B
根据cookie绑定,即使同一个client用不同的浏览器访问,cookie也不同
设置并启用内键的管理状态页面
vim /etc/httpd/conf.d/tomcat_ajp.conf 如下图7
在最下方添加如下信息:
<Location /balancer-manager>
SetHandler balancer-manager
ProxyPass !
Require all granted
</Location>
httpd -t ; systemctl restart httpd ; ss -ntl 80端口
浏览器:192.168.1.6/balancer-manager ok 如下图8
会话保持另一种方法--session cluster(集群不能太大)
persistent manager 持久会话管理器(内存中)
周期性存储在磁盘的某个特定文件中--session.xxx
GDBC manager 持久会话管理器(磁盘中)--不常用(名字不准确)
把会话存储在外部的关系型数据库中--MySQL,Oracle
delta manager 增量(变化的意思,不一定是增加)--完成集群会话管理
节点多--会话多--资源消耗
backup manager 备用管理器
两个或多个节点互为备份,保留会话的一部分,使用在集群较多的环境(淘汰了)
集群较多的环境--现在用session server(下面有)
delta manager(此处使用)
把多个tomcat加入到一个集群
成员关系判定--集群中有几个节点--发送自己的增量数据给这些节点
所属的集群名字--判断加入那个集群
是否处于同一个多播域/多播地址--判断是否处于同一个集群中
同一个多播地址--此节点属于这个集群
此节点是否在这个集群中(网络故障导致下线)--周期性判定网络节点的健康状态
leader node--周期性判定网络节点的健康状态--低效
每个节点主动报告自己是否在线--高效
每个节点周期性向外传递自己的信息给leader node-->heart beat(心跳信息)
leader node--收集每个节点发来的报告--判断集群的节点数量
同时把当前的picture(节点报告状态)--同步给同一集群的其他节点(协作逻辑)
-----------------------------------------------------------------------------------------
相关概念了解--后面会细讲--此处不深究
分布式-->多个节点共同参与一个工作
分布式系统
Paxos协议--分布式系统受益于此协议--人类社会的缩影--人工智能
zookeeper--zab协议--zookeeper原子广播协议
etcd(docker)--raft协议--不挑战智商
tomcat--内部程序包含了这些功能,没有用这些协议
问题-->network partition(网络分区)--网络故障--节点找不到组织了--四分五裂
quorum机制--判断哪一部分可以代表组织继续工作
with quorum 拥有法定票数,才能代表组织继续工作
> total/2 大于总票数的一半
leader node在这里--ok,开始工作
leader node不在这里--启用投票机制(领导选举方式),选一个新领导
有选举权+无被选举权--观察者节点
有选举权+无被选举权--不能被选为领导
选举权+被选举权
node--先提(自己做leader)先得--得票数大于规定的基本票数--ok--leader
without quorum 不拥有法定票数,不能代表组织继续工作
<= total/2 小于等于总票数的一半
放弃组织成员的一切权力,不被使用,直到找到组织
分布式系统(多台主机工作)实现分布式协作时,只能满足3个功能的2个
ACP
分区容错性--P--一部分出错,一部分可以继续使用--必须的
可用性--A
一致性--C
平衡--AP/CP
-----------------------------------------------------------------------------------------
session cluster--delta manager
添加集群的相关设定
vim /etc/tomcat/server.xml(centos7.4--192.168.1.7)
在Engine行添加自己的id,在Engine下方添加cluster信息--到官网复制后更改
如下图9和图10
<Engine name="Catalina" defaultHost="localhost" jvmRoute="tcA">
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
channelSendOptions="8">
<Manager className="org.apache.catalina.ha.session.DeltaManager"
expireSessionsOnShutdown="false"
notifyListenersOnReplication="true"/>
<Channel className="org.apache.catalina.tribes.group.GroupChannel">
<Membership className="org.apache.catalina.tribes.membership.McastService"
address="228.110.110.4"
port="45564"
frequency="500"
dropTime="3000"/>
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
address="192.168.1.7"
port="4000"
autoBind="100"
selectorTimeout="5000"
maxThreads="6"/>
<Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
<Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
</Sender>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatch15Interceptor"/>
</Channel>
<Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
filter=""/>
<Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>
<Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
tempDir="/tmp/war-temp/"
deployDir="/tmp/war-deploy/"
watchDir="/tmp/war-listen/"
watchEnabled="false"/>
<ClusterListener className="org.apache.catalina.ha.session.JvmRouteSessionIDBinderListener"/>
<ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
</Cluster>
vim /etc/tomcat/server.xml(centos7.4-2--192.168.1.8)
如下图11
cp /etc/tomcat/web.xml /usr/share/tomcat/webapps/test/WEB-INF/
vim /usr/share/tomcat/webapps/test/WEB-INF/web.xml
在web-app标签内部添加信息:<distributable/> 如下图12
网络文档如下图13
systemctl stop tomcat.service
tail -f /var/log/tomcat/catalina.2018-04-26.log 输出的日志
systemctl start tomcat.service 再看日志--如下图14
centos7.4-3(使用nginx做代理服务器)
systemctl stop httpd.service ; ss -ntl 关闭httpd服务器,因为会话保持测试不出效果
systemctl start nginx.service ; ss -ntl
浏览器:192.168.1.6/test/ 刷新后,虽然调度到不同的主机,但是会话还是一致的
如下图15和图16
会话集群--无论调度至哪个节点--会话是一致的
centos7.4-3(使用haproxy做代理服务器)
systemctl stop nginx.service ; ss -ntl
systemctl start haproxy.service ; ss -ntl 80和9009端口
浏览器:192.168.1.6/test/ 刷新后,虽然调度到不同的主机,会话仍然是一致的
图1
image.png
图2
image.png
图3
image.png
图4
image.png
图5
image.png
图6
image.png
图7
image.png
图8
image.png
图9
image.png
图10
image.png
图11
image.png
图12
image.png
图13
image.png
图14
image.png
图15
image.png
图16
image.png
NoSQL(非关系型数据库)
memcached:cache(无持久功能)--内存中,down机则数据丢失,50~100万个事务数
redis:store service(有持久功能)--k/v,50~100万个事务数(普通的pc-server就可以)
MySQL(关系型数据库) 50个事务数
MongoDB和CouchDB(文档存储)/...
k/v store,document store,列存储,graphe store
缓存介绍--如下图1
读多写少--如下图2
memcached--参考文档
yum info memcached
yum -y install memcached
rpm -ql memcached
memcached -h
rpm包安装(yum)默认生成一个memcached的用户
memcached内存空间分配的介绍,如下图3
memcached -u memcached -vv
memcached -u memcached -f 1.5 -vvv slab class变少了
cat /etc/sysconfig/memcached
CACHESIZE="64" 生产中会调整
OPTIONS="" 把支持的选项填进去: -d ...
-U 0 关闭udp
cat /usr/lib/systemd/system/memcached.service
ExecStart=/usr/bin/memcached -u $USER -p $PORT -m $CACHESIZE -c $MAXCONN $OPTIONS
更改/etc/sysconfig/memcached文件,此处直接生效
我们做测试就不改了
systemctl start memcached.service
ss -ntlu udp/tcp 11211端口
memcached-tool 连接至哪台服务器,发送一些命令
memcached-tool 127.0.0.1 stats 统计数据项
auth_cmds 认证多少次
cmd_get 用户查询多少次
cmd_set 设定内存数据多少次
cas_hits 命中多少次(不同数据类型,命中方式不同)
get_hits 查询命中多少次
delete_hits 删除命中多少次
decr_hits decr命中多少次
...
memcached-tool 127.0.0.1 dump 显示键值
没有存储任何数据
yum info libmemcached 存数据
memcat 显示键值
memcp 复制数据
memdump 显示键值
memflush 清空数据库
memping 探测服务器存活
...
yum -y install libmemcached
memping -h
memping --servers=127.0.0.1:11211 没有信息就是最好的消息
yum -y install telnet
less /usr/share/doc/memcached-1.4.15/protocol.txt
命令的用法
<command name> <key> <flags> <exptime> <bytes>
flags 0-65535的数字
telnet 127.0.0.1 11211
stats
add mykey 1 300 11 存储键值
hello world 输入要存入的键值(字节数要和上面对应),显示"STORED"存储成功
get mykey 显示键值,一旦过期,get时,不会出现数据
set mykey 1 300 15 更改数据
hello ilinux.io 输入变更后的数据
get mykey
删除/...
add count 1 3600 1
0 输入数字
get count
incr count 8 增加8,回车后自动显示变更后的结果
decr count 3 减少3
stats 可以看到,不同命令的命中次数
memcached-tool 127.0.0.1:11211 dump
flush_all 清除数据--标记为无效,并非真的清除
memcached-tool 127.0.0.1:11211 dump 可以看到有items,但无内容
程序--通过驱动--连接至存储
php连接mysql php-myslq
php连接memcached php-pecl-memcache(base) php-pecl-memcached(epel)
yum list all *memcache* 文档也有
图1
image.png
图2
image.png
图3
image.png
会话保持的第三种方法--session server(性能好,有冗错能力)
把会话存储在服务器上,tomcat不支持,使用第三方应用msm(memcached-session-manager)
tomcat会话管理器--msm--支持将session保存到这样的存储系统中(session server)
代码托管网站www.github.com
搜索"tomcat session",使用第三方应用msm
https://github.com/magro/memcached-session-manager
文档
https://github.com/magro/memcached-session-manager/wiki/SetupAndConfiguration
msm(memcached-session-manager)
double writing功能
同时写两份数据到主节点和从节点
failover功能
从"主节点"读取数据--主节点down机--自动切换为另一个节点(健康状态检测和切换)
memcached仅存储流式化数据,jsp(Java语言),纯面向对象;
内存中的会话(对象式的)存储到memcached,再获取,不是原样的;
msm--流式化框架完成数据流式化
基于众多应用管理会话:redis/couchbase/memcached;
建议会话保存在redis; 性能(同memcached)+持久存储能力
数据--流式化--存储--读取
序列化工具介绍 如下图1 文档网页
配置第三方工具可用,需要手动整合进来几个类库 如下图2 文档网页
存储不同,用到的组件不同
我们配置session server
存储 memcached
序列化工具 javolution-serializer
拓扑
centos7.4 192.168.1.7 centos7.4-2 192.168.1.8 centos7.4-3 192.168.1.6
centos7.4和centos7.4-2都安装tomcat+memcached(相当于是四台主机)
centos7.4已经安装了tomcat+memcached
centos7.4-2已经安装了tomcat,但是没有安装memcached
centos7.4-2
yum -y install memcached
systemctl start memcached.service 将来使用时,最起码要更改内存大小
ss -ntlu udp,tcp-11211端口
删除之前配置文件中添加的<Cluster...Cluster/>,与"session server"不兼容
centos7.4和centos7.4-2
systemctl stop tomcat.service
vim /etc/tomcat/server.xml
:107,146d
下载工具包并上传文件
https://github.com/magro/memcached-session-manager
http://www.java2s.com/Code/Jar/j/Downloadjavolution5431jar.htm
javolution-5.4.3.1.jar.zip 需要解包
memcached-session-manager-2.3.0.jar
memcached-session-manager-tc7-2.3.0.jar
msm-javolution-serializer-2.1.1.jar
spymemcached-2.9.1.jar
rpm -ql tomcat-lib .jar文件都存放在/usr/share/java/tomcat/
cd /usr/share/java/tomcat/
rz 上传5个文件
unzip javolution-5.4.3.1.jar.zip
更改配置文件,添加Context
centos7.4和centos7.4-2
vim /etc/tomcat/server.xml
<Context path="/test" docBase="test" reloadable="true">
<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes="n1:192.168.1.7:11211,n2:192.168.1.8:11211"
failoverNodes="n2"
requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
transcoderFactoryClass="de.javakaffee.web.msm.serializer.javolution.JavolutionTranscoderFactory"
/>
</Context>
systemctl start tomcat ; ss -tnl 8080,8005,8009端口
tail -f /var/log/tomcat/catalina.2018-04-27.log 看日志是否出错
显示"INFO: Server startup" ok
centos7.4-3
systemctl stop haproxy.service
systemctl start nginx.service
浏览器:
http://192.168.1.6/test/ 如下图3和4
http://192.168.1.7:8080/test/ ok haproxy做代理,就不能访问后端服务器
http://192.168.1.8:8080/test/ ok
centos7.4-4:firefox浏览器:http://192.168.1.6/test/ ok
centos7.4:systemctl stop memcached.service n1挂掉
centos7.4-4:firefox浏览器:http://192.168.1.6/test/ ok,标识符变为n2
centos7.4:systemctl start memcached.service n1启用
centos7.4-4:firefox浏览器:http://192.168.1.6/test/ ok,标识符仍是n2,n1为备用
redis做会话存储以后讲
https://github.com/search?utf8=%E2%9C%93&q=tomcat+session
图1
image.png
图2
image.png
图3
image.png
图4
image.png
图5
image.png
图6
image.png
Tomcat的常用优化配置
内存分析 如上图5和图6
内存优化
centos7.4
free -m 查看内存信息:总内存/已用内存/剩余内存
vim /etc/sysconfig/tomcat
默认没有启用,添加信息即可
JAVA_OPTS="-server -Xms80m -Xmx100m"
systemctl restart tomcat ; ss -ntl
jps 看Bootstrap的进程编号
cat /proc/26503/cmdline 看Bootstrap启动时启用了哪些参数,显示我们定义的参数
centos7.4-2没有定义就不会显示出参数
线程池
启用URIEncoding属性 以http为例
vim /etc/tomcat/server.xml
Connector的HTTP协议中,操作,如下图1
...
JVM常用的分析工具
jsp 看Bootstrap的id
jinfo
jinfo -flags
jinfo -flags 26503(Bootstrap的进程编号) 显示参数信息
jinfo -sysprops 26503 Java system properties
jps -v
jstat -options
jstat -gc 26503
S0C S1C 容量--capacity Survivor
S0U S1U 利用情况--utilization Survivor
EC EU 新生代
OC OU 老年代
MC MU 元空间
YGC--新生代垃圾回收次数 YGCT--新生代垃圾回收时间
FGC--full gc 次数 FGCT--full gc 时间
GCT--total gc 时间
jstat -gc 26503 -1000 1s显示1次
jstat -gc 26503 -1000 3 3次后退出
jconsole 图形界面工具
centos7.4图形界面连接,输入命令--不安全连接即可--如下图2
连接后,如下图3
jvisualvm 图形界面工具(centos7.4--yum安装时,没有此工具--可能少安装了某个包)
centos7.3图形界面连接(centos7.3前面实验安装过官网下载的tomcat)
catalina.sh start 启动tomcat
jvisualvm 如下图4
连接tomcat 如下图5
了解有这些工具即可
图1
image.png
图2
image.png
图3
image.png
图4
image.png
图5
image.png
网友评论