1.haproxy https实现
haproxy可以实现https的证书安全,从用户到haproxy为https,从haproxy到后端服务器用http通信但基于性能考虑,生产中证书都是在后端服务器比如nginx上实现。
#配置HAProxy支持https协议,支持ssl会话;
bind *:443 ssl crt /PATH/TO/SOME_PEM_FILE
#指令 crt 后证书文件为PEM格式,需要同时包含证书和所有私钥
cat demo.key demo.crt > demo.pem
#把80端口的请求重定向到443端口
bind *:80
redirect scheme https if !{ ssl_fc }
#向后端传递用户请求的协议和端口(frontend或backend)
http_request set-header X-Forwarded-Port %[dst_port]
http_request add-header X-Forwared-Proto https if { ssl_fc }
准备环境
1.Haproxy 10.0.0.7
2.Nginx-01 10.0.0.8
3.Nginx-02 10.0.0.18
1.1制作自签名证书
[root@centos7 ~]mkdir /etc/haproxy/certs/
[root@centos7 ~]cd /etc/haproxy/certs/
[root@centos7 certs]#openssl genrsa -out haproxy.key 2048
[root@centos7 certs]#openssl req -new -x509 -key haproxy.key -out haproxy.crt -subj "/CN=www.ceshi.org"
#或者用下一条命令实现
[root@centos7 certs]#openssl req -x509 -newkey rsa:2048 -subj "/CN=www.ceshi.org" -keyout haproxy.key -nodes -days 365 -out haproxy.crt
[root@centos7 certs]#cat haproxy.key haproxy.crt > haproxy.pem
[root@centos7 certs]#openssl x509 -in haproxy.pem -noout -text #查看证书
1.2https配置
[root@centos7 ~]#cat /etc/haproxy/conf.d/test.cfg
frontend ceshi_http_port
bind 10.0.0.7:80
###################### https setting ##############################
bind 10.0.0.7:443 ssl crt /etc/haproxy/certs/haproxy.pem
redirect scheme https if !{ ssl_fc } # 注意{ }内的空格
http-request set-header X-forwarded-Port %[dst_port]
http-request add-header X-forwarded-Proto https if { ssl_fc }
mode http
balance roundrobin
log global
option httplog
###################### acl setting ###############################
acl mobile_domain hdr_dom(host) -i mobile.ceshi.org
###################### acl hosts #################################
default_backend pc_hosts
################### backend hosts #################################
backend mobile_hosts
mode http
server web1 10.0.0.17:80 check inter 2000 fall 3 rise 5
backend pc_hosts
mode http
#http-request set-header X-forwarded-Port %[dst_port] 也可加在此处
#http-request add-header X-forwarded-Proto https if { ssl_fc }
server web2 10.0.0.27:80 check inter 2000 fall 3 rise 5
[root@centos7 ~]#ss -ntl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 100 127.0.0.1:25 *:*
LISTEN 0 128 10.0.0.7:443 *:*
LISTEN 0 128 *:9999 *:*
LISTEN 0 128 10.0.0.7:80 *:*
LISTEN 0 128 *:22 *:*
LISTEN 0 128 [::]:22 [::]:*
1.3修改后端服务器的日志格式
[root@centos7 ~]#vim /etc/httpd/conf/httpd.conf
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" \"{X�Forwarded-Port}i\" \"%{X-Forwarded-Proto}i\"" combined
1.4验证https
[root@centos7 ~]#curl -IkL http://www.ceshi.org
HTTP/1.1 302 Found
content-length: 0
location: https://www.ceshi.org/
cache-control: no-cache
HTTP/1.1 200 OK
date: Thu, 27 Oct 2022 12:22:15 GMT
server: Apache/2.4.6 (CentOS) PHP/5.4.16
last-modified: Tue, 25 Oct 2022 13:50:22 GMT
etag: "a-3e532a01e5bfc"
accept-ranges: bytes
content-length: 10
content-type: text/html; charset=UTF-8
[root@centos7 ~]#curl -Ik https://www.ceshi.org
HTTP/1.1 200 OK
date: Thu, 27 Oct 2022 12:23:15 GMT
server: Apache/2.4.6 (CentOS) PHP/5.4.16
last-modified: Tue, 25 Oct 2022 13:50:55 GMT
etag: "a-3e532a0fa2215"
accept-ranges: bytes
content-length: 10
content-type: text/html; charset=UTF-8
查看后端服务器的访问日志
[root@centos7 ~]#tail /var/log/httpd/access_log
2.总结tomcat的核心组件以及根目录结构
2.1组件分层及分类
顶级组件
Server,代表整个Tomcat容器,一台主机可以启动多tomcat实例,需要确保端口不要产生冲突
服务类组件
Service,实现组织Engine和Connector,建立两者之间关联关系, service 里面只能包含一个Engine连接器组件
Connector,有HTTP(默认端口8080/tcp)、HTTPS(默认端口8443/tcp)、AJP(默认端口8009/tcp)协议的连接器,AJP(Apache Jserv protocol)是一种基于TCP的二进制通讯协议。
容器类
Engine、Host(虚拟主机)、Context(上下文件,解决路径映射)都是容器类组件,可以嵌入其它组件,内部配置如何运行应用程序。
内嵌类
可以内嵌到其他组件内,valve、logger、realm、loader、manager等。以logger举例,在不同容器组件内分别定义。
集群类组件
listener、cluster
2.2核心组件
Tomcat启动一个Server进程。可以启动多个Server,即tomcat的多实例, 但一般只启动一个创建一个Service提供服务。可以创建多个Service,但一般也只创建一个。每个Service中,是Engine和其连接器Connector的关联配置,可以为这个Service提供多个连接器Connector,这些Connector使用了不同的协议,绑定了不同的端口,其作用就是处理来自客户端的不同的连接请求或响应。
Service 内部还定义了Engine,引擎才是真正的处理请求的入口,其内部定义多个虚拟主机Host。Engine对请求头做了分析,将请求发送给相应的虚拟主机,如果没有匹配,数据就发往Engine上的defaultHost缺省虚拟主机,Engine上的缺省虚拟主机可以修改。
Host 定义虚拟主机,虚拟主机有name名称,通过名称匹配。
Context 定义应用程序单独的路径映射和配置。
2.3根目录结构
Tomcat中默认网站根目录是$CATALINA_BASE/webapps/,在Tomcat中部署主站应用程序和其他应用程序,和之前WEB服务程序不同。
nginx
假设在nginx中部署2个网站应用eshop、forum,假设网站根目录是/data/nginx/html,那么部署可以是这样的。
eshop解压缩所有文件放到 /data/nginx/html/ 目录下,forum 的文件放在 /data/nginx/html/forum/ 下。最终网站链接有以下对应关系
http://localhost/ 对应于eshop的应用,即 /data/nginx/html/
http://localhost/forum/ 对应于forum的应用,即/data/nginx/html/forum/
Tomcat
Tomcat中默认网站根目录是$CATALINA_BASE/webapps/,在Tomcat的webapps目录中,有个非常特殊的目录ROOT,它就是网站默认根目录。
将eshop解压后的文件放到这个$CATALINA_BASE/webapps/ROOT中。bbs解压后文件都放在$CATALINA_BASE/webapps/forum目录下。$CATALINA_BASE/webapps下面的每个目录都对应一个Web应用,即WebApp。最终网站链接有以下对应关系
http://localhost/ 对应于eshop的应用WebApp,即$CATALINA_BASE/webapps/ROOT/目录,
http://localhost/forum/ 对应于forum的应用WebApp,即$CATALINA_BASE/webapps/forum/
如果同时存在$CATALINA_BASE /webapps/ROOT/forum ,仍以 $CATALINA_BASE/webapps/forum/ 优先生效。每一个虚拟主机都可以使用appBase指令配置自己的站点目录,使用appBase目录下的ROOT目录作为主站目录。
3.tomcat实现多虚拟主机
3.1安装tomcat
[root@centos7 ~]#yum list tomcat*
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
* base:
Available Packages
tomcat.noarch 7.0.76-9.el7_6 base
tomcat-admin-webapps.noarch 7.0.76-9.el7_6 base
tomcat-docs-webapp.noarch 7.0.76-9.el7_6
base
tomcat-el-2.2-api.noarch 7.0.76-9.el7_6
base
tomcat-javadoc.noarch 7.0.76-9.el7_6
base
tomcat-jsp-2.2-api.noarch 7.0.76-9.el7_6
base
tomcat-jsvc.noarch 7.0.76-9.el7_6
base
tomcat-lib.noarch 7.0.76-9.el7_6
base
tomcat-native.x86_64 1.2.21-1.el7
epel
tomcat-servlet-3.0-api.noarch 7.0.76-9.el7_6
base
tomcat-webapps.noarch 7.0.76-9.el7_6
base
tomcatjss.noarch 7.2.1-8.el7_6
base
[root@centos7 ~]#yum -y install tomcat tomcat-webapps tomcat-admin-webapps tomcat-docs-webapp
[root@centos7 ~]#systemctl enable --now tomcat
Created symlink from /etc/systemd/system/multi-user.target.wants/tomcat.service to /usr/lib/systemd/system/tomcat.service.
[root@centos7 ~]#ss -ntl
State Recv-Q Send-Q Local Address:Port b Peer Address:Port
LISTEN 0 100 127.0.0.1:25 *:*
LISTEN 0 128 *:22 *:*
LISTEN 0 100 [::1]:25 [::]:*
LISTEN 0 1 [::ffff:127.0.0.1]:8005 [::]:*
LISTEN 0 100 [::]:8009 [::]:*
LISTEN 0 100 [::]:8080 [::]:*
LISTEN 0 128 [::]:22 [::]:*
[root@centos7 ~]#getent passwd tomcat
tomcat:x:53:53:Apache Tomcat:/usr/share/tomcat:/sbin/nologin
[root@centos7 ~]#ps aux|grep tomcat
tomcat 1921 19.4 9.8 2291096 98496 ? Ssl 18:16 18:05 /usr/lib/jvm/jre/bin/java -Djavax.sql.DataSource.Factory=org.apache.commons.dbcp.BasicDataSourceFactory -classpath /usr/share/tomcat/bin/bootstrap.jar:/usr/share/tomcat/bin/tomcat-juli.jar:/usr/share/java/commons-daemon.jar -Dcatalina.base=/usr/share/tomcat -Dcatalina.home=/usr/share/tomcat -Djava.endorsed.dirs= -Djava.io.tmpdir=/var/cache/tomcat/temp -Djava.util.logging.config.file=/usr/share/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager org.apache.catalina.startup.Bootstrap start
root 1988 0.0 0.0 112824 976 pts/1 R+ 18:17 0:00 grep --color=auto tomcat
打开浏览器访问:http://tomcat:8080/
3.2tomcat实现多虚拟主机
3.2.1修改配置文件
[root@centos7 ~]#vim /usr/local/tomcat/conf/server.xml
#在文件最后添加以下四行
<Host name="www.ceshi1.org" appBase="/data/webapps1" unpackWARs="true" autoDeploy="true">
</Host>
<Host name="www.ceshi2.org" appBase="/data/webapps2"unpackWARs="true" autoDeploy="true">
</Host>
</Engine>
</Service>
</Server>
3.2.2准备数据目录
[root@centos7 ~]#mkdir /data/webapps{1,2}/ROOT -pv
[root@centos7 ~]#chown -R tomcat.tomcat /data/webapps{1,2}/
[root@centos7 ~]#vim /data/webapps1/ROOT/index.html
www.ceshi1.org
[root@centos7 ~]#vim /data/webapps2/ROOT/index.html
www.ceshi2.org
#域名解析
[root@centos7 ~]#vim /etc/hosts
10.0.0.8 www.ceshi1.org www.ceshi2.org
#重启服务
[root@centos7 ~]#systemctl restart tomcat.service
3.2.3测试访问
[root@centos7 ~]#crul www.ceshi1.org:8080
[root@centos7 ~]#crul www.ceshi2.org:8080
4.nginx实现后端tomcat的负载均衡调度
4.1负载均衡主机和网络地址规划
10.0.0.8 proxy.ceshi.org 安装nginx、httpd的调度器
10.0.0.18 t1.ceshi.org tomcat1 jdk8、tomcat8
10.0.0.28 t2.ceshi.org tomcat2 jdk8、tomcat8
#只需在10.0.0.18的nginx主机上实现域名解析
vim /etc/hosts
#添加以下三行
10.0.0.8 proxy.ceshi.org proxy
10.0.0.18 t1.ceshi.org t1
10.0.0.28 t2.ceshi.org t2
4.2负载均衡tomcat主机准备
修改tomcat的虚拟机主机为自定义的主机名,并设为默认的虚拟主机
t1虚拟主机配置conf/server.xml
<Engine name="Catalina" defaultHost="t1.ceshi.org">
<Host name="t1.ceshi.org" appBase="/data/webapps" autoDeploy="true" >
</Host>
</Engine>
t2虚拟主机配置conf/server.xml
<Engine name="Catalina" defaultHost="t1.ceshi.org">
<Host name="t2.ceshi.org" appBase="/data/webapps" autoDeploy="true" >
</Host>
</Engine>
4.3负载均衡准备负载均衡规划测试用的jsp文件
在t1和 t2节点创建相同的文件/data/webapps/ROOT/index.jsp
#项目路径配置
mkdir -pv /data/webapps/ROOT
#编写测试jsp文件,内容在下面
vim /data/webapps/ROOT/index.jsp
<%@ page import="java.util.*" %>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>tomcat test</title>
</head>
<body>
<div>On <%=request.getServerName() %></div>
<div><%=request.getLocalAddr() + ":" + request.getLocalPort() %></div>
<div>SessionID = <span style="color:blue"><%=session.getId() %></span></div>
<%=new Date()%>
</body>
</html>
#设置权限
chown -R tomcat.tomcat /data/webapps/
4.4Nginx 实现后端 tomcat 的负载均衡
nginx 配置如下
vim /etc/nginx/nginx.conf
#在http块中加以下内容
#注意名称不要用下划线
upstream tomcat-server {
#ip_hash; # 先禁用看看轮询,之后开启开黏性
#hash $cookie_JSESSIONID; # 先禁用看看轮询,之后开启开黏性
server t1.ceshi.org:8080;
server t2.ceshi.org:8080;
}
server {
location ~* \.(jsp|do)$ {
proxy_pass http://tomcat-server;
}
}
测试访问http://proxy.ceshi.com/index.jsp,可以看到轮询调度效果,每次刷新后端主机和SessionID都会变化
4.5实现 session 黏性
在upstream中使用ip_hash指令,使用客户端IP地址Hash。
[root@proxy ~]#vim /etc/nginx/nginx.conf
#只添加ip_hash;这一行
upstream tomcat-server {
ip_hash; #启动源地址hash
#hash $cookie_JSESSIONID #启动基于cookie的hash
server t1.ceshi.org:8080;
server t2.ceshi.org:8080;
}
配置完reload nginx服务,使用curl测试可以看到,每次都调度到10.0.0.28主机上,但因为curl每次请求不会自动携带之前获取的cookie,所有SessionID每次都在变化。
通过图形浏览器访问可以看到主机不变,sessionID不变。
5.简述memcached的工作原理
memcached启动会在内存中分布一块默认64M大,可以修改的空间供使用,储存内容时会以键值对的形式存储,这些存放数据大小不一,定时清理后易形成内存碎片,为了提升内存使用效率,memcached把内存空间先分成page,1page大小默认为1M,进而把page分为大小不同的chunk,每个page采用不同的划分规则,形成chunk空间大小不等的Slab class,数据存放的时候,根据数据的大小放到不同的分组slab class对应的chunk,这样清理之后的空间能够重复使用,不会形成内存碎片。在提升内存使用效率的同时,memcachd不会主动删除数据,当长时间不访问,最终的空间就会被新的数据覆盖,memcached会根据数据访问的时间程度进行覆盖新数据,memcached的自身不具有高可用,需要借助客户端,第三方工具实现高可用集群。