JAVA
JAVA一直作为企业级应用编程的不二选择,其核心理念“一次编译,到处运行”,也一直多年来位于全世界编程语言榜首,一起从运维视角探究java和tomcat。
JAVA的体系结构规范
- java编程语言
- java class文件格式
- java api
- java vm
java语言具有简单性、面向对象、分布式、健壮性、安全性、平台独立与可移植性、多线程、动态性等特点,也是越来越多企业级项目转向java开发的原因,java作为纯面向对象的编程,所以的对象都是需要通过类来实现的,整个java语言的运行大致过程为: .java–>.class–>class loader–>JVM–>执行引擎
JVM的运行时区域:
- 方法区:线程共享,用于存储被jvm加载的class信息,常量,静态变量,方法等;持久代
- 堆:是jvm所管理的内在的最大的一部分,也是GC管理的主要区域;主流的垃圾收集算法基于分代收集机制
- java栈:线程私有,存储线程自己的局部变量
- PC寄存器:线程私有的内存空间,程序的指令指针
- 本地方法栈:调用本地c库
JAVA体系:
- JAVA 2 SE:JDK
OpenJDK;OracleJDK - JAVA 2 EE:JDK+企业级类
Servlet;JSP;EJB;JMS;JMX;JavaMail… - JAVA 2 ME:移动领域
Servlet+JSP构建了如今JAVA web编程的基础:
Serlet相当于为CGI提供解析成html的格式输出,而html标签需要硬编码进java代码,极其不便。
JSP为JAVA代码嵌入进html标签,java无须硬编码html标签。
Servlet index.java->javac->index.class->class loader->jvm
JSP index.jsp ->jsper->index_jsp.java->javac->index_jsp.class->class loader->jvm
Web Container
为了实现java在运行过程中自动进行通过javac编译,我们需要可以提供JAVA 2 EE的容器,而这样的web容器有许多,其中最著名的开源实现就是tomcat。
tomcat大致的实现构造,也是我们配置tomcat需要考虑的构造:
tomcat的配置文件都是通过xml文件来实现,其大致配置结构如下:
1 | tomcat: |
2 | <server> |
3 | <service> |
4 | <Connector> |
5 | <Conector> |
6 | <Engine> |
7 | <Host> |
8 | <Context> |
9 | ... |
10 | </Host> |
11 | <Host> |
12 | ... |
13 | </Host> |
14 | <Engine> |
15 | </service> |
16 | </server> |
tomcat本身是通过java实现的,所以全部的组件也都是遵循java,每个组件都是通过类来实现。
此些组件可分为如下几类:
- 顶级组件:server
- 服务组件:service
- 连接器组件:http https ajp
- 容器类:Engine Host Context
- 被嵌套组件:valve logger realm loader manager
- 集群类组件:listener…
安装tomcat
tomcat由java实现所以它本身就依赖java运行环境,所以得先安装JDK:
1、安装openjdk
1 | ~]# yum install -y java-1.7.0-openjdk java-1.7.0-openjdk-devel |
2 | ~]# which java |
3 | /usr/bin/java |
4 | ~}# ll /usr/bin/java |
5 | lrwxrwxrwx. 1 root root 22 May 29 04:19 /usr/bin/java -> /etc/alternatives/java |
6 | ~]# ll /etc/alternatives/java |
7 | lrwxrwxrwx. 1 root root 76 May 29 04:19 /etc/alternatives/java -> /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.141-2.6.10.1.el7_3.x86_64/jre/bin/java |
8 | |
9 | 所以当我们同时存在多版本的openjdk的时候,可以通过alternatives来切换openjdk |
10 | |
11 | ~]# vim /etc/profile.d/java.sh |
12 | JAVA_HOME=/usr |
13 | export JAVA_HOME |
2、安装oraclejdk
这个需要去oracle官网下载oraclejdk,建议使用rpm包
1 | ~]# rpm -ivh jdk-7u80-linux-x64.rpm |
2 | ~]# cd /usr/java/ |
3 | ~}# ll |
4 | total 4 |
5 | lrwxrwxrwx. 1 root root 16 May 28 05:46 default -> /usr/java/latest |
6 | drwxr-xr-x. 8 root root 4096 May 28 05:46 jdk1.7.0_80 |
7 | lrwxrwxrwx. 1 root root 21 May 28 05:46 latest -> /usr/java/jdk1.7.0_80 |
8 | ~]# vim /etc/profile.d/java.sh |
9 | JAVA_HOME=/usr/java/latest |
10 | export JAVA_HOME |
1、通过yum来安装tomcat
1 | ~]# yum install -y tomcat tomcat-lib tomcat-webapps tomcat-admin-webapps |
2、通过tomcat.apache.org下载tomcat二进制安装
1 | ~]# tar xf apache-tomcat-7.0.78.tar.gz -C /usr/local/ |
2 | ~]# ln -s /usr/local/apache-tomcat-7.0.78 /usr/local/tomcat |
3 | ~]# vim /etc/profile.d/catalina.sh |
4 | CATALINA_BASE=/usr/local/tomcat |
5 | PATH=$PATH:$CATALINA_BASE/bin |
6 | export PATH CATALINA_BASE |
tomcat目录结构:
- bin:脚本,及启动时用到的类
- lib:类库
- conf:配置文件
- logs:日志文件
- webapps:默认的部署目录
- work:工作目录
- temp:临时文件目录
tomcat的配置文件:
- server.xml:主配置文件
- context.xml:每个webapp都可以有专用的配置文件,这些配置文件通常位于webapp应用程序自己目录下的WEB-INF目录中,此context.xml为每个webapp提供默认配置
- web.xml:每个webapp只有在部署后才能被访问,此文件则用于为各webapps定义默认的部署方式,每个webapp都可以有专用的配置文件,这些配置文件通常位于webapp应用程序自己目录下的WEB-INF目录中。
- tomcat-user.xml:用户认证的账号和密码文件
- catalina.policy:当使用-security选项来启动tomcat实例时,会取此配置文件来实现安全策略的运行方式
- catalina.properties: java属性的定义文件,用于设定类加载器路径,以及一些于jvm调优相关的参数等
- logging.properties: 日志系统相关配置
JSP WebAPP的组织结构:
/:webapps的根目录
- index.jsp主页
- WEB-INF/:当前webapp的私有资源的目录,通常存放当前webapp自用的web.xml
- META-INF/:当前webapp的私有资源的目录,通常存放当前webapp资源的context.xml
- classes/:类文件,当前webapp的私有类
- lib/:当前webapp的私有类,被打包成jar格式
webapp归档格式:
- .war:webapp
- .jar:EJB的打包文件
- .rar:资源适配器
- .ear:企业级应用
手动测试tomcat应用的方法:
1、创建webapp特有的目录结构
mkdir -p myapp/{classes,WEB-INF,META-INF,lib}
2、提供webapp的测试页面
myapp/index.jsp
1 | <%@ page language="java" %> |
2 | <%@ page import="java.util.*" %> |
3 | <html> |
4 | <head> |
5 | <title>JSP Page</title> |
6 | </head> |
7 | <body> |
8 | <% out.println("hello world!"); %> |
9 | </body> |
10 | </html> |
tomcat自带的应用程序:
manager app:webapp管理工具
host manager:vhost管理工具
如果想要访问这些app管理工具,可以在/PATH/TO/TOMCAT/conf/tomcat-users.xml
1 | <role rolename="manager-gui"/> #manager app |
2 | <role rolename="admin-gui"/> #host manager |
3 | <user username="tomcat" password="tomcat" roles="manager-gui,admin-gui"/> |
重启tomcatcatalina.sh stop && catalina.sh start
可以查看整个tomcat的运行情况
应用管理,支持热部署
虚拟主机管理,支持直接创建虚拟主机
tomcat配置文件
1 | ~}# cat /usr/local/tomcat/conf/server.xml |
2 | <Server port="8005" shutdown="SHUTDOWN"> |
3 | <!--Server元素代表整个Catalina Servlet容器,是Tomcat实例的顶级元素; |
4 | port,指定Tomcat服务器监听shutdown命令的端口; |
5 | shutdown,指定当终止Tomcat服务器时,发送给它的shutdown监听端口的字符串。 --> |
6 | <Listener className="org.apache.catalina.startup.VersionLoggerListener" /> |
7 | <!-- className,指定实现此Server接口的类。--> |
8 | |
9 | <Service name="Catalina"> |
10 | <!-- Service元素用于关联一个引擎和与此引擎相关的连接器; |
11 | name,用于定义Service的名字; |
12 | className,指定实现此Service接口的类--> |
13 | <Connector port="8080" protocol="HTTP/1.1" |
14 | connectionTimeout="20000" |
15 | redirectPort="8443" /> |
16 | <!-- Connector元素是与客户端交互的组件; |
17 | port,设定监听端口号; |
18 | protocol,设定使用的协议; |
19 | connectionTimeout,定义超时时长,以毫秒为单位; |
20 | redirectPort,如果某连接器支持的协议是http,当接收到https请求时,转发至此属性定义的端口; |
21 | enableLookups,是否支持服务器对客户端进行域名解析。 --> |
22 | |
23 | |
24 | <Connector port="8443" protocol="org.apache.coyote.http11.Http11AprProtocol" |
25 | maxThreads="150" SSLEnabled="true" > |
26 | <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" /> |
27 | <SSLHostConfig> |
28 | <Certificate certificateKeyFile="conf/localhost-rsa-key.pem" |
29 | certificateFile="conf/localhost-rsa-cert.pem" |
30 | certificateChainFile="conf/localhost-rsa-chain.pem" |
31 | type="RSA" /> |
32 | </SSLHostConfig> |
33 | </Connector> |
34 | <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> |
35 | |
36 | <Engine name="Catalina" defaultHost="localhost"> |
37 | <!-- Engine是Servlet处理器的一个实例,即Servlet引擎; |
38 | name,定义Engine的名字; |
39 | defaultHost:指定处理客户端请求的默认主机名; |
40 | jvmRoute,定义Tomcat路由标示。 --> |
41 | |
42 | <Realm className="org.apache.catalina.realm.LockOutRealm"> |
43 | |
44 | <Realm className="org.apache.catalina.realm.UserDatabaseRealm" |
45 | resourceName="UserDatabase"/> |
46 | </Realm> |
47 | |
48 | <Host name="localhost" appBase="webapps" |
49 | unpackWARs="true" autoDeploy="true"> |
50 | <!-- 定义用于接收客户端请求并进行相应处理的主机或虚拟主机; |
51 | name,定义虚拟主机的名字; |
52 | appBase,指定虚拟主机的目录,可以指定绝对路径,也可以指定相对于<CATALINA_HOME>的相对路径; |
53 | unpackWARs,在启用此WebApp时是否对WAR格式的归档文件先进行展开; |
54 | autoDeploy,在Tomcat处于运行状态时放置于appBase目录下的应用程序文件是否自动进行部署; |
55 | alias,指定虚拟主机的别名,可以指定多个别名。 --> |
56 | <Context path="/bbs" |
57 | docBase="/web/threads/bbs" |
58 | reloadable="true"> |
59 | </Context> |
60 | <!-- Context在某些意义上类似于apache中的路径别名,一个Context定义用于标识Tomcat实例中的一个Web应用程序; |
61 | path,指定访问该Web应用的URL(相对于此Web服务器根路径)入口,如果为"",则表示为此Webapp的根路径; |
62 | docBase,指定Web应用的存放位置; |
63 | reloadable,是否允许重新加载此context相关的Web应用程序相关的类; --> |
64 | |
65 | <Valve className="org.apache.catalina.authenticator.SingleSignOn" /> |
66 | |
67 | <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" |
68 | prefix="localhost_access_log" suffix=".txt" |
69 | pattern="%h %l %u %t "%r" %s %b" /> |
70 | <!-- 定义日志格式; |
71 | directory:指定于log存放的目录 |
72 | prefix:指定日志的前缀格式 |
73 | suffix:指定日志的结尾 |
74 | pattern:日志格式定义,可以参照httpd的宏定义 |
75 | --!> |
76 | </Host> |
77 | </Engine> |
78 | </Service> |
79 | </Server> |
每一个组件都是通过特定的类来实现的,而且实现的方法不止一种:
Server: tomcat实例:即运行的一个JVM进程,监听于8005端口接受SHUTDOWN,各Server监听的端口不能相同,因此,一个物理主机上启动多个Server实例应该使用不同的端口。
Service:用于实现将一个或多个Connector关联至一个Engine
Connector组件:
进入tomcat的请求可分为两类
tomcat自己作为独立的应用程序服务器:standalone,此时,请求将来之于浏览:
http,https
tomcat作为应用程序服务器:请求将来之于前面的反代主机
httpd:http,https,ajp
nginx:http,https
属性:1
address:监听的ip地址
2
maxThreads:最大并发连接数,默认为150
3
ort:监听的端口
4
protocol:连接器使用的协议,一般为HTTP/1.1或AJP/1.3
5
redirectPort:
6
connectionTimeout:连接的超时时长,单位为毫秒,默认为60000
7
enableLookups:
8
acceptCount:定义等待的队列的长度
9
scheme:
10
debug
11
secure
12
clientAuth
13
sslProtocol
Engine:Servlet的一个实例,即Servlet引擎,其内部可以有一个或多个Host组件来定义站点,通常需要通过defaultHost的属性定义默认虚拟主机
属性:1
name
2
defaultHost
3
jvmRoute
Host:位于Engine容器中用于接受请求并进行相应处理的主机和虚拟主机
常用属性:1
appBase:此host的webapps目录,即存放非归档的web应用程序的目录或归档后的war文件的目录路径;可以使用基于$CATALINA_HOME的相对路径
2
autoDeploy:在tomcat处于运行状态时放置于appBase目录下的应用程序文件是否自动进行deploy,默认为true
3
unpackWars:在启动此webapps时是否对WAR格式的归档文件先进行展开,默认为true
虚拟主机定义实例:
1
<Engine name="Catalina" defaultHost="localhost">
2
<Host name="localhost" appBase="webapps">
3
<Context path="" docBase="ROOT"/>
4
<Context path="/bbs" docBase="/www/bbs"
5
reloadable="true" crossContext="true"/>
6
</Host>
7
8
<Host name='jusene.com' appBase="/data/www">
9
</Host>
10
</Engine>
Context组件:
在某些意义上类似apache中的路径别名,一个context定义表示一个tomcat实例中的web应用程序;1
<Context path='/chat' docBase="/web/chat"/>
在tomcat6中,每一个context定义也可以使用一个xml文件进行,其文件的目录为$CATALINTA_HOME/conf/{engine name}/{hostname},可以用于Context中的xml元素有Loader,Manager,Realm,Resource和WatchdResource.
常用的属性定义有:
docBase:相应的web应用程序的存放位置,也可以使用相对路径,起始路径为此Context所属Host中的appBase定义的路径,切记,docBase的路径名不能与相应的Host中appBase中定义的路径名有包含关系,比如,如果appBase为deploy,而docBase绝不能为deploy-bbs类的名字 path:相对于web服务器的根路径而言的url,如果为空,则表示为此webapp的根路径,如果context定义在一个单独的xml文件中,此属性不需要定义
reloadable:是否允许重新加载此context相关的web应用程序的类,默认为falseRealm组件:
一个Realm表示一个安全上下文,它是一个授权访问某个Context的用户列表和某用户所允许切换的角色相关定义的列表,因此,Realm就像是一个用户和组织相关的数据库,定义Realm时唯一必须提供的属性是classname,它是Realm的多种不同实现,用于表示此Realm认证的用户及角色等认证信息的存放位置。
JAASRealm:基于java authintication and authorization service实现用户认证:
JDBCRealm:通过jdbc访问某关系性数据库表用户认证
JNDIRealm:基于jndi使用目录服务实现认证信息的获取,ldap
MemoryRealm:查找tomcat-users.xml文件实现用户信息的获取
UserDataseRealm:基于UserDatabase文件(通常是tomcat-user.xml)实现用户认证,它实现了一个完全可更新和持久有效的MemoryRealm,因此能够根标准的memoryrealm兼容,它通过JNDI实现
下面是一个常见的userdatabase的配置:1
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
2
resourceName="UserDatabase"/>
下面是一个使用JDBC方式获取用户认证信息的配置:
1
<Realm className="org.apache.catalina.realm.JDBCRealm" debug=99
2
driveName="org.gjt.mm.mysql.Driver"
3
connectionURL="jdbc:mysql://localhost/authority"
4
userTable="users" userNameCol="user_name"
5
userCredCol="user_pass"
6
userRoleTable="user_roles" roleNameCol="role_name" />
Valve组件
Valve类似于过滤器,它可以工作于engine和host/context 之间,host和context之间以及context和web应用程序的某资源之间,一个容器内可以建立多个Valve,而且Valve定义的次序也决定了它们生效的次序,Tomcat6种实现了多种不同的Valve.
AccessLogValve:访问日志Valve
RemoteAddrValve:基于远程地址的访问控制
RemoteHostValve:基于远程主机名的访问控制
AccessLogValve:1
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
2
prefix="localhost_access_log." suffix=".txt"
3
pattern="%h %l %u %t "%r" %s %b" />
RemoteHostValve和RemoteAddrValve可以通过基于ip活着主机名的方式来进行访问控制,控制本身可以通过allow和deny来进行定义:
1
<Context path="/probe" docBase="probe">
2
<Valve className="org.apache.catalina.valves.RemoteAddrValve"
3
allow="127\.0\.0\.1"/>
4
</Context>
其中相关的属性定义:
calssroom:相关的java实现的类名,相当于分别应该为org.apache.catalina.valves.RemoteHostValve或org.apache.catalina.RemoteAddrValve
allow: 以逗号分开的允许访问的ip地址列表,支持正则表达式,因此,点号“.”用于ip地址时需要转义;仅定义allow时,非明确allow的地址均为deny
deny:以逗号分开的禁止访问的ip地址列表,支持正则表达式,使用方法同allow
LNMT
1 | server { |
2 | listen 80; |
3 | server_name www.jusene.com; |
4 | location / { |
5 | proxy_pass http://127.0.0.1:8080; |
6 | proxy_set_header Host $host; |
7 | proxy_set_header X-Real-IP $remote_addr; |
8 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; |
9 | } |
10 | } |
tomcat获取真实ip
1 | <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" |
2 | prefix="localhost_access_log." suffix=".txt" |
3 | pattern="%h %{X-Real-IP}i %l %u %t "%r" %s %b" /> |
LAMT
client–>http–>httpd–>reverse_proxy_module(http)–>tomcat(http connector)
client–>http–>httpd–>reverse_proxy_module(ajp)–>tomcat(ajp connector)
第一种方式:proxy_module;proxy_http_module
1
<VirtualHost *:80>
2
ServerName www.jusene.com
3
ProxyRequests Off #关闭正向代理
4
ProxyVia On #开启代理经过的server
5
ProxyPreserveHost On #开启透传host头部
6
<Proxy *>
7
Require all granted #代理授权控制
8
</Proxy>
9
ProxyPass / http://127.0.0.1:8080/
10
ProxyPassReverse / http://127.0.0.1:8080/ #支持代理重新回写url
11
<Location />
12
Require all granted #根授权,httpd2.4默认根拒绝访问
13
</Location>
14
</VirtualHost>
第二种方式:proxy_module;proxy_ajp_module(官方建议这样的反向代理)
1
<VirtualHost *:80>
2
ServerName www.jusene.com
3
ProxyRequests Off #关闭正向代理
4
ProxyVia On #开启代理经过的server
5
ProxyPreserveHost On #开启透传host头部
6
<Proxy *>
7
Require all granted #代理授权控制
8
</Proxy>
9
ProxyPass / ajp://127.0.0.1:8009/
10
ProxyPassReverse / ajp://127.0.0.1:8009/ #支持代理重新回写url
11
<Location />
12
Require all granted #根授权,httpd2.4默认根拒绝访问
13
</Location>
14
</VirtualHost>