1. 概述
1.1 版本
FineBI 版本 | JAR 包 | 新增功能 |
---|---|---|
5.1.2 | 2020-01-15 | BI 的数据更新和所有 BI 相关请求在主节点完成 |
5.1.11 | 2021-04-02 | BI 相关请求可分散在多个节点 |
1.2 功能简介
从 2020-01-15 的版本起,FineBI 推出了 Web 集群 &BI 单节点的应用方案,该方案不需要 Spider 多节点支持,仅需部署 BI 的 Web 集群,规定好主节点后,配置 Nginx 即可。
对于不同版本的 JAR ,有不同的实现方案。不同方案实现的效果不同,具体说明如下所示:
1)方案一效果:
JAR 需要在 2020-01-15 及之后,只区分 FineBI 和 FineReport 的请求。
BI 的数据更新和所有 BI 相关请求都会在这个主节点完成,其余 FR 或者管理系统的请求会随机转发到集群节点上面。
2)方案二效果:
JAR 需要在 2021-04-02 及之后,直连和 Spider 的请求可以区分开,在 Nginx 中配置相应转发。
直连的请求和 FineReport 的请求会随机转发到集群节点上,Spider 的请求在主节点完成。
1.3 部署方案
该部署方案在部署好 Web 集群的基础上,在 BI 的配置文件中规定好主节点,并配置 Nginx 中的主次节点。
1.4 前提条件
已按照 Web集群 文档部署好集群环境。
2. 部署方案
以集群两个节点,192.168.5.12 为主节点,192.168.5.11 为子节点,负载均衡地址是 192.168.5.11 的 Nginx 配置演示部署方案,可以根据实际场景进行修改。
2.1 配置主节点
2.1.1 添加 Web 集群主节点参数
1)关闭 Web 集群,在外置数据库中找到 FINE_CONF_ENTITY 表,并在其中增加一条 ID 记录:SystemOptimizationConfig.biClusterMasterNodeHostName,用来规定 Web 集群中的主节点,value 对应主节点服务器的 hostname。比如主节点服务器为 192.168.5.12 ,其对应 hostname 为 test02 ,则在表中增加的记录如下图所示:
2)此处主节点的服务器中,需要确保在/etc/hosts文件中,已经配置好 IP 和 hostname 的对应关系,如下图所示:
2.1.2 添加定时调度主节点参数
集群环境中,若节点一是主节点,更新的数据都在节点一上,而定时调度在进行请求转发时,没有特定指定某一个节点,所以当请求转发到节点二这个非数据节点上时,定时调度生成 pdf 文件将会报错没有权限导出数据。
关闭 Web 集群,在外置数据库中找到 FINE_CONF_ENTITY 表,并在其中增加一条 ID 记录:SystemOptimizationConfig.ClientMasterId,值为主节点的 ID 。
可在工程部署路径%FineBI%/webapps/webroot/WEB-INF/config目录下的cluster.properties文件里查看主节点 ID ,如下图所示:
2.2 方案一:BI 相关请求在主节点完成
进入 Nginx 安装目录/usr/nginx/conf,打开 nginx.conf 文件,复制如下内容并修改其中的 IP 和端口,替换掉原文件内容。代码如下所示:
#user root;
worker_processes auto;
#worker_cpu_affinity auto;
error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" $upstream_addr';
access_log off;
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65s;
types_hash_max_size 2048;
#gzip on;
#gzip_disable "MSIE [1-6].";
client_header_buffer_size 512k;
large_client_header_buffers 4 512k;
client_max_body_size 100M;
upstream FR.com {
server 192.168.5.12:37799 max_fails=15 fail_timeout=300s;
server 192.168.5.11:37799 max_fails=15 fail_timeout=300s;
check interval=1000 rise=5 fall=10 timeout=8000 type=http;
check_http_send "GET /webroot/decision/system/info HTTP/1.0\r\n\r\n";
check_http_expect_alive http_2xx http_3xx;
}
upstream BI.main.com {
server 192.168.5.12:37799 max_fails=15 fail_timeout=300s;
}
upstream WBS.com {
server 192.168.5.12:48888 max_fails=15 fail_timeout=300s;
server 192.168.5.11:48888 max_fails=15 fail_timeout=300s;
ip_hash;
}
server {
listen 9090;
server_name localhost;
underscores_in_headers on;
#charset koi8-r;
#access_log logs/host.access.log main;
location /status {
healthcheck_status html;
}
location ~*/decision/v5/conf/ {
proxy_http_version 1.1;
proxy_pass http://BI.main.com;
proxy_next_upstream http_500 http_502 http_503 http_504 http_403 http_404 http_429 error timeout invalid_header non_idempotent;
proxy_redirect off;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Connection "";
proxy_connect_timeout 20;
proxy_read_timeout 1000;
proxy_send_timeout 300;
proxy_buffer_size 64k;
proxy_buffers 32 32k;
proxy_busy_buffers_size 128k;
}
location ~*/decision/v5/design/ {
proxy_http_version 1.1;
proxy_pass http://BI.main.com;
proxy_next_upstream http_500 http_502 http_503 http_504 http_403 http_404 http_429 error timeout invalid_header non_idempotent;
proxy_redirect off;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Connection "";
proxy_connect_timeout 20;
proxy_read_timeout 1000;
proxy_send_timeout 300;
proxy_buffer_size 64k;
proxy_buffers 32 32k;
proxy_busy_buffers_size 128k;
}
location ~*/decision/link/ {
proxy_http_version 1.1;
proxy_pass http://BI.main.com;
proxy_next_upstream http_500 http_502 http_503 http_504 http_403 http_404 http_429 error timeout invalid_header non_idempotent;
proxy_redirect off;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Connection "";
proxy_connect_timeout 20;
proxy_read_timeout 1000;
proxy_send_timeout 300;
proxy_buffer_size 64k;
proxy_buffers 32 32k;
proxy_busy_buffers_size 128k;
}
location ~*/decision/file {
proxy_http_version 1.1;
proxy_pass http://FR.com;
proxy_next_upstream http_500 http_502 http_503 http_504 http_403 http_404 http_429 error timeout invalid_header non_idempotent;
proxy_redirect off;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Connection "";
proxy_connect_timeout 20;
proxy_read_timeout 1000;
proxy_send_timeout 300;
proxy_buffer_size 64k;
proxy_buffers 32 32k;
proxy_busy_buffers_size 128k;
if ($query_string ~ "TextGenerator") {
proxy_pass http://BI.main.com;
}
}
location ~*/decision/v10/bi/package/field/ {
proxy_http_version 1.1;
proxy_pass http://BI.main.com;
proxy_next_upstream http_500 http_502 http_503 http_504 http_403 http_404 http_429 error timeout invalid_header non_idempotent;
proxy_redirect off;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Connection "";
proxy_connect_timeout 20;
proxy_read_timeout 1000;
proxy_send_timeout 300;
}
location ~*/decision/v10/entry/access/ {
proxy_http_version 1.1;
if ($query_string ~* ^(.*)dashboardType=(4|5)(.*)$) {
proxy_pass http://BI.main.com;
}
proxy_pass http://FR.com;
proxy_next_upstream http_500 http_502 http_503 http_504 http_403 http_404 http_429 error timeout invalid_header non_idempotent;
proxy_redirect off;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Connection "";
proxy_connect_timeout 20;
proxy_read_timeout 1000;
proxy_send_timeout 300;
proxy_buffer_size 64k;
proxy_buffers 32 32k;
proxy_busy_buffers_size 128k;
}
location / {
proxy_http_version 1.1;
proxy_pass http://FR.com;
proxy_next_upstream http_500 http_502 http_503 http_504 http_403 http_404 http_429 error timeout invalid_header non_idempotent;
#proxy_next_upstream_timeout 0;
#proxy_next_upstream_tries 0;
proxy_redirect off;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Connection "";
#proxy_buffering off;
#proxy_buffer_size 64k;
#proxy_buffers 32 64k;
#proxy_busy_buffers_size 64k;
proxy_connect_timeout 120;
proxy_read_timeout 600;
proxy_send_timeout 600;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
server {
#FineReport:38889 FineBI:48889
listen 48889;
#listen 48889;
server_name localhost;
location / {
#add_header Access-Control-Allow-Origin *;
proxy_http_version 1.1;
proxy_pass http://WBS.com;
proxy_connect_timeout 120;
proxy_read_timeout 600;
proxy_send_timeout 600;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
}
2.2.1 根据实际情况修改 nginx.conf 文件
注:IP、port 需要修改为自身环境对应的 IP 和端口,详细的配置参数说明可参考 nginx.conf 配置手册 ,增加了集群主节点的配置。修改后保存该配置。
1)配置主子节点的 IP。如下图所示:
2)配置 nginx 转发。如下图所示:
3)配置 nginx 检查请求。有些客户版本从9.0升级上来地址还是"/WebReport/ReportServer/",或者客户自己改过Servlet后会出现nginx无法访问的问题。所以这部分根据实际最终地址进行修改。如下图所示:
2.2.2 启动 Web 集群
启动 Web 集群,即部署完成。
2.3 方案二:直连请求随机转发到集群节点
进入 Nginx 安装目录/usr/nginx/conf,打开 nginx.conf 文件,复制如下内容并修改其中的 IP 和端口,替换掉原文件内容。
如下代码所示:
#user root;
worker_processes auto;
#worker_cpu_affinity auto;
error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
log_format main '[$time_local] $remote_addr => $upstream_addr \n'
'"$request" $http_x_forwarded_for $status \n\n';
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for" $upstream_addr';
access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65s;
types_hash_max_size 2048;
#gzip on;
#gzip_disable "MSIE [1-6].";
client_header_buffer_size 512k;
large_client_header_buffers 4 512k;
client_max_body_size 300M;
#抽取部分固定主节点请求
upstream BI.main.com {
server 192.168.5.249:8080 max_fails=15 fail_timeout=300s;
}
#随机转发请求
upstream BI.cluster.com {
server 192.168.5.249:8080 max_fails=15 fail_timeout=300s;
server 192.168.5.207:8080 max_fails=15 fail_timeout=300s;
check interval=2000 rise=5 fall=10 timeout=10000 type=http;
check_http_send "GET /webroot/decision/system/health HTTP/1.0\r\n\r\n"; # 检查请求
check_http_expect_alive http_2xx http_3xx;
}
#直连部分仪表板和数据准备请求
upstream BI.com {
hash "$cookie_fine_login_users - $http_sessionid";
server 192.168.5.249:8080 max_fails=15 fail_timeout=300s;
server 192.168.5.207:8080 max_fails=15 fail_timeout=300s;
keepalive 300;
check interval=2000 rise=5 fall=10 timeout=10000 type=http;
check_http_send "GET /webroot/decision/system/health HTTP/1.0\r\n\r\n"; # 检查请求
check_http_expect_alive http_2xx http_3xx;
}
upstream WBS.com {
server 192.168.5.249:48888 max_fails=15 fail_timeout=300s;
server 192.168.5.207:48888 max_fails=15 fail_timeout=300s;
ip_hash;
}
server {
listen 80; #访问nginx端口
server_name 192.168.5.221; #访问nginxip
underscores_in_headers on;
location ~*/decision/v5/conf/ {
proxy_http_version 1.1;
proxy_pass http://BI.main.com;
proxy_next_upstream http_500 http_502 http_503 http_504 http_403 http_404 http_429 error timeout invalid_header non_idempotent;
proxy_redirect off;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Connection "";
proxy_connect_timeout 20;
proxy_read_timeout 1000;
proxy_send_timeout 300;
proxy_buffer_size 64k;
proxy_buffers 32 32k;
proxy_busy_buffers_size 128k;
}
location ~*/decision/v5/direct/conf/ {
proxy_http_version 1.1;
proxy_pass http://BI.com;
proxy_next_upstream http_500 http_502 http_503 http_504 http_403 http_404 http_429 error timeout invalid_header non_idempotent;
proxy_redirect off;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Connection "";
proxy_connect_timeout 20;
proxy_read_timeout 1000;
proxy_send_timeout 300;
proxy_buffer_size 64k;
proxy_buffers 32 32k;
proxy_busy_buffers_size 128k;
}
location ~*/decision/v5/design/ {
proxy_http_version 1.1;
if ($query_string ~* ^(.*)engineType=1(.*)$) {
proxy_pass http://BI.com;
}
proxy_pass http://BI.main.com;
proxy_next_upstream http_500 http_502 http_503 http_504 http_403 http_404 http_429 error timeout invalid_header non_idempotent;
proxy_redirect off;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Connection "";
proxy_connect_timeout 20;
proxy_read_timeout 1000;
proxy_send_timeout 300;
proxy_buffer_size 64k;
proxy_buffers 32 32k;
proxy_busy_buffers_size 128k;
}
location ~*/decision/link/ {
proxy_http_version 1.1;
proxy_pass http://BI.main.com;
proxy_next_upstream http_500 http_502 http_503 http_504 http_403 http_404 http_429 error timeout invalid_header non_idempotent;
proxy_redirect off;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Connection "";
proxy_connect_timeout 20;
proxy_read_timeout 1000;
proxy_send_timeout 300;
proxy_buffer_size 64k;
proxy_buffers 32 32k;
proxy_busy_buffers_size 128k;
}
location ~*/decision/file {
proxy_http_version 1.1;
proxy_pass http://BI.cluster.com;
proxy_next_upstream http_500 http_502 http_503 http_504 http_403 http_404 http_429 error timeout invalid_header non_idempotent;
proxy_redirect off;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Connection "";
proxy_connect_timeout 20;
proxy_read_timeout 1000;
proxy_send_timeout 300;
proxy_buffer_size 64k;
proxy_buffers 32 32k;
proxy_busy_buffers_size 128k;
# if ($query_string ~ "TextGenerator") {
# proxy_pass http://BI.main.com;
# }
}
location ~*/decision/v10/bi/package/field/ {
proxy_http_version 1.1;
proxy_pass http://BI.main.com;
proxy_next_upstream http_500 http_502 http_503 http_504 http_403 http_404 http_429 error timeout invalid_header non_idempotent;
proxy_redirect off;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Connection "";
proxy_connect_timeout 20;
proxy_read_timeout 1000;
proxy_send_timeout 300;
}
location /status {
healthcheck_status html;
}
location ~*/decision/v10/entry/access/ {
proxy_http_version 1.1;
if ($query_string ~* ^(.*)dashboardType=(4|5)(.*)$) {
proxy_pass http://BI.main.com;
}
proxy_pass http://BI.cluster.com;
proxy_next_upstream http_500 http_502 http_503 http_504 http_403 http_404 http_429 error timeout invalid_header non_idempotent;
proxy_redirect off;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Connection "";
proxy_connect_timeout 20;
proxy_read_timeout 1000;
proxy_send_timeout 300;
proxy_buffer_size 64k;
proxy_buffers 32 32k;
proxy_busy_buffers_size 128k;
}
location / {
proxy_http_version 1.1;
proxy_pass http://BI.cluster.com;
proxy_next_upstream http_500 http_502 http_503 http_504 http_403 http_404 http_429 error timeout invalid_header non_idempotent;
proxy_redirect off;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Connection "";
proxy_connect_timeout 20;
proxy_read_timeout 1000;
proxy_send_timeout 300;
proxy_buffer_size 64k;
proxy_buffers 32 32k;
proxy_busy_buffers_size 128k;
}
#charset koi8-r;
#access_log logs/host.access.log main;
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
server {
#FineReport:38889 FineBI:48889
listen 48889;
#listen 48889;
server_name 192.168.5.249;
location / {
#add_header Access-Control-Allow-Origin *;
proxy_http_version 1.1;
proxy_pass http://WBS.com;
proxy_connect_timeout 120;
proxy_read_timeout 600;
proxy_send_timeout 600;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
}
2.3.1 根据实际情况修改 nginx.conf 文件
注:IP、port 需要修改为自身环境对应的 IP 和端口,详细的配置参数说明可参考 nginx.conf 配置手册 ,增加了集群主节点的配置。修改后保存该配置。
1)配置主子节点的 IP。如下图所示:
2)配置 nginx 转发。如下图所示:
3)配置 nginx 检查请求。有些客户版本从9.0升级上来地址还是"/WebReport/ReportServer/",或者客户自己改过Servlet后会出现nginx无法访问的问题。所以这部分根据实际最终地址进行修改。如下图所示:
2.3.2 启动 Web 集群
启动 Web 集群,即部署完成。
3. 注意事项
3.1 更新卡住,重启后无法停止更新
3.1.1 问题描述
单表更新卡住,重启后更新进度页面显示仍在更新。
3.1.2 原因分析
集群若只有一个节点重启,不会清状态服务器 Redis 里的更新进度,需要重启整个集群,才会重置更新进度,如果只重启一个节点,之前在进行中的任务会强制失败,未开始的任务会继续更新。
3.1.2 解决方案
将所有的集群节点关闭之后全部重启。
3.2 BI 仪表板空白
3.2.1 问题描述
若同时使用 FineReport 和 FineBI ,且 Tomcat 版本为 8.0.23,FR 目录上挂出的 BI 仪表板打开显示空白。
3.2.2 解决方案
1)升级 Tomcat 版本到 8.5。
2)进入 Nginx 安装目录/usr/nginx/conf,打开 nginx.conf 文件,在以下位置加上proxy_http_version 1.1;,如下图所示:
3.3 数据同步
目前的 Web 集群+BI的 Spider 引擎单节点部署方案是通过 Nginx 转发访问节点,Spider 引擎更新的数据文件只存储在主节点上,只有主节点可以访问到这些文件上,不支持数据同步,即子节点上没有更新数据。 Spider 引擎的双机热备详情参见:热备集群部署