[TOC]
一、nginx实现全栈SSL。要求http rewrite到https协议。 1.1、自签名证书 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 [root@server ~] [root@server nginx] [root@server nginx] [root@server certs] Country Name (2 letter code) [XX]:CN State or Province Name (full name) []:beijing Locality Name (eg, city) [Default City]:beijing Organization Name (eg, company) [Default Company Ltd]:magedu Organizational Unit Name (eg, section) []:it Common Name (eg, your name or your server's hostname) []:*.magedu.org #网站 Email Address []: #*.magedu.org使用的是泛域名,也可以指定具体网站 [root@server certs]#ls www.magedu.org.crt www.magedu.org.key #查看证书文件 [root@server certs]#openssl x509 -in www.magedu.org.crt -noout -text #或者下载到windows上查看 [root@server certs]#sz www.magedu.org.crt
1.2、https配置 nginx 的https 功能基于模块ngx_http_ssl_module实现,因此如果是编译安装的nginx要使用参数
ngx_http_ssl_module开启ssl功能,但是作为nginx的核心功能,yum安装的nginx默认就是开启的,编
译安装的nginx需要指定编译参数–with-http_ssl_module开启
1 https:// nginx.org/en/ docs/http/ ngx_http_ssl_module.html
配置参数如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ssl on | off; listen 443 ssl; ssl_certificate /path/to/file; ssl_certificate_key /path/to/file; ssl_protocols [SSLv2] [SSLv3] [TLSv1] [TLSv1.1] [TLSv1.2]; ssl_session_cache off | none | [builtin [:size]] [shared:name:size]; off: none: builtin [:size]: [shared:name:size]: ssl_session_timeout time;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 [root@server certs] nginx version: nginx/1.20.2 built by gcc 8.5.0 20210514 (Red Hat 8.5.0-10) (GCC) built with OpenSSL 1.1.1k FIPS 25 Mar 2021 TLS SNI support enabled configure arguments: --prefix=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module --add-module=/usr/local/src/echo-nginx-module-0.63 [root@server certs] [root@server nginx] [root@server conf.d] server { ...... listen 443 ssl; ssl_certificate /apps/nginx/certs/www.magedu.org.crt; ssl_certificate_key /apps/nginx/certs/www.magedu.org.key; ssl_session_cache shared:sslcache:20m; ssl_session_timeout 10m; ...... } :wq [root@server conf.d] nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok nginx: configuration file /apps/nginx/conf/nginx.conf test is successful [root@server conf.d] [root@server conf.d] State Recv-Q Send-Q Local Address:Port Peer Address:Port Process LISTEN 0 128 0.0.0.0:80 0.0.0.0:* LISTEN 0 128 0.0.0.0:22 0.0.0.0:* LISTEN 0 128 0.0.0.0:443 0.0.0.0:* LISTEN 0 128 [::]:22 [::]:*
1.3、实现HSTS 官方文档:
1 https://www.nginx.com/blog/http-strict-transport-security-hsts-and-nginx/
注意:配置rewrite才能实现http跳转到https
Nginx服务器利用 ngx_http_rewrite_module 模块(属于标准模块,系统默认安装)解析和处理rewrite请求,此功能依靠 PCRE(perl compatible regular expression),因此编译之前要安装PCRE库,rewrite是nginx服务器的重要功能之一,用于实现URL的重写,URL的重写是非常有用的功能,比如它可以在我们改变网站结构之后,不需要客户端修改原来的书签,也无需其他网站修改我们的链接,就可以设置为访问,另外还可以在一定程度上提高网站的安全性。
rewrite官方文档:
1 https://nginx.org/en/docs/http/ngx_http_rewrite_module.html
1.3.1、利用return实现http跳转到https return适用于server、location、if
1.3.1.1、用两个虚拟主机分开实现跳转 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 [root@server conf.d] server { listen 80; server_name www.magedu.org; root /data/nginx/html/pc; return 302 https://www.magedu.org/; } server { listen 443 ssl; ssl_certificate /apps/nginx/certs/www.magedu.org.crt; ssl_certificate_key /apps/nginx/certs/www.magedu.org.key; ssl_session_cache shared:sslcache:20m; ssl_session_timeout 10m; server_name www.magedu.org; root /data/nginx/html/pc; ..... } :wq [root@server conf.d] nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok nginx: configuration file /apps/nginx/conf/nginx.conf test is successful [root@server conf.d]
1.3.1.2、用一个虚拟主机实现跳转 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 [root@server conf.d] server { listen 80; listen 443 ssl; ssl_certificate /apps/nginx/certs/www.magedu.org.crt; ssl_certificate_key /apps/nginx/certs/www.magedu.org.key; ssl_session_cache shared:sslcache:20m; ssl_session_timeout 10m; server_name www.magedu.org; root /data/nginx/html/pc; if ($scheme = http) { return 302 https://www.magedu.org/; } :wq [root@server conf.d] nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok nginx: configuration file /apps/nginx/conf/nginx.conf test is successful [root@server conf.d]
1.3.2、利用rewrite实现http跳转到https rewrite 格式
1 2 3 Syntax: rewrite regex replacement [flag]; Default: — Context: server, location, if
flag 说明
1 2 3 4 5 6 7 8 9 10 11 12 13 redirect; 使用相对路径,或者http://或https://开头,状态码:302 permanent;break ; 的其它配置;结束循环,建议在location中使用 last; 不建议在location中使用
1.3.2.1、用两个虚拟主机分开实现跳转 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 [root@server conf.d] server { listen 80; server_name www.magedu.org; root /data/nginx/html/pc; rewrite ^(.*)$ https://$host$1 redirect; } server { listen 443 ssl; ssl_certificate /apps/nginx/certs/www.magedu.org.crt; ssl_certificate_key /apps/nginx/certs/www.magedu.org.key; ssl_session_cache shared:sslcache:20m; ssl_session_timeout 10m; server_name www.magedu.org; root /data/nginx/html/pc; ..... } :wq [root@server conf.d] nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok nginx: configuration file /apps/nginx/conf/nginx.conf test is successful [root@server conf.d]
1.3.1.2、用一个虚拟主机实现跳转 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 [root@server conf.d] server { listen 80; listen 443 ssl; ssl_certificate /apps/nginx/certs/www.magedu.org.crt; ssl_certificate_key /apps/nginx/certs/www.magedu.org.key; ssl_session_cache shared:sslcache:20m; ssl_session_timeout 10m; server_name www.magedu.org; root /data/nginx/html/pc; if ($scheme = http) { rewrite ^(.*)$ https://$host$1 redirect; } ..... } :wq location /about { alias /opt/pc/about; if ($scheme = http) { rewrite / https://$host /about redirect; } } [root@server conf.d] nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok nginx: configuration file /apps/nginx/conf/nginx.conf test is successful [root@server conf.d]
二、nginx实现动静分离。
2.1、架构组成 1 2 3 反向代理服务器:10.0.0.184 proxy 后端服务器:10.0.0.185 server01 存放静态资源 后端服务器:10.0.0.186 server02 存放动态资源
2.2、反向代理服务器配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 [root@proxy conf.d] server { listen 80; server_name www.magedu.org; access_log /apps/nginx/logs/access-json-www.magedu.org.log access_json; root /data/nginx/html/pc; location ~ \.(jpg|png|gif)$ { proxy_pass http://10.0.0.185; } location /api { proxy_pass http://10.0.0.186; } } :wq [root@proxy conf.d] nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok nginx: configuration file /apps/nginx/conf/nginx.conf test is successful [root@proxy conf.d]
2.3、后端服务器配置 1 2 [root@server01 ~] [root@server01 html]
1 2 3 4 5 6 [root@server02 ~] [root@server02 html] [root@server02 html] [root@server02 api] <h1> 10.0.0.186 </h1> :wq
三、nginx实现防盗链功能。 防盗链基于客户端携带的referer实现,referer是记录打开一个页面之前记录是从哪个页面跳转过来的标
记信息,如果别人只链接了自己网站图片或某个单独的资源,而不是打开了网站的整个页面,这就是盗
链,referer就是之前的那个网站域名,正常的referer信息有以下几种:
1 2 3 4 5 none: blocked: server_names: arbitrary_string: regular expression:
3.1、实现盗链 在一个web 站点盗链另一个站点的资源信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 [root@proxy ~] [root@proxy pc] <html> <head > <meta http-equiv=Content-Type content="text/html;charset=utf-8" > <title>盗链</title> </head> <body> <img src="http://m.magedu.org/1.jpg" > </body> </html> :wq [root@proxy conf.d] 10.0.0.1 - - [29/Nov/2022:16:30:07 +0800] "GET /1.jpg HTTP/1.1" 304 0 "http://www.magedu.org/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 Edg/107.0.1418.56"
3.2、实现防盗链 基于访问安全考虑,nginx支持通过ngx_http_referer_module模块,检查访问请求的referer信息是否有
效实现防盗链功能
官方文档:
1 https://nginx.org/en/docs/http/ngx_http_referer_module.html
语法格式:
1 2 3 4 5 6 7 8 9 10 location /images { root /data/nginx/html/pc; index index.html; valid_referers none blocked server_names *.example.com example.* www.example.org/galleries/ ~\.google\.; if ($invalid_referer ) { return 403; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 [root@proxy conf.d] server { listen 80; server_name m.magedu.org; location / { root /data/nginx/html/mobile; } valid_referers none blocked server_names ~\.google\. ~\.baidu\. ~\.bing\. ~\.so\. ; if ($invalid_referer ) { return 403 "Forbidden Access" ; } } :wq [root@proxy conf.d] nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok nginx: configuration file /apps/nginx/conf/nginx.conf test is successful [root@proxy conf.d] [root@proxy conf.d] 10.0.0.1 - - [29/Nov/2022:16:49:52 +0800] "GET /1.jpg HTTP/1.1" 403 16 "http://www.magedu.org/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 Edg/107.0.1418.56"
四、解析nginx常见的负载均衡算法。 Nginx 可以基于ngx_http_upstream_module模块提供服务器分组转发、权重分配、状态监测、调度算法等高级功能
官方文档: https://nginx.org/en/docs/http/ngx_http_upstream_module.html
4.1、负载均衡五种算法 ①轮询(默认)
每个请求按时间顺序逐一分配到不同的后端服务,如果后端某台服务器死机,自动剔除故障系统,使用户访问不受影响。
②weight(轮询权值)
weight的值越大分配到的访问概率越高,主要用于后端每台服务器性能不均衡的情况下。或者仅仅为在主从的情况下设置不同的权值,达到合理有效的地利用主机资源。
指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。
③ip_hash
每个请求按访问IP的哈希结果分配,使来自同一个IP的访客固定访问一台后端服务器,并且可以有效解决动态网页存在的session共享问题。
每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。
④fair(第三方)
比 weight、ip_hash更加智能的负载均衡算法,fair算法可以根据页面大小和加载时间长短智能地进行负载均衡,也就是根据后端服务器的响应时间 来分配请求,响应时间短的优先分配。Nginx本身不支持fair,如果需要这种调度算法,则必须安装upstream_fair模块。
按后端服务器的响应时间来分配请求,响应时间短的优先分配。⑤url_hash(第三方)
按访问的URL的哈希结果来分配请求,使每个URL定向到一台后端服务器,可以进一步提高后端缓存服务器的效率。Nginx本身不支持url_hash,如果需要这种调度算法,则必须安装Nginx的hash软件包。
按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。
1 2 3 4 5 hash KEY [consistent];hash $request_uri consistent; hash $cookie_sessionid
五、基于LNMP完成搭建任意一种应用。
5.1、准备数据库 1 2 3 4 5 6 7 8 9 10 11 [root@Rocky ~] [root@Rocky ~] [root@Rocky ~] mysql> create database kodbox; mysql> create user kodbox@'10.0.0.%' identified by '123456' ; mysql> grant all on kodbox.* to kodbox@'10.0.0.%' ; [root@Rocky ~]bind 0.0.0.0 [root@Rocky ~]
5.2、nginx的配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 [root@proxy ~] [root@proxy ~] include /apps/nginx/conf.d/*.conf; [root@proxy ~] [root@proxy ~] [root@proxy conf.d] server { listen 80; server_name kodbox.magedu.org; root /data/nginx/kodbox; client_max_body_size 200M; index index.php; location ~ \.php$ { root /data/nginx/kodbox; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name ; include fastcgi_params; } location ~ ^/(ping|fpm_status)$ { fastcgi_pass 127.0.0.1:9000; fastcgi_param PATH_TRANSLATED $document_root$fastcgi_script_name ; include fastcgi_params; } } :wq [root@proxy conf.d] nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok nginx: configuration file /apps/nginx/conf/nginx.conf test is successful [root@proxy conf.d]
5.3、安装和配置php 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 [root@proxy ~] [root@proxy ~] ; Maximum allowed size for uploaded files. ; http://php.net/upload-max-filesize upload_max_filesize = 200M ; http://php.net/post-max-size post_max_size = 200M :wq [root@proxy ~] ; RPM: apache user chosen to provide access to the same directories as httpd user = nginx ; RPM: Keep a group allowed to write in log dir . group = nginx ; listen = /run/php-fpm/www.sock listen = 127.0.0.1:9000 ..... ; Default Value: not set pm.status_path = /fpm_status ..... ; Default Value: not set ping.path = /ping .... ; Default Value: pong ping.response = pong :wq [root@proxy ~]
5.4、在DNS里添加解析(以前搭建的DNS) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 [root@DNS ~]$TTL 1D @ IN SOA master admin.magedu.org ( 6 1D 10M 1D 6H ) NS master NS slave1 master A 10.0.0.128 slave1 A 10.0.0.184 kodbox A 10.0.0.184 :wq [root@DNS ~] server reload successful [root@proxy ~] DNS1=10.0.0.128 :wq [root@proxy ~] [root@proxy ~]
5.5、可道云下载 1 2 3 4 5 6 7 8 9 10 11 12 [root@proxy ~] [root@proxy ~] [root@proxy ~] total 172 drwxr-xr-x 8 root root 110 Oct 31 18:31 app -rw-r--r-- 1 root root 168291 Oct 31 18:31 Changelog.md drwxr-xr-x 3 root root 91 Oct 31 18:31 config drwxr-xr-x 3 root root 20 Oct 31 18:31 data -rw-r--r-- 1 root root 157 Oct 31 18:31 index.php drwxr-xr-x 18 root root 260 Oct 31 18:31 plugins drwxr-xr-x 6 root root 58 Oct 31 18:31 static [root@proxy ~]
下一步:
此时发现仍缺少redis的相关组件
5.6、编译安装redis相关组件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 [root@proxy ~] [root@proxy ~] [root@proxy ~] [root@proxy src] [root@proxy src] echo-nginx-module-0.63 nginx-1.20.2.tar.gz package.xml redis-5.3.7.tgz v0.63.tar.gz nginx-1.20.2 nginx-module-vts-0.2.1 redis-5.3.7 v0.2.1.tar.gz [root@proxy src] [root@proxy redis-5.3.7] For everything you should need to install PhpRedis on your system, see the [INSTALL.markdown](./INSTALL.markdown) page. [root@proxy redis-5.3.7]cd phpredis phpize ./configure [--enable-redis-igbinary] [--enable-redis-msgpack] [--enable-redis-lzf [--with-liblzf[=DIR]]] [--enable-redis-zstd] make && make install [root@proxy redis-5.3.7] -bash: phpize: command not found [root@proxy redis-5.3.7] Last metadata expiration check: 1:56:31 ago on Wed 30 Nov 2022 04:13:44 PM CST. php-cli-7.2.24-1.module+el8.4.0+413+c9202dda.x86_64 : Command-line interface for PHP Repo : AppStream Matched from: Filename : /usr/bin/phpize [root@proxy redis-5.3.7] [root@proxy redis-5.3.7] Can't find PHP headers in /usr/include/php The php-devel package is required for use of this command. [root@proxy redis-5.3.7]#yum -y install php-devel [root@proxy redis-5.3.7]#./configure [root@proxy redis-5.3.7]#make && make install Installing shared extensions: /usr/lib64/php/modules/ #提示模块安装的路径 [root@proxy redis-5.3.7]#ls /usr/lib64/php/modules/ bz2.so dom.so gd.so mbstring.so pdo.so simplexml.so wddx.so calendar.so exif.so gettext.so mysqli.so pdo_sqlite.so sockets.so xmlreader.so ctype.so fileinfo.so iconv.so mysqlnd.so phar.so sqlite3.so xml.so curl.so ftp.so json.so pdo_mysql.so redis.so tokenizer.so xmlwriter.so xsl.so #但此时PHP程序不知道有redis模块,需人为进行添加 [root@proxy redis-5.3.7]#vim /etc/php.d/ 20-bz2.ini 20-fileinfo.ini 20-mbstring.ini 20-sqlite3.ini 20-calendar.ini 20-ftp.ini 20-mysqlnd.ini 20-tokenizer.ini 20-ctype.ini 20-gd.ini 20-pdo.ini 20-xml.ini 20-curl.ini 20-gettext.ini 20-phar.ini 20-xmlwriter.ini 20-dom.ini 20-iconv.ini 20-simplexml.ini 20-xsl.ini 20-exif.ini 20-json.ini 20-sockets.ini 30-mysqli.ini 30-pdo_mysql.ini 30-pdo_sqlite.ini 30-wddx.ini 30-xmlreader.ini [root@proxy redis-5.3.7]#vim /etc/php.d/31-redis.ini extension=redis #添加此行 :wq [root@proxy redis-5.3.7]#systemctl restart php-fpm
六、jumpserver 总结安装部署,添加用户授权,行为审计。 官方文档:
1 https://docs.jumpserver.org/zh/master/install/setup_by_fast/
6.1、安装要求 JumpServer 环境要求:
①硬件配置: 2个CPU核心, 4G 内存, 50G 硬盘(最低)
②操作系统: Linux 发行版 x86_64
③Python = 3.6.x
④MySQL Server ≥ 5.6 或者 Mariadb Server ≥ 5.5.56 数据库编码要求 uft8,新版要求5.7以上
⑤Redis: 新版要求6.0以上
6.2、安装方法 官方提供了多种安装方法
①手动部署: 一步一步实现
②极速部署: 资产数量不多,或者测试体验的用户请使用本脚本快速部署
③容器部署: 基于docker 实现
④分布式部署: 适用大型环境
6.3、基于容器部署 官方文档:
1 2 https://github.com/jumpserver/Dockerfile/tree/master/allinone https://docs.jumpserver.org/zh/master/install/docker_install/
6.3.1、环境说明 1 https://github.com/jumpserver/Dockerfile/tree/master/allinone
使用外置 MySQL 数据库和 Redis:
1 2 3 4 5 6 7 8 9 10 11 12 - 外置数据库要求 MySQL 版本大于等于 5.7 - 外置 Redis 要求 Redis 版本大于等于 6.0 # 自行部署 MySQL 可以参考 (https://docs.jumpserver.org/zh/master/install/setup_by_lb/#mysql) # mysql 创建用户并赋予权限, 请自行替换 nu4x599Wq7u0Bn8EABh3J91G 为自己的密码 mysql -u root -p create database jumpserver default charset 'utf8'; create user 'jumpserver'@'%' identified by 'nu4x599Wq7u0Bn8EABh3J91G'; grant all on jumpserver.* to 'jumpserver'@'%'; flush privileges; # 自行部署 Redis 可以参考 (https://docs.jumpserver.org/zh/master/install/setup_by_lb/#redis)
基于容器,安装完毕后可以通过以下方式访问
①浏览器访问: http://<容器所在服务器IP>
②默认管理员账户 admin 密码 admin
③SSH 访问: ssh -p 2222 <容器所在服务器IP>
④XShell 等工具请添加 connection 连接, 默认 ssh 端口 2222
容器docker安装
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 [root@docker ~] DOCKER_VERSION="20.10.10" UBUNTU_DOCKER_VERSION="5:${DOCKER_VERSION} ~3-0~`lsb_release -si`-`lsb_release -cs`" COLOR_SUCCESS="echo -e \\033[1;32m" COLOR_FAILURE="echo -e \\033[1;31m" END="\033[m" . /etc/os-releasecolor () { RES_COL=60 MOVE_TO_COL="echo -en \\033[${RES_COL} G" SETCOLOR_SUCCESS="echo -en \\033[1;32m" SETCOLOR_FAILURE="echo -en \\033[1;31m" SETCOLOR_WARNING="echo -en \\033[1;33m" SETCOLOR_NORMAL="echo -en \E[0m" echo -n "$1 " && $MOVE_TO_COL echo -n "[" if [ $2 = "success" -o $2 = "0" ] ;then ${SETCOLOR_SUCCESS} echo -n $" OK " elif [ $2 = "failure" -o $2 = "1" ] ;then ${SETCOLOR_FAILURE} echo -n $"FAILED" else ${SETCOLOR_WARNING} echo -n $"WARNING" fi ${SETCOLOR_NORMAL} echo -n "]" echo }install_docker (){ if [ $ID = "centos" -o $ID = "rocky" ];then if [ $VERSION_ID = "7" ];then cat > /etc/yum.repos.d/docker.repo <<EOF [docker] name=docker gpgcheck=0 #baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/7/x86_64/stable/ baseurl=https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/7/x86_64/stable/ EOF else cat > /etc/yum.repos.d/docker.repo <<EOF [docker] name=docker gpgcheck=0 #baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/8/x86_64/stable/ baseurl=https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/8/x86_64/stable/ EOF fi yum clean all ${COLOR_FAILURE} "Docker有以下版本" ${END} yum list docker-ce --showduplicates ${COLOR_FAILURE} "5秒后即将安装: docker-" ${DOCKER_VERSION} " 版本....." ${END} ${COLOR_FAILURE} "如果想安装其它Docker版本,请按ctrl+c键退出,修改版本再执行" ${END} sleep 5 yum -y install docker-ce-$DOCKER_VERSION docker-ce-cli-$DOCKER_VERSION \ || { color "Base,Extras的yum源失败,请检查yum源配置" 1;exit ; } else dpkg -s docker-ce &> /dev/null && $COLOR "Docker已安装,退出" 1 && exit apt update || { color "更新包索引失败" 1 ; exit 1; } apt -y install apt-transport-https ca-certificates curl software-properties-common || \ { color "安装相关包失败" 1 ; exit 2; } curl -fsSL https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu/gpg | sudo apt-key add - add-apt-repository "deb [arch=amd64] https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu $(lsb_release -cs) stable" apt update ${COLOR_FAILURE} "Docker有以下版本" ${END} apt-cache madison docker-ce ${COLOR_FAILURE} "5秒后即将安装: docker-" ${UBUNTU_DOCKER_VERSION} " 版本....." ${END} ${COLOR_FAILURE} "如果想安装其它Docker版本,请按ctrl+c键退出,修改版本再执行" ${END} sleep 5 apt -y install docker-ce=${UBUNTU_DOCKER_VERSION} docker-ce-cli=${UBUNTU_DOCKER_VERSION} fi if [ $? -eq 0 ];then color "安装软件包成功" 0 else color "安装软件包失败,请检查网络配置" 1 exit fi }config_docker (){ mkdir -p /etc/docker tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors" : ["https://si7y70hh.mirror.aliyuncs.com" ], "insecure-registries" :["harbor.magedu.org:80" ] } EOF systemctl daemon-reload systemctl enable docker systemctl restart docker docker version && color "Docker 安装成功" 0 || color "Docker 安装失败" 1 }set_alias (){ echo 'alias rmi="docker images -qa|xargs docker rmi -f"' >> ~/.bashrc echo 'alias rmc="docker ps -qa|xargs docker rm -f"' >> ~/.bashrc } install_docker config_docker set_alias
6.3.2、安装MySQL服务 官方说明:
1 https://docs.jumpserver.org/zh/master/install/prod/distributed_03/
MYSQL要求
1 2 3 4 create database jumpserver default charset 'utf8'; create user 'jumpserver'@'%' identified by 'nu4x599Wq7u0Bn8EABh3J91G'; grant all on jumpserver.* to 'jumpserver'@'%'; flush privileges;
6.3.2.1、在宿主机准备MySQL配置文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 [root@docker ~] [root@docker ~] [root@docker ~] [mysqld] pid-file= /var/run/mysqld/mysqld.pid socket= /var/run/mysqld/mysqld.sock datadir= /var/lib/mysql symbolic-links=0 character-set-server=utf8 EOF [root@docker ~] [mysql] default-character-set=utf8 EOF [root@docker ~] /etc/mysql/ ├── conf.d │ └── mysql.cnf └── mysql.conf.d └── mysqld.cnf 2 directories, 2 files
6.3.2.2、启动MySQL容器 将上面宿主机的设置好的配置文件挂载至MySQL容器
1 2 3 4 5 6 7 8 [root@docker ~] -e MYSQL_ROOT_PASSWORD=123456 \ -e MYSQL_DATABASE=jumpserver \ -e MYSQL_USER=jumpserver \ -e MYSQL_PASSWORD=123456 \ -v /data/mysql:/var/lib/mysql \ -v /etc/mysql/mysql.conf.d/mysqld.cnf:/etc/mysql/mysql.conf.d/mysqld.cnf \ -v /etc/mysql/conf.d/mysql.cnf:/etc/mysql/conf.d/mysql.cnf mysql:5.7.30
6.3.2.3、查看验证mysql 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 [root@docker ~] REPOSITORY TAG IMAGE ID CREATED SIZE mysql 5.7.30 9cfcce23593a 2 years ago 448MB [root@docker ~] State Recv-Q Send-Q Local Address:Port Peer Address:Port Process LISTEN 0 128 0.0.0.0:22 0.0.0.0:* LISTEN 0 128 0.0.0.0:3306 0.0.0.0:* LISTEN 0 128 *:80 *:* LISTEN 0 128 [::]:22 [::]:* LISTEN 0 128 [::]:3306 [::]:* [root@client ~] mysql: [Warning] Using a password on the command line interface can be insecure. Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 2 Server version: 5.7.30 MySQL Community Server (GPL) [root@client ~] mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | jumpserver | +--------------------+
6.3.3、安装Redis服务 官方说明:
1 https://docs.jumpserver.org/zh/master/install/prod/distributed_04/
新版要求:
1 外置 Redis 要求 Redis 版本大于等于 6.0
6.3.3.1、启动redis
6.3.3.2、验证Redis连接 1 2 3 4 5 6 [root@client ~] [root@client ~] 10.0.0.186:6379> info redis_version:6.2.6
6.3.4、部署JumpServer 6.3.4.1、生成key和token 官方说明
1 2 https://github.com/jumpserver/Dockerfile/tree/master/allinone https://docs.jumpserver.org/zh/master/install/docker_install/
需要先生成key和token
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 [root@docker ~]if [ ! "$SECRET_KEY " ]; then SECRET_KEY=`cat /dev/urandom | tr -dc A-Za-z0-9 | head -c 50`; echo "SECRET_KEY=$SECRET_KEY " >> ~/.bashrc; echo SECRET_KEY=$SECRET_KEY ;else echo SECRET_KEY=$SECRET_KEY ;fi if [ ! "$BOOTSTRAP_TOKEN " ]; then BOOTSTRAP_TOKEN=`cat /dev/urandom | tr -dc A-Za-z0-9 | head -c 16`; echo "BOOTSTRAP_TOKEN=$BOOTSTRAP_TOKEN " >> ~/.bashrc; echo BOOTSTRAP_TOKEN=$BOOTSTRAP_TOKEN ;else echo BOOTSTRAP_TOKEN=$BOOTSTRAP_TOKEN ;fi :wq [root@docker ~] SECRET_KEY=GkYTTfwge2HpQDiqjQ7hGqR7vEsSACM4rjgAlRbPE4gM7UKw7J BOOTSTRAP_TOKEN=gdqRJc1By36Rq9pc [root@docker ~] SECRET_KEY=GkYTTfwge2HpQDiqjQ7hGqR7vEsSACM4rjgAlRbPE4gM7UKw7J BOOTSTRAP_TOKEN=gdqRJc1By36Rq9pc
6.3.4.2、运行容器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 ----------------------------------------------------------------------------------- docker: Error response from daemon: driver failed programming external connectivity on endpoint jms_all (6e30f944775bad02dad4865998908f432c97b740bc2f3f211cbb4f6d1adabf63): Error starting userland proxy: listen tcp4 0.0.0.0:80: bind : address already in use. ----------------------------------------------------------------------------------- [root@docker ~] -v /opt/jumpserver/core/data:/opt/jumpserver/data \ -v /opt/jumpserver/koko/data:/opt/koko/data \ -v /opt/jumpserver/lion/data:/opt/lion/data \ -p 80:80 \ -p 2222:2222 \ -e SECRET_KEY=GkYTTfwge2HpQDiqjQ7hGqR7vEsSACM4rjgAlRbPE4gM7UKw7J \ -e BOOTSTRAP_TOKEN=gdqRJc1By36Rq9pc \ -e LOG_LEVEL=ERROR \ -e DB_HOST=10.0.0.186 \ -e DB_PORT=3306 \ -e DB_USER=jumpserver \ -e DB_PASSWORD=123456 \ -e DB_NAME=jumpserver \ -e REDIS_HOST=10.0.0.186 \ -e REDIS_PORT=6379 \ -e REDIS_PASSWORD='' \ --privileged=true \ jumpserver/jms_all ----------------------------------------------------------------------------------- docker: Error response from daemon: Conflict. The container name "/jms_all" is already in use by container "10aecc51ec5bfd5a8121480a49bfdba40c6218868f1ac2f4e76ce685e3ef4412" . You have to remove (or rename) that container to be able to reuse that name. [root@docker ~] CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 10aecc51ec5b jumpserver/jms_all "./entrypoint.sh" 17 minutes ago Created jms_all ea0fcb85ce50 redis "docker-entrypoint.s…" About an hour ago Up About an hour 0.0.0.0:6379->6379/tcp, :::6379->6379/tcp redis 26371d0aad4b mysql:5.7.30 "docker-entrypoint.s…" About an hour ago Up About an hour 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp mysql [root@docker ~] jms_all -----------------------------------------------------------------------------------
6.3.4.3、验证是否成功 1 2 3 4 5 6 7 8 9 10 11 [root@docker ~] ...... 2022-12-01 12:51:29 JumpServer version v2.17.2, more see https://www.jumpserver.org Migrate model org id : UserGroupStarting supervisor: supervisord. Jumpserver ALL v2.17.2 官网 http://www.jumpserver.org 文档 http://docs.jumpserver.org 进入容器命令 docker exec -it jms_all /bin/bash
注意:首次登录的初始账号和密码均为admin
登录进去后,会立刻让更改密码
更改密码后重新登录
6.4、用户授权和行为审计 6.4.1、创建组 创建开发组和测试组
6.4.2、创建用户并加入组 创建用户:xiaoming并加入开发组
创建用户:xiaohong并加入测试组
登录账户:xiaoming,首次登录需要完善个人信息
6.4.3、创建系统审计员 创建系统审计员:mage
登录账户:mage,左侧管理向与普通用户不同
6.4.4、创建管理用户 管理用户是jumpServer用来管理后端服务器或其它资产的管理员用户,此用户必须对后端服务器有管理权限
管理用户特点:
①通常是后端服务器的root或者是具备root权限的超级用户
②用于推送或者是创建系统用户
③用于获取被管理的硬件资产信息
6.4.5、创建资产并实现资产分类 创建可以被jumpServer用户访问的后端服务器和其它资产,比如:路由器,交换机等
开发环境和测试环境各加入一台服务器
6.4.6、创建系统用户 系统用户是分配给JumpServer用户,用来让JumpServer用户在连接后端服务器和其它资产,一般不会给管理权限
生产环境中,一般都会利用自动化运维工具提前在后端服务器创建好系统用户,在所有后端服务器统一用户ID信息,而非在jumpserver中创建
创建ceshi和kaifa用户
6.4.7、关联使用系统用户的资产 将前面创建的系统用户推送到后端服务器并自动创建
在系统用户中添加使用此用户的资产
6.4.8、创建授权规则 通过授权规则, 为JumpServer用户分配可以访问的资产及使用的系统用户
开发组授权
测试组授权
6.4.9、测试登录访问后端服务器
开发组xiaoming登录后端
6.4.9、ssh连接jumpserver JumpServer 还支持用户通过ssh连接其2222/tcp端口进行访问
1 2 3 4 5 6 7 8 9 10 11 12 13 [root@Rocky ~] xiaoming, JumpServer 开源堡垒机 1) 输入 部分IP,主机名,备注 进行搜索登录(如果唯一). 2) 输入 / + IP,主机名,备注 进行搜索,如:/192.168. 3) 输入 p 进行显示您有权限的主机. 4) 输入 g 进行显示您有权限的节点. 5) 输入 d 进行显示您有权限的数据库. 6) 输入 k 进行显示您有权限的Kubernetes. 7) 输入 r 进行刷新最新的机器和节点信息. 8) 输入 h 进行显示帮助. 9) 输入 q 进行退出. Opt>
6.4.10、数据库授权 6.4.10.1、在后端服务器创建数据库 1 2 3 4 5 6 7 [root@mysql ~] [root@mysql ~] Created symlink /etc/systemd/system/multi-user.target.wants/mysqld.service → /usr/lib/systemd/system/mys [root@mysql ~] mysql> create database wordpress; mysql> create user wordpress@'10.0.0.%' identified by '123456' ; mysql> grant all on wordpress.* to wordpress@'10.0.0.%' ;
6.4.10.2、创建数据库应用 应用管理–数据库–创建
6.4.10.3、创建数据库的系统用户 创建针对数据库的专用系统用户
注意:协议选择mysql
6.4.10.4、创建数据库授权规则 权限管理–应用授权
数据库授权给测试组使用
6.4.10.5、测试数据库连接
6.4.11、会话管理 会话管理-命令记录、历史会话里面可以看到用户操作过并且已经退出的录像记录
在线会话
历史会话
七、JVM垃圾回收原理,JVM调优。 对于垃圾回收,需要解决三个问题
①哪些是垃圾要回收
②怎么回收垃圾
③什么时候回收垃圾
7.1、确定垃圾的方法 ①引用计数: 每一个堆内对象上都与一个私有引用计数器,记录着被引用的次数,引用计数清零,该对象所占用堆内存就可以被回收。循环引用的对象都无法将引用计数归零,就无法清除。Python中即使用此种方式
②根搜索(可达)算法 Root Searching
7.2、垃圾回收基本算法 方法一:标记-清除 Mark-Sweep
分垃圾标记阶段和内存释放两个阶段。
①标记阶段,找到所有可访问对象打个标记。清理阶段,遍历整个堆
②对未标记对象(即不再使用的对象)逐一进行清理。
特点:
优点:算法简单
缺点:标记-清除最大的问题会造成内存碎片 ,但是不浪费空间,效率较高(如果对象较多时,逐一删除效率也会受到影响)
方法二:标记-压缩 (压实)Mark-Compact
分垃圾标记阶段和内存整理两个阶段。
①标记阶段,找到所有可访问对象打个标记。
②内存清理阶段时,整理时将对象向内存一端移动,整理后存活对象连续的集中在内存一端。
特点:
标记-压缩算法好处是整理后内存空间连续分配,有大段的连续内存可分配,没有内存碎片。
缺点是内存整理过程有消耗,效率相对低下
方法三:复制Copying
先将可用内存分为大小相同两块区域A和B,每次只用其中一块,比如A。当A用完后,则将A中存活的对象复制到B。复制到B的时候连续的使用内存,最后将A一次性清除干净。
特点 :
好处是没有碎片,复制过程中保证对象使用连续空间,且一次性清除所有垃圾,所以即使对象很多,收回效率也很高
缺点是比较浪费内存,只能使用原来一半内存,因为内存对半划分了,复制过程毕竟也是有代价。
总结:
没有最好的算法,在不同场景选择最合适的算法
①效率: 复制算法>标记清除算法> 标记压缩算法
②内存整齐度: 复制算法=标记压缩算法> 标记清除算法
③内存利用率: 标记压缩算法=标记清除算法>复制算法
7.3、垃圾回收的原理 分代堆内存GC策略: 对不同数据进行区分管理,不同分区对数据实施不同回收策略,分而治之。
堆内存分代 将heap内存空间分为三个不同类别: 年轻代、老年代、持久代
①年轻代Young :Young Generation
——伊甸园区eden : 只有一个,刚刚创建的对象
——幸存(存活)区Servivor Space: 有2个幸存区,一个是from区,一个是to区。大小相等、地位相同、可互换
——from 指的是本次复制数据的源区
——to 指的是本次复制数据的目标区
②老年代Tenured: Old Generation, 长时间存活的对象
**默认空间大小比例:**默认JVM试图分配最大内存的总内存的1/4,初始化默认总内存为总内存的1/64,年青代中heap的1/3,老年代占2/3
③永久代: JDK1.7之前使用, 即Method Area方法区,保存JVM自身的类和方法,存储JAVA运行时的环境信息,JDK1.8后 改名为 MetaSpace,此空间不存在垃圾回收,关闭JVM会释放此区域内存,此空间物理上不属于heap内存,但逻辑上存在于heap内存
——永久代必须指定大小限制,字符串常量JDK1.7存放在永久代,1.8后存放在heap中
——MetaSpace 可以设置,也可不设置,无上限
规律: 一般情况99%的对象都是临时对象
7.3.1、年轻代回收Minor GC ①起始时,所有新建对象(特大对象直接进入老年代)都出生在eden,当eden满了,启动GC 。这个称
为Young GC 或者 Minor GC 。
②先标记 eden存活对象,然后将存活对象复制 到s0(假设本次是s0,也可以是s1,它们可以调
换),eden剩余所有空间都清空。GC完成 。
③继续新建对象,当eden再次满了,启动GC 。
④先同时标记 eden和s0中存活对象,然后将存活对象复制 到s1。将eden和s0清空,此次GC完成
⑤继续新建对象,当eden满了,启动GC 。
⑥ 先标记 eden和s1中存活对象,然后将存活对象复制 到s0。将eden和s1清空,此次GC完成
以后就重复上面的步骤。
通常场景下,大多数对象都不会存活很久,而且创建活动非常多,新生代就需要频繁垃圾回收。
但是,如果一个对象一直存活,它最后就在from、to来回复制,如果from区中对象复制次数达到阈值
(默认15次,CMS为6次,可通过java的选项 -XX:MaxTenuringThreshold=N 指定),就直接复制到老年
代。
7.3.2、老年代回收Major GC 进入老年代的数据较少,所以老年代区被占满的速度较慢,所以垃圾回收也不频繁。
如果老年代也满了,会触发老年代GC,称为Old GC 或者 Major GC 。
由于老年代对象一般来说存活次数较长,所以较常采用标记-压缩 算法。
当老年代满时,会触发 Full GC ,即对所有”代”的内存进行垃圾回收
Minor GC比较频繁,Major GC较少。但一般Major GC时,由于老年代对象也可以引用新生代对象,所
以先进行一次Minor GC,然后在Major GC会提高效率。可以认为回收老年代的时候完成了一次Full GC。
所以可以认为 MajorGC = FullGC
7.4、JVM参数的选项分类 Java 命令行参考文档: https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html
选项分类
-选项名称 此为标准选项,所有HotSpot都支持
-X选项名称 此为稳定的非标准选项
-XX:选项名称 非标准的不稳定选项,下一个版本可能会取消
7.5、jvm调优 注意: 在不同领域和场景对JVM需要不同的调整策略
减少 STW 时长,串行变并行
减少 GC 次数,要分配合适的内存大小
一般情况下,大概可以使用以下原则:
客户端或较小程序,内存使用量不大,可以使用串行回收
对于服务端大型计算,可以使用并行回收
大型WEB应用,用户端不愿意等待,尽量少的STW,可以使用并发回收
①调整-Xms值和-Xmx值
将-Xms值和-Xmx值设置为一样大小,避免内存不够用时来回申请
-Xms:设置应用程序初始 使用的堆内存大小(年轻代+老年代)
-Xmx:设置应用程序能获得的最大 堆内存;早期JVM不建议超过32G,内存管理效率下降
1 2 3 4 5 6 7 8 9 10 11 12 [root@tomcat1 ~] Heap.java [root@tomcat1 ~] [root@tomcat1 ~] Heap.class Heap.java [root@tomcat1 ~] max=478150656字节 456.0MB total=31457280字节 30.0MB [root@tomcat1 ~] max=1073741824字节 1024.0MB total=1073741824字节 1024.0MB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 [root@tomcat2 tomcat] JAVA_OPTS="-Xms4g -Xmx4g" :wq [root@tomcat2 tomcat] ************************************************************************* JAVA_OPTS="-server -Xms4g -Xmx4g -XX:NewSize= -XX:MaxNewSize= " -server:服务器模式 -Xms:堆内存初始化大小 -Xmx:堆内存空间上限 -XX:NewSize=:新生代空间初始化大小 -XX:MaxNewSize=:新生代空间最大值
更改前heap大小
更改后heap大小
②指定垃圾回收器的种类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 [root@tomcat1 tomcat] -XX:G1ConcRefinementThreads=2 -XX:GCDrainStackTargetSize=64 -XX:InitialHeapSize=29808512 -XX:MaxHeapSize=476936192 -XX:+PrintCommandLineFlags -XX:ReservedCodeCacheSize=251658240 -XX:+SegmentedCodeCache -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseG1GC [root@tomcat2 tomcat] JAVA_OPTS="-Xms4g -Xmx4g -XX:+UseConcMarkSweepGC -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=5" :wq [root@tomcat2 tomcat] ************************************************************************** -XX:+UseConcMarkSweepGC 新生代使用ParNew, 老年代优先使用CMS,备选方式为Serial Old 响应时间要短,停顿短使用这个垃圾收集器 -XX:CMSInitiatingOccupancyFraction=N,N为0-100整数表示达到老年代的大小的百分比多少触发回收默认68 -XX:+UseCMSCompactAtFullCollection 开启此值,在CMS收集后,进行内存碎片整理 -XX:CMSFullGCsBeforeCompaction=N 设定多少次CMS后,进行一次内存碎片整理 -XX:+CMSParallelRemarkEnabled 降低标记停顿
③线程池调整
常用属性:
①connectionTimeout :连接超时时长,单位ms
②maxThreads:最大线程数,默认200
③minSpareThreads:最小空闲线程数
④maxSpareThreads:最大空闲线程数
⑤acceptCount:当启动线程满了之后,等待队列的最大长度,默认100
⑥URIEncoding:URI 地址编码格式,建议使用 UTF-8
⑦enableLookups:是否启用客户端主机名的DNS反向解析,缺省禁用,建议禁用,就使用客户端IP就行
⑧compression:是否启用传输压缩机制,建议 “on”,CPU和流量的平衡
—compressionMinSize:启用压缩传输的数据流最小值,单位是字节
—compressableMimeType:定义启用压缩功能的MIME类型text/html, text/xml, text/css,text/javascript
1 2 3 4 5 6 7 8 [root@tomcat1 tomcat] <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" maxThreads="2000" /> :wq [root@tomcat1 tomcat]
八、tomcat实现java应用发布。 8.1、部署基于JAVA的博客系统JPress 官方网站:http://www.jpress.io/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 [root@Rocky ~] [root@Rocky webapps] docs examples host-manager jpress-v4.0.7 jpress-v4.0.7.war manager ROOT [root@Rocky webapps] [root@Rocky webapps] docs examples host-manager manager ROOT [root@Rocky webapps] [root@Rocky opt] [root@Rocky opt] /usr/local/tomcat/webapps [root@Rocky webapps] blog blog.war docs examples host-manager manager ROOT
1 2 3 4 5 6 [root@Rocky webapps] [root@Rocky webapps] mysql> create database jpress; mysql> create user jpress@'localhost' identified by '123456' ; mysql> grant all on jpress.* to jpress@'localhost' ;
此后输入10.0.0.186:8080/blog即可登录网页,但不是网站后端
此后输入10.0.0.186:8080/blog/用户名即可登录网站后端
九、实现tomcat session粘性,并验证过程。
9.1、Tomcat配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 [root@tomcat1 ~] [root@tomcat1 tomcat] <Host name="www.magedu.org" appBase="/data/tomcat/node1/" unpackWARs="true" autoDeploy="true" > <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="node1_access_log" suffix=".txt" pattern="%h %l %u %t "%r" %s %b" /> </Host> :wq [root@tomcat1 ~] [root@tomcat1 ~] [root@tomcat1 ROOT] [root@tomcat1 ROOT] <%@ page import="java.util.*" %> <!DOCTYPE html> <html lang="en" > <head > <meta charset="UTF-8" > <title>tomcat test </title> </head> <body> <h1> Tomcat Website node1 </h1> <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> [root@tomcat1 ~] [root@tomcat1 ROOT] ----------------------------------------------------------------------------------- [root@tomcat2 ~] [root@tomcat2 tomcat] <Host name="www.magedu.org" appBase="/data/tomcat/node2/" unpackWARs="true" autoDeploy="true" > <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="node2_access_log" suffix=".txt" pattern="%h %l %u %t "%r" %s %b" /> </Host> :wq [root@tomcat2 ~] [root@tomcat2 ~] [root@tomcat2 ROOT] [root@tomcat2 ROOT] <%@ page import="java.util.*" %> <!DOCTYPE html> <html lang="en" > <head > <meta charset="UTF-8" > <title>tomcat test </title> </head> <body> <h1> Tomcat Website node2 </h1> <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> [root@tomcat2 ~] [root@tomcat2 ROOT]
9.2、DNS解析 1 2 3 4 5 6 7 8 9 10 11 [root@DNS ~]$TTL 1D @ IN SOA master admin.magedu.org ( 6 1D 10M 1D 6H ) NS master NS slave1 master A 10.0.0.128 slave1 A 10.0.0.184 node1 A 10.0.0.216 node2 A 10.0.0.217 :wq [root@DNS ~]
9.3、nginx的配置(反向代理与负载均衡) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 [root@nginx ~] http { upstream tomcat { server 10.0.0.216:8080; server 10.0.0.217:8080; } server { listen 80; server_name localhost; location / { root html; index index.html index.htm; proxy_pass http://tomcat; proxy_set_header Host $http_host ; } } } :wq [root@nginx ~]
9.3.1、保持session不发生变化 1 2 3 4 5 6 7 8 [root@nginx ~] upstream tomcat { hash $cookie_JSESSIONID ; server 10.0.0.216:8080; server 10.0.0.217:8080; } :wq [root@nginx ~]
十、实现tomcat会话复制集群。 Tomcat 官方实现了 Session 的复制集群,将每个Tomcat的Session进行相互的复制同步,从而保证所有Tomcat都有相同的Session信息.
10.1、配置说明
官方文档:
1 https://tomcat.apache.org/tomcat-10.0-doc/cluster-howto.html https://tomcat.apache.org/tomcat-9.0-doc/cluster-howto.html https://tomcat.apache.org/tomcat-8.5-doc/cluster-howto.html
说明
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 <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.0.0.4" port="45564" frequency="500" dropTime="3000" /> <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" address="auto" 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.MessageDispatchIntercep tor" /> </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.ClusterSessionListener" /> </Cluster>
10.1、Tomcat配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 [root@tomcat1 ~] [root@tomcat1 tomcat] <Host name="www.magedu.org" appBase="/data/tomcat/node1/" unpackWARs="true" autoDeploy="true" > <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="node1_access_log" suffix=".txt" pattern="%h %l %u %t "%r" %s %b" /> <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.0.0.4" port="45564" frequency="500" dropTime="3000" /> <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" address="10.0.0.216" 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.MessageDispatchInterceptor" /> </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.ClusterSessionListener" /> </Cluster> </Host> :wq [root@tomcat1 ~] [root@tomcat1 ~] [root@tomcat1 ROOT] [root@tomcat1 ROOT] <%@ page import="java.util.*" %> <!DOCTYPE html> <html lang="en" > <head > <meta charset="UTF-8" > <title>tomcat test </title> </head> <body> <h1> Tomcat Website node1 </h1> <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> [root@tomcat1 ~] [root@tomcat1 ~] [root@tomcat1 ~] <distributable/> :wq [root@tomcat1 ROOT] ----------------------------------------------------------------------------------- [root@tomcat2 ~] [root@tomcat2 tomcat] <Host name="www.magedu.org" appBase="/data/tomcat/node2/" unpackWARs="true" autoDeploy="true" > <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="node2_access_log" suffix=".txt" pattern="%h %l %u %t "%r" %s %b" /> <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.0.0.4" port="45564" frequency="500" dropTime="3000" /> <Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver" address="10.0.0.216" 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.MessageDispatchInterceptor" /> </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.ClusterSessionListener" /> </Cluster> </Host> :wq [root@tomcat2 ~] [root@tomcat2 ~] [root@tomcat2 ROOT] [root@tomcat2 ROOT] <%@ page import="java.util.*" %> <!DOCTYPE html> <html lang="en" > <head > <meta charset="UTF-8" > <title>tomcat test </title> </head> <body> <h1> Tomcat Website node2 </h1> <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> [root@tomcat2 ~] [root@tomcat2 ~] [root@tomcat2 ~] <distributable/> :wq [root@tomcat2 ROOT]
10.2、DNS解析 和上面9.2、DNS解析相同
10.3、nginx的配置(反向代理与负载均衡) 和上面9.3、nginx的配置(反向代理与负载均衡)相同