第十九周作业

1、haproxy https实现

  1. 配置haproxy,执行SSL加解密
[root@centos8mini ~]# cat /etc/haproxy/haproxy.cfg
...
frontend www
    log global
    option httplog
    bind 192.168.156.11:80
    #需要加上ssl选项
    bind 192.168.156.11:443 ssl crt /root/mxx.pem 
    #http到https重定向
    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 }
    use_backend aaa
    mode http 
    #capture request header Host len  256
    #capture request header User-Agent len 512
    #capture request header Referer len 15
    #capture request header X-Forwarded-For len 15

backend aaa
    cookie Dserver insert nocache indirect
    server rs1 192.168.156.202:80 cookie web1 send-proxy
    server rs2 192.168.156.204:80 cookie web2 send-proxy
...
  1. 配置nginx日志,记录x-forwarded-port和x-forwarded-proto信息:
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for" "$host" "$proxy_protocol_addr" "$http_x_forwarded_port" "$http_x_forwarded_proto"';  
  1. 测试结果
#后端服务器可以看到https,haproxy加上去的请求头部字段
192.168.156.208 - - [21/Jan/2022:21:11:36 +0800] "GET / HTTP/1.1" 200 110 "-" "curl/7.58.0" "192.168.156.100" "www.mxx.com" "192.168.156.100" "443" "https"
  1. 抓包可以看到前端是80切443,后端一直是80,ssl的加解密由haproxy完成
#客户端100去访问VIP 156.11的443端口
21:24:23.882974 IP 192.168.156.11.443 > 192.168.156.100.37330: Flags [P.], seq 1353:1624, ack 695, win 235, options [nop,nop,TS val 3578864071 ecr 3498970570], length 271
21:24:23.883118 IP 192.168.156.11.443 > 192.168.156.100.37330: Flags [P.], seq 1624:1895, ack 695, win 235, options [nop,nop,TS val 3578864071 ecr 3498970570], length 271
21:24:23.883393 IP 192.168.156.100.37330 > 192.168.156.11.443: Flags [.], ack 1895, win 501, options [nop,nop,TS val 3498970571 ecr 3578864071], length 0

#haproxy 208去访问后端的204的80端口
21:24:23.883424 IP 192.168.156.208.46246 > 192.168.156.204.80: Flags [S], seq 3363885263, win 29200, options [mss 1460,sackOK,TS val 3269997331 ecr 0,nop,wscale 7], length 0
21:24:23.883460 IP 192.168.156.204.80 > 192.168.156.208.46246: Flags [S.], seq 3613891712, ack 3363885264, win 28960, options [mss 1460,sackOK,TS val 1974460156 ecr 3269997331,nop,wscale 7], length 0
21:24:23.884099 IP 192.168.156.208.46246 > 192.168.156.204.80: Flags [.], ack 1, win 229, options [nop,nop,TS val 3269997332 ecr 1974460156], length 0
21:24:23.884167 IP 192.168.156.208.46246 > 192.168.156.204.80: Flags [P.], seq 1:231, ack 1, win 229, options [nop,nop,TS val 3269997332 ecr 1974460156], length 230: HTTP
21:24:23.884177 IP 192.168.156.204.80 > 192.168.156.208.46246: Flags [.], ack 231, win 235, options [nop,nop,TS val 1974460157 ecr 3269997332], length 0

2、总结tomcat的核心组件以及根目录结构

tomcat核心组件

  • Server组件:一个server就是一个tomcat实例,不同server使用不同的端口
  • service组件:包含了Engine和Connector的对应关系
  • Connector组件:可以简单理解为一个监听端口,包含HTTP、HTTPS、AJP协议的连接器
  • 容器类组件:在Engine内创建多个Host,Host内可以配置本地磁盘路径和URL路径的关联关系
    • Engine:接收用户通过某个接口发送的处理请求;Server里只有一个Engine
    • Host:一个Engine可以包含多个虚拟主机,和Apache、Nginx的虚拟主机是一样的概念,通过端口、IP、域名等方式区分虚拟主机
    • Context:执行路径映射,类似Apache或Nginx里的Location,配置磁盘目录和URL路径的关联关系
  • 内嵌类:可以内嵌到其他组件内,如valve、logger、realm、loader、manager等
  • 集群类组件:listener、cluster

根目录结构

  • bin/:包含服务启动、停止的程序和文件,如shutdown.sh、startup.sh、catalina.sh等
  • conf/:包含全局配置文件,比如启动service时,EnvironmentFile=tomcat.conf文件、web.xml、server.xml、context.xml、tomcat-users.xml等
  • lib/:java库目录
  • logs/:日志文件的存放位置
  • webapps/:类似apache的/var/www/html,是tomcat默认页面的存放路径
  • work/:jsp编译后的字节码和servlet文件存放位置,通常jsp文件需要被提前预热访问,以加快用户的访问速度;
    • 该目录中的缓存文件可能会影响新版本资源的发布,需要删除这些自动生成的文件,让新版本的jsp可以重新生成

3、tomcat实现多虚拟主机

#!/bin/bash
#****************************************************************************************#
#Author:                        Yabao11
#QQ:                            what QQ,no QQ
#Date:                          2022-01-04
#FileName:                      nginx.sh
#URL:                           https://github.com/yabao11
#Description:                   Test Script
#Copyright (C):                 2022 All rights reserved
#*******************************定义颜色*************************************************#
RED="\e[1;31m"
GREEN="\e[1;32m"
SKYBLUE="\e[1;36m"
YELLOW="\e[1;43m"
BLUE="\e[1;44m"
END="\e[0m"
RandomColor="\e[1;32m"
#****************************************************************************************#
function Ostype {
    if grep -i -q "release 6" /etc/centos-release;then
      echo Centos6
    elif grep -i -q Centos-8 /etc/os-release;then
      echo Centos
    elif grep -i -q Centos-7 /etc/os-release;then
      echo Centos7
    elif grep -i -q Ubuntu /etc/os-release;then
      echo Ubuntu
    elif grep -i -q "RedHat" /etc/os-release;then
      echo Redhat
    fi
}

function color {
  RES_COL=60
  MOVE_TO_COL="echo -en \E[${RES_COL}G"
  SETCOLOR_SUCCESS="echo -en \E[1;32m"
  SETCOLOR_FAILURE="echo -en \E[1;31m"
  SETCOLOR_WARNING="echo -en \E[1;33m"
  SETCOLOR_NORMAL="echo -en \E[0m"
  echo -n "$1" && $MOVE_TO_COL
  echo -n "["
  if [[ $2 = "success" || $2 = "0" ]]; then
    ${SETCOLOR_SUCCESS}
    echo -n "  OK  "
  elif [[ $2 = "failure" || $2 = "1" ]]; then
    ${SETCOLOR_FAILURE}
    echo -n "FAILED"
  else
    ${SETCOLOR_WARNING}
    echo -n "WARNING"
  fi
  ${SETCOLOR_NORMAL}
  echo -n "]"
  echo
}


function jdk_install {
    read -p "输入希望二进制安装的jdk版本,直接回车默认安装'/root/jdk-8u321-linux-x64'" jdk
    oracle_jdk=${jdk:-jdk-8u321-linux-x64}

    [ -e /root/${oracle_jdk}.tar.gz ] && tar xvf /root/${oracle_jdk}.tar.gz -C /usr/local/src/ || { color "文件不存在" 2;exit; }
    mv /usr/local/src/jdk* /usr/local/src/jdk
    cat > /etc/profile.d/jdk.sh <<\EOF
export JAVA_HOME=/usr/local/src/jdk
export PATH=$PATH:$JAVA_HOME/bin
export JRE_HOME=$JAVA_HOME/jre
export CLASSPATH=$JAVA_HOME/lib/:$JRE_HOME/lib/
EOF
    . /etc/profile.d/jdk.sh
    java -version > /dev/null && color "jdk安装成功!" 0
}


read -p "输入希望二进制安装的tomcat版本,直接回车默认安装'apache-tomcat-8.5.75'" tomcat
read -p "输入JAVA_HOME路径,直接回车使用默认路径:'/usr/local/src/jdk'" pjdk
read -p "输入tomcat路径,直接回车使用默认路径:'/usr/local/src/tomcat'" ptomcat
tomcat_version=${tomcat:-apache-tomcat-8.5.75}
java_path=${pjdk:-/usr/local/src/jdk}
tomcat_path=${ptomcat:-/usr/local/src/tomcat}

function tomcat_install {
    java -version > /dev/null || { color "缺少java环境!" 1;exit; }
    [ -e /root/${tomcat_version}.tar.gz ] || { yum -y install wget;wget https://mirrors.tuna.tsinghua.edu.cn/apache/tomcat/tomcat-8/v8.5.75/bin/${tomcat_version}.tar.gz; }
    [ -e /root/${tomcat_version}.tar.gz ] || { color "找不到tomcat文件" 1;exit; } 
    tar xf ${tomcat_version}.tar.gz -C /usr/local/src/
    [ -e ${tomcat_path} ] && rm -rf ${tomcat_path}
    ln -s /usr/local/src/${tomcat_version} ${tomcat_path}
    echo 'PATH=${tomcat_path}/bin:$PATH' > /etc/profile.d/tomcat.sh
    . /etc/profile.d/tomcat.sh
    useradd -r -s /sbin/nologin tomcat
    chmod +x ${tomcat_path}/bin/*
    catalina.sh version > /dev/null && color "安装成功!" 0 || color "catalina命令执行失败,请检查权限或路径" 1
    cat > ${tomcat_path}/conf/tomcat.conf < /lib/systemd/system/tomcat.service <)|\1 %{JSESSIONID}c %{HOST}i %{X-Forwarded-For}i %{X-Via}o\2|' \
    -e 's|shutdown="SHUTDOWN"|shutdown="44ba3c71d57f494992641b258b965f28"|' \
    -e '/<\/Engine>/i      \n        \n      \n' \
    ${tomcat_path}/conf/server.xml && color "配置日志格式,修改server参数" 0
    sed -i.bak -r '/<\/tomcat-users>/i\n\n\n' ${tomcat_path}/conf/tomcat-users.xml && color "配置允许访问tomcat的status等管理页面" 0
    sed -i.bak -r 's|(allow.*)("[[:space:]]+\/>)|\1\|\\d+\\.\\d+\\.\\d+\\.\\d+\2|' ${tomcat_path}/webapps/manager/META-INF/context.xml && color "配置允许所有IP地址访问status(测试环境)" 0
    sed -i.bak -r 's|(allow.*)("[[:space:]]+\/>)|\1\|\\d+\\.\\d+\\.\\d+\\.\\d+\2|' ${tomcat_path}/webapps/host-manager/META-INF/context.xml && color "配置允许所有IP地址访问host-manager(测试环境)" 0
    echo -e $GREEN"创建mxx虚拟主机"$END
    mkdir ${tomcat_path}/mxx/ROOT -p
    chown tomcat.tomcat ${tomcat_path}/mxx -R
    cat > ${tomcat_path}/mxx/ROOT/index.jsp <<\EOF
<%@ page import="java.util.*" %>



    
    tomcat test


Tomcat Website

On <%=request.getServerName() %>
<%=request.getLocalAddr() + ":" + request.getLocalPort() %>
SessionID = <%=session.getId() %>
<%=new Date()%>

这是一个测试页面

EOF echo -e $GREEN"创建多个虚拟主机"$END while true;do read -p "是否需要继续创建虚拟主机?(yes or no)" askuser1 askuser1=`echo $askuser1 | tr 'A-Z' 'a-z'` case $askuser1 in y|yes) let i=++i ;; n|no) break ;; *) inputerror ;; esac read -p "输入虚拟主机的域名" vhost if [ -z ${vhost} ];then while [ -z ${vhost} ];do read -p "请输入虚拟主机的域名" vhost done fi sed -i.bak -r -e '/<\/Engine>/i \n \n \n' \ ${tomcat_path}/conf/server.xml && color "虚拟主机配置成功" 0 mkdir ${tomcat_path}/mxx${i}/ROOT -p chown tomcat.tomcat ${tomcat_path}/mxx$i -R cat > ${tomcat_path}/mxx$i/ROOT/index.jsp <<\EOF <%@ page import="java.util.*" %> tomcat test

Tomcat Website

On <%=request.getServerName() %>
<%=request.getLocalAddr() + ":" + request.getLocalPort() %>
SessionID = <%=session.getId() %>
<%=new Date()%>

这是一个测试页面

EOF systemctl restart tomcat.service done } #exec jdk_install && tomcat_install && tomcat_config

测试结果

image.png
image.png

4、nginx实现后端tomcat的负载均衡调度

Nginx作为反向代理配置

配置nginx反向代理,将域名全部调度给后端tomcat服务器组,因为后端tomcat配置了虚拟主机,因此调度时修改了Host字段的值:

[root@centos8mini ~]# cat /data/nginx/conf/conf.d/server1.conf
server {
    listen 80;
    server_name m1.mxx.com;
    default_type text/html;
    root /data/server1;
#   location ~* \.jsp$  {
#       proxy_pass http://www.mxx.com:8080;
#       #proxy_set_header Host $http_host;
#   }
#   location ~* \.html$  {
#       proxy_pass http://blog.mxx.com:8080;
#       #proxy_set_header Host $http_host;
#   }
#   location /blog {
#       index index.jsp;
#       proxy_pass http://www.mxx.com:8080/blog;
#   }
    location / {
        index index.jsp;
        proxy_set_header Host www.mxx.com;
        proxy_pass http://webserver;
    }
}

在http语句块下定义服务器组,指向后端的两台tomcat服务器,调度算法也是在这里指定:

[root@centos8mini ~]# cat /data/nginx/conf/nginx.conf
...
http {
    upstream webserver {
        #hash $cookie_jsessionid consistent;
        server 192.168.1.12:8080 max_fails=3 fail_timeout=30s;
        server 192.168.1.14:8080 max_fails=3 fail_timeout=30s;
    ....
    }
...

测试结果

修改windows的hosts文件,解析m1.mxx.com域名,指向nginx代理服务器:

192.168.1.13 m1.mxx.com m2.mxx.com

没做session的会话保持前,调度到不同服务器会生成不同的session ID:

image.png

5、简述memcached的工作原理

Memcached采用Slab Allocator机制来分配、管理内存。根据提前定义好的Growth factor等参数,memcached启动后自动按照定义的参数分配内存空间并执行数据的存储。

memcached使用c/s架构,服务器维护key-value关联数组,客户端输入数据到数组中,并使用key来查询。
key可以有250字节长度,value可以存最大1M。

memcached内存空间是启动时提前分配好的。内存被分成大小相等的slab,然后每个slab被等分成chunk,slab按照chunk的大小进行分组,组成不同的slab class。

  • 一个1M大小内存空间作为一个slab,slab会等分成固定大小的chunk,但不同slab等分的chunk是不同的。处于相同层次的slab分配的chunk大小是相同的,不同层次按照growth factor来确定下一层次slab中chunk的大小。

当执行value存储时,memcached会根据value的大小,找到合适的chunk进行存储。

当内存不足时,memcached使用LRU(least recently used)机制来查找可用空间。memcached不会监视数据是否过期,而是采取Lazy Expiration懒过期机制,在取数据时才查看数据是否过期,过期就把数据有效期标识为0,但并不清理该数据,而是在以后直接覆盖该位置来存储其他数据。

memcached集群功能是基于客户端的分布式集群,客户端在生成数据时决定应该在哪里存放数据,memcached不会去执行数据的集群同步。

你可能感兴趣的:(第十九周作业)