ホームページ  >  記事  >  運用・保守  >  Debian で Nginx および Tomcat サーバーを構築して負荷分散を実現する方法

Debian で Nginx および Tomcat サーバーを構築して負荷分散を実現する方法

PHPz
PHPz転載
2023-05-19 22:31:041535ブラウズ

負荷分散の基本概念

負荷分散 (ロード バランシング) は、複数のコンピューター (コンピューター クラスター)、ネットワーク接続、CPU、ディスクの負荷を分散するために使用されるコンピューター ネットワーク テクノロジです。ドライブまたはその他のリソースを最適化して、リソース使用量を最適化し、スループットを最大化し、応答時間を最小化し、過負荷を回避します。

単一コンポーネントの代わりに複数のサーバー コンポーネントを負荷分散とともに使用すると、冗長性によって信頼性が向上します。負荷分散サービスは通常、専用のソフトウェアとハ​​ードウェアによって実行されます。

負荷分散の最も重要なアプリケーションの 1 つは、複数のサーバーを使用して 1 つのサービスを提供することです。このソリューションはサーバー ファームと呼ばれることもあります。通常、負荷分散は主に Web サイト、大規模なインターネット リレー チャット ネットワーク、トラフィックの多いファイル ダウンロード Web サイト、nntp (ネットワーク ニュース転送プロトコル) サービス、および DNS サービスで使用されます。現在、ロード バランサーは、データベース ロード バランサーと呼ばれるデータベース サービスもサポートし始めています。

インターネット サービスの場合、ロード バランサは通常、外部ポートをリッスンするソフトウェア プログラムです。インターネット ユーザーはこのポートを通じてサービスにアクセスでき、ソフトウェアはロード バランサとしてユーザーのリクエストを転送します。バックエンド イントラネット サーバーの場合、イントラネット サーバーは要求された応答をロード バランサーに返し、ロード バランサーはその応答をユーザーに送信します。これにより、イントラネット構造がインターネット ユーザーから隠蔽され、ユーザーがバックエンド (イントラネット) に直接アクセスできなくなります。サーバーの安全性を高め、コア ネットワーク スタックや他のポートで実行されているサービスへの攻撃を防ぎます。

すべてのバックエンド サーバーに障害が発生した場合、一部のロード バランサーは、この状況に対処するための特別な機能を提供します。たとえば、バックアップ ロード バランサーへのリクエストの転送、サービスの停止に関するメッセージの表示などです。ロード バランサを使用すると、IT チームはフォールト トレランスを大幅に向上できます。アプリケーション トラフィックの増減に対応できるよう、大量の容量が自動的に提供されます。

負荷分散機能を備えた nginx Tomcat サーバーの組み合わせを構築する方法を見てみましょう:

0. 早期の準備

使用debian環境。 nginx (デフォルトのインストール)、Web プロジェクト、Tomcat (デフォルトのインストール) などをインストールします。

1. nginx.conf 設定ファイル

# 定义nginx运行的用户 和 用户组 如果对应服务器暴露在外面的话建议使用权限较小的用户 防止被入侵
# user www www;
#nginx进程数, 建议设置为等于cpu总核心数
worker_processes 8;
#开启全局错误日志类型
error_log /var/log/nginx/error.log info;
#进程文件
pid /var/run/nginx.pid;
#一个nginx进程打开的最多文件描述数目 建议与ulimit -n一致
#如果面对高并发时 注意修改该值 ulimit -n 还有部分系统参数 而并非这个单独确定
worker_rlimit_nofile 65535;
events{
 #使用epoll模型提高性能
 use epoll;
 #单个进程最大连接数
 worker_connections 65535;
}
http{
 #扩展名与文件类型映射表
 include mime.types;
 #默认类型
 default_type application/octet-stream;
 sendfile on;
 tcp_nopush on;
 tcp_nodelay on;
 keepalive_timeout 65;
 types_hash_max_size 2048;
 #日志
 access_log /var/log/nginx/access.log;
 error_log /var/log/nginx/error.log;
 #gzip 压缩传输
 gzip on;
 gzip_min_length 1k; #最小1k
 gzip_buffers 16 64k;
 gzip_http_version 1.1;
 gzip_comp_level 6;
 gzip_types text/plain application/x-javascript text/css application/xml application/javascript;
 gzip_vary on;
 #负载均衡组
 #静态服务器组
 upstream static.zh-jieli.com {
 server 127.0.0.1:808 weight=1;
 }
 #动态服务器组
 upstream zh-jieli.com {
 server 127.0.0.1:8080;
 #server 192.168.8.203:8080;
 }
 #配置代理参数
 proxy_redirect off;
 proxy_set_header host $host;
 proxy_set_header x-real-ip $remote_addr;
 proxy_set_header x-forwarded-for $proxy_add_x_forwarded_for;
 client_max_body_size 10m;
 client_body_buffer_size 128k;
 proxy_connect_timeout 65;
 proxy_send_timeout 65;
 proxy_read_timeout 65;
 proxy_buffer_size 4k;
 proxy_buffers 4 32k;
 proxy_busy_buffers_size 64k;
 #缓存配置
 proxy_cache_key '$host:$server_port$request_uri';
 proxy_temp_file_write_size 64k;
 proxy_temp_path /dev/shm/jielierp/proxy_temp_path;
 proxy_cache_path /dev/shm/jielierp/proxy_cache_path levels=1:2 keys_zone=cache_one:200m inactive=5d max_size=1g;
 proxy_ignore_headers x-accel-expires expires cache-control set-cookie;
server{
 listen 80;
 server_name erp.zh-jieli.com;
 location / {
 index index; #默认主页为 /index
 #proxy_pass http://jieli;
 }
 location ~ .*\.(js|css|ico|png|jpg|eot|svg|ttf|woff) {
 proxy_cache cache_one;
 proxy_cache_valid 200 304 302 5d;
 proxy_cache_valid any 5d;
 proxy_cache_key '$host:$server_port$request_uri';
 add_header x-cache '$upstream_cache_status from $host';
 proxy_pass http:
//static.zh-jieli.com;
 #所有静态文件直接读取硬盘
 # root /var/lib/tomcat7/webapps/jielierp/web-inf ;
 expires 30d; #缓存30天
 }
 #其他页面反向代理到tomcat容器
 location ~ .*$ {
 index index;
 proxy_pass http:
//zh-jieli.com;
 }
 }
 server{
 listen 808;
 server_name static;
 location / {
}
 location ~ .*\.(js|css|ico|png|jpg|eot|svg|ttf|woff) {
 #所有静态文件直接读取硬盘
 root /var/lib/tomcat7/webapps/jielierp/web-inf ;
 expires 30d; #缓存30天
 }
 }
}

基本的には、負荷を実現するためにこのファイルを設定します。しかし、内部のさまざまな関係を理解することはさらに面倒です。

2. 基本的な説明

次に、Tomcat がデプロイされたコンピューター 192.168.8.203 があり、ブラウザ経由でポート 8080 に j2ee サービスがあるとします。通常通りウェブを閲覧できます。ここで問題が発生します。Tomcat は比較的包括的な Web コンテナです。静的 Web ページの処理は比較的リソースを大量に消費する必要があり、特に静的ページは毎回ディスクから読み取られて返される必要があります。これにより、Tomcat リソースが消費され、動的ページの解析パフォーマンスに影響を与える可能性があります。 Linux の哲学、つまりソフトウェアは 1 つのことしか実行しないという原則に準拠しています。 Tomcat は JSP 動的ページのみを処理する必要があります。ここではリバースプロキシに以前学んだnginxを使います。最初のステップは、動的 Web ページと静的 Web ページを分離するプロキシとして機能することです。これはとても簡単です。

worker_processes 8;
 
 pid /var/run/nginx.pid;
 
 worker_rlimit_nofile 65535;
 
 events{
 use epoll;
 worker_connections 65535;
 }
 
 http{
 include mime.types;
 default_type application/octet-stream;
 sendfile on;
 tcp_nopush on;
 tcp_nodelay on;
 keepalive_timeout 65;
 types_hash_max_size 2048;
proxy_redirect off;
 proxy_set_header host $host;
 proxy_set_header x-real-ip $remote_addr;
 proxy_set_header x-forwarded-for $proxy_add_x_forwarded_for;
 client_max_body_size 10m;
 client_body_buffer_size 128k;
 proxy_connect_timeout 65;
 proxy_send_timeout 65;
 proxy_read_timeout 65;
 proxy_buffer_size 4k;
 proxy_buffers 4 32k;
 proxy_busy_buffers_size 64k;
 
 server{
 listen 80;
 server_name xxx.com;
 location / {
 index index; 
 }
 location ~ .*\.(js|css|ico|png|jpg|eot|svg|ttf|woff) {
 proxy_pass http:
//192.168.8.203:8080;
 expires 30d; 
 }
 location ~ .*$ {
 index index;
 proxy_pass http:
//192.168.8.203:8080;
 }
 }
 }

worker_processes 8;
pid /var/run/nginx.pid;
worker_rlimit_nofile 65535;
events{
 use epoll;
 worker_connections 65535;
 }
http{
 include mime.types;
 default_type application/octet-stream;
 sendfile on;
 tcp_nopush on;
 tcp_nodelay on;
 keepalive_timeout 65;
 types_hash_max_size 2048;
proxy_redirect off;
 proxy_set_header host $host;
 proxy_set_header x-real-ip $remote_addr;
 proxy_set_header x-forwarded-for $proxy_add_x_forwarded_for;
 client_max_body_size 10m;
 client_body_buffer_size 128k;
 proxy_connect_timeout 65;
 proxy_send_timeout 65;
 proxy_read_timeout 65;
 proxy_buffer_size 4k;
 proxy_buffers 4 32k;
 proxy_busy_buffers_size 64k;
server{
 listen 80;
 server_name xxx.com;
 location / {
 index index;
 }
 location ~ .*\.(js|css|ico|png|jpg|eot|svg|ttf|woff) {
 proxy_pass http:
//192.168.8.203:8080;
 expires 30d;
 }
 location ~ .*$ {
 index index;
 proxy_pass http:
//192.168.8.203:8080;
 }
 }
 }

nginx 設定ファイル /etc/nginx/nginx.conf を変更します。デフォルトで設定ファイルがあります。実際、それらのほとんどは似ていますが、重要なのはサーバーセグメントの設定です。ここでは、サーバー セグメントを上記のように設定し、他のセグメントをコピーするだけです。サーバーセクションの説明は次のとおりです。 行 35 は、ローカル マシンのポート 80 をリッスンします。行 37 ~ 39 はデフォルトのホームページを表しています。ここでのデフォルトのホームページは、プロジェクトのインデックスに対応する、index.jsp です。ここでは、

indexindex.jspindex.htmlindex.htmindex.php

詳細は他の記事を参照してください。キーライン 40、これは定期的なマッチングで、インターネット上で多くの紹介があります。これは、プロジェクトで使用されているすべての静的 Web ページのサフィックスと一致します。 41 行目はプロキシ アドレスです。ここでは、Web アプリケーションにプロキシ接続します。 Expires 30d キャッシュは 30 日です。ここでのキャッシュは、フロントエンド ページとユーザーのキャッシュ制御フィールドに対応します。

Debian で Nginx および Tomcat サーバーを構築して負荷分散を実現する方法

44 行目の正規表現は次のとおりです。一致するサフィックスなしのページ。私のプロジェクトの JSP ページにはサフィックスがありません。これは必要に応じて変更できます。 192.168.8.203:8080 にもプロキシします。この時点で、一体何の意味があるのか​​と疑問に思っているかもしれません。もちろん、今はそうではありません。静的と動的の分離を単純に実装するには、行 41 を

root  /var/lib/tomcat7/webapps/jielierp/web-inf

に変更します。これは、プロキシを持たず、ローカル ディスクから直接取得されることを意味します。 Tomcat のログを確認すると、静的ページにアクセスされていないことがわかります。しかし、別の問題があります。このような柔軟性は良くなく、後述するメモリキャッシュやクラスタ展開にも不向きなため、以下のような記述方法を採用しています。別のサーバーセグメントを書き込みます。

server{
 listen 808;
 server_name static;
 location / {
}
location ~ .*\.(js|css|ico|png|jpg|eot|svg|ttf|woff) {
 #所有静态文件直接读取硬盘
 root /var/lib/tomcat7/webapps/jielierp/web-inf ;
 expires 30d; #缓存30天
 }
 }

今回は、ポート 808 をリッスンし、上記のコード行 41 を proxy_pass http://192.168.8.203:808 に変更します。この時点で、動的と静的の分離が達成されます。複数のサーバーがある場合は、対応する IP を変更するだけです。接続できない場合は、ファイアウォール、権限、その他の外部の問題を確認する必要があります。この構成は次のようになります。

如果单纯这样的话,我们会发现页面直接传输过于占用带宽。对应web的优化,这里想到的是通过对页面进行gzip压缩,然后传到用户那里,再解压,这样可以有效的减少带宽。这里就会用到nginx 的gzip模块了。默认的nginx是集成有gzip模块的。只需在http段增加下面配置即可。

gzip on;
 gzip_min_length 1k; #最小1k
 gzip_buffers 16 64k;
 gzip_http_version 1.1;
 gzip_comp_level 6;
 gzip_types text/plain application/x-javascript text/css application/xml application/javascript;
 gzip_vary on;

给个首页看看效果

Debian で Nginx および Tomcat サーバーを構築して負荷分散を実現する方法

不要在意请求数不一样,那两个请求是谷歌插件来的。不用觉得我在骗你。

作为假使有很多人访问的网站来说,缓存肯定是很重要的东西了。一开始是想通过插件,让nginx和redis进行合成,然后nginx使用redis来缓存的,但是发现配置起来很麻烦,还要自己下载插件,重新编译nginx,比较麻烦,所以这里觉得用nginx自带的缓存也是不错的选择。虽然效率比不上redis,但是有还是比没有好。nginx默认的缓存是磁盘文件系统的缓存,而不是像redis那样的内存级别的缓存。一开始我以为nginx就只有这样。后来查了写资料,才知道是我太天真了,对linux不是很了解导致的。linux的一切皆文件。原来我们可以把文件缓存到内存对应的linux文件系统中。我说的可能比较难以理解,请自行搜索/dev/shm 这个文件目录。我们把文件缓存到这个文件目录里,其实就相当与内存的缓存了。只不过还是靠文件系统管理。所以比不上自定义格式的redis那样的内存缓存。

在http段进行基本配置

#缓存配置
proxy_cache_key '$host:$server_port$request_uri';
proxy_temp_file_write_size 64k;
proxy_temp_path /dev/shm/jielierp/proxy_temp_path;
proxy_cache_path /dev/shm/jielierp/proxy_cache_path levels=1:2 keys_zone=cache_one:200m inactive=5d max_size=1g;
proxy_ignore_headers x-accel-expires expires cache-control set-cookie;

location ~ .*\.(js|css|ico|png|jpg|eot|svg|ttf|woff) {
 proxy_cache cache_one;
 proxy_cache_valid 200 304 302 5d;
 proxy_cache_valid any 5d;
 proxy_cache_key '$host:$server_port$request_uri';
 add_header x-cache '$upstream_cache_status from $host';
 proxy_pass http:
//192.168.8.203:808;
expires 30d; #缓存30天
 }

经过这两个的配置就基本能实现了,这里说几个注意项,也是困扰我很久的问题。上面第一段代码第6行,proxy_ignore_headers 如果web项目中的html的head头里面指定

<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">

这些不缓存的话,就要加上proxy_ignore_headers的配置项了。还有一点就是/dev/shm下面的文件系统权限默认只给root用户,所以要chmod 777 -r /dev/shm 这样不是很安全的做法,如果实际上线可以给定某个用户组,关于用户组的设置是配置的第一行

user www www;

上面第二段代码的第6行是增加一个header字段方便查看是否击中缓存。

我们rm -rf /dev/shm/jielierp/proxy_* 下面的所有文件(注意这里如果是进行多次测试的话要nginx -s reload 重新读取配置或重启服务,因为你rm -rf只是删除了缓存文件,但是缓存的结构信息还在nginx进程里面,结构还在,如果不重启的话,是会出现访问不到的)

Debian で Nginx および Tomcat サーバーを構築して負荷分散を実現する方法

所以要记得重启哦。下面是运行效果

第一次访问

Debian で Nginx および Tomcat サーバーを構築して負荷分散を実現する方法

第二次访问,在浏览器中ctrl+shift+r 强制刷新

Debian で Nginx および Tomcat サーバーを構築して負荷分散を実現する方法

到这里就可以看到效果了。我们查看一下/dev/shm这个里面

Debian で Nginx および Tomcat サーバーを構築して負荷分散を実現する方法

到这里已经快结束了。最后也是比较关键的一个技术点,就是集群,集群,集群。这个就要用到upstream了,看到最开头的配置文件了吗,就是那个

#负载均衡组
#静态服务器组
upstream static {
 server 127.0.0.1:808 weight=1;
 server 192.168.8.203:808 weight=1;
}

#动态服务器组
upstream dynamic {
 server 127.0.0.1:8080;
 #server 192.168.8.203:8080;
}

上面那个就是集群组了。upstream是关键字,static 和 dynamic是两个服务器集群组的名称。以第一个为例,server 127.0.0.1:808 是服务器地址,后面的weight=1 是权重。有多个就写多个。亲测试过,集群中的一个坏了,不影响系统运行。至于更多的轮询规则,可以参考网上更多的资料。这里不多说。至于怎么使用呢? proxy_pass http://192.168.8.203:808 改为 proxy_pass http://static; 这样即可实现均衡。

到这里就结束了。把上面各个部分根据自己需求配置起来就可以实现单机房负载均衡了。 上面这种做法有一个缺点就是在前面的那一台nginx如果当机,后面所以机器就失去了被访问的能力了,所以需要在前面实现多个nginx多机房的负载。关于这个就是另外一个话题了。目前还没有研究。以后有机会再说了。

上面动态服务器组如果是那种需要保存用户状态的话,会有问题,就是session问题,比如我在server1进行登录后,下一次动态服务器组进行轮询后可能分配到server2,就会造成要重新登录。治标的办法是,配置轮询规则,根据用户请求的ip进行hash,然后分配对应的服务器。具体配置如下:

upstream dynamic{
ip_hash;
server 127.0.0.1:8080;
server 192.168.0.203:8080;
}

这样就可以实现一个用户对应一个服务器节点。这样就不会有重复登录的问题。另一种治本的办法是,利用缓存系统进行session的统一存储管理。

以上がDebian で Nginx および Tomcat サーバーを構築して負荷分散を実現する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。