1. 背景
该问题的最终解决离不开公司大拿 whs 先生的指点, 先表示感谢
某项目的 geoserver 发布在一台 linux 上, 端口为 8082 使用 Nginx 对该 geoserver 服务 (包括其他服务) 做了一个转发代理, Nginx 监听的端口是 8081 由于 8082 端口没有对外开放, 所以用户只能访问该 8081 端口进行访问
由于系统与 Geoserver 的对接是直接基于 OGC 服务对接, 所以一切正常, 但是, 用户依然发现对于 Geoserver 服务网站的访问却存在两个问题:
a. 通过 8081 代理端口访问 Geoserver 网站, 图层无法直接预览
b. 通过 8081 代理端口访问 Geoserver 时, 如果不加上斜杠(/), 则会报空指针异常错误
2. 问题一: Geoserver 服务无法预览问题
2.1 问题排查过程
点击预览时录制脚本:
可见本应是 8081 端口请求变成了默认的 80 端口, 导致样式等文件无法加载, 从而出现预览为空跟踪源码, 发现 URL 的获取方式为:
再查看目前 Nginx 的配置为:
可见, 此处获取到的 URL 仅为浏览器输入地址的 IP, 而没有端口号, 所以出现了脚本中默认 80 端口的问题加上端口配置, 重启 Nginx 服务, 解决
配置修改为:
重启 Nginx 操作:
2.2 关于 proxy_set_header 参数的理解
其语法规则为:
语法: proxy_set_header field value; 默认值:
- proxy_set_header Host $proxy_host;
- proxy_set_header Connection close;
上下文: http, server, location
其作用为:
允许重新定义或者添加发往后端服务器的请求头 value 可以包含文本变量或者它们的组合 当且仅当当前配置级别中没有定义 proxy_set_header 指令时, 会从上面的级别继承配置
对上面问题出现我们可以这样理解: 当使用了 nginx 反向服务器后, 在 web 端使用 request.getRemoteAddr()(本质上就是获取 $remote_addr), 取得的是 nginx 的地址, 即 $remote_addr 变量中封装的是 nginx 的地址, 当然是没法获得用户的真实 ip 的
3. 问题二: 浏览器输入首页访问地址不带斜杠报错问题(http://ip:8081/geoserver 报错)
3.1. 一个奇怪的现象
首先, 我在本地单独发布了一个 Geoserver 测试该问题, 发现即使我输入不带斜杠, 访问时浏览器也会为我自动加上斜杠访问而服务器上的 Geoserver 则不会
最开始怀疑为浏览器自身补全功能, 但是这又无法解释访问云上地址时不补全现象最后通过查资料确定为如下情况导致:
以访问 http://ip:8081/geoserver 为例子, 在 windows 系统上, 一般如果服务器如果识别目录有个名称是 geoserver , 但是根目录有文件夹为 geoserver(没有文件名为 geoserver) 时, 他们会自动给目录加斜杠但是, 如果是 linux 系统则不会, linux 系统会把它作为文件处理(不会以目录形式处理), 而是直接就打开 geoserver 文件, 所以不会加上斜杠
因为服务器为 linux 系统, 所以不会自动加上斜杠
3.2 从报错信息排查起
3.2.1 正常情况下, 带 / 时跳转的原理
Geoserver 的 web.xml 中有如下配置:
- <welcome-file-list>
- <welcome-file>/index.html</welcome-file>
- </welcome-file-list>
所以带上 / 时, 会自动跳转至 index.html 页面, 而
index.html 中有:
于是请求再度调转为: http://192.168.56.104:8081/geoserver/web/, 进入 Geoserver 首页
3.2.2 没有按照套路走, 报错发生的原因在哪里
我们再看 web.xml 中的配置:
此时因为匹配规则是 /*, 所以所有请求要先经过过滤器之后, 才会走到欢迎页面设置, 查看源码发现:
3.3 解决方法
经过认真思考, 有两种解决方案:
一种是对 Nginx 配置进行针对性优化;
一种方案是对 Geoserver 升级
以下分段进行分别描述
4. 针对问题二: Nginx 配置优化
4.1 需求描述
整理需求为: 我们需要实现在直接访问 Geoserver(不带 /)时转发自动加上 / 但是针对 Geoserver/(带上 /)时转发不再自动加上 /(// 现象会导致访问 404 问题)
查找资料, Nginx 的 rewrite 机制可以非常好的解决该需求:
和 apache 等 web 服务软件一样, Nginx 的 rewrite 的组要功能是实现 RUL 地址的重定向 Nginx 的 rewrite 功能需要 PCRE 软件的支持, 即通过 perl 兼容正则表达式语句进行规则匹配的默认参数编译 nginx 就会支持 rewrite 的模块, 但是也必须要 PCRE 的支持 rewrite 是实现 URL 重写的关键指令, 根据 regex(正则表达式)部分内容, 重定向到 replacement, 结尾是 flag 标记
4.2Nginx 相关配置总结
4.2.1 语法规则
其语法规则为:
rewrite <regex> <replacement> [flag];
关键字 正则 替代内容 flag 标记
关键字: 其中关键字 error_log 不能改变
正则: perl 兼容正则表达式语句进行规则匹配
替代内容: 将正则匹配的内容替换成 replacement
flag 标记: rewrite 支持的 flag 标记
flag 标记说明:
- last #本条规则匹配完成后, 继续向下匹配新的 location URI 规则
- break #本条规则匹配完成即终止, 不再匹配后面的任何规则
- redirect #返回 302 临时重定向, 浏览器地址会显示跳转后的 URL 地址
- permanent #返回 301 永久重定向, 浏览器地址栏会显示跳转后的 URL 地址
4.2.2 执行顺序
a. 执行 server 块的 rewrite 指令 (这里的块指的是 server 关键字后{} 包围的区域, 其它 xx 块类似)
b. 执行 location 匹配
c. 执行选定的 location 中的 rewrite 指令
如果其中某步 URI 被重写, 则重新循环执行 1-3, 直到找到真实存在的文件
如果循环超过 10 次, 则返回 500 Internal Server Error 错误
4.2.3 正则表达式规则
. : 匹配除换行符以外的任意字符
? : 重复 0 次或 1 次
+ : 重复 1 次或更多次
* : 重复 0 次或更多次
\d : 匹配数字
^ : 匹配字符串的开始
$ : 匹配字符串的介绍
{n} : 重复 n 次
{n,} : 重复 n 次或更多次
[c] : 匹配单个字符 c
[a-z] : 匹配 a-z 小写字母的任意一个
小括号 () 之间匹配的内容, 可以在后面通过 $1 来引用,$2 表示的是前面第二个 () 里的内容正则里面容易让人困惑的是 \ 转义特殊字符
4.2.4 常用变量
$args : # 这个变量等于请求行中的参数, 同 $query_string
$content_length : 请求头中的 Content-length 字段
$content_type : 请求头中的 Content-Type 字段
$document_root : 当前请求在 root 指令中指定的值
$host : 请求主机头字段, 否则为服务器名称
$http_user_agent : 客户端 agent 信息
$http_cookie : 客户端 cookie 信息
$limit_rate : 这个变量可以限制连接速率
$request_method : 客户端请求的动作, 通常为 GET 或 POST
$remote_addr : 客户端的 IP 地址
$remote_port : 客户端的端口
$remote_user : 已经经过 Auth Basic Module 验证的用户名
$request_filename : 当前请求的文件路径, 由 root 或 alias 指令与 URI 请求生成
$scheme : HTTP 方法(如 http,https)
$server_protocol : 请求使用的协议, 通常是 HTTP/1.0 或 HTTP/1.1
$server_addr : 服务器地址, 在完成一次系统调用后可以确定这个值
$server_name : 服务器名称
$server_port : 请求到达服务器的端口号
$request_uri : 包含请求参数的原始 URI, 不包含主机名, 如:/foo/bar.php?arg=baz
$uri : 不带请求参数的当前 URI,$uri 不包含主机名, 如 / foo/bar.html
$document_uri : 与 $uri 相同
4.2.5 动态变量参数
$1-$9 存放着正则表达式中最近的 9 个正则表达式的匹配结果, 这些结果按照子匹配的出现顺序依次排列
$1 代表的是匹配的第一个结果
括号表示的是表达式定义的组(group), 并且将匹配这个表达式的字符保存到一个临时区域(一个正则表达式中最多可以保存 9 个) 上面的表达式有 2 个匹配组 (\w+) 和 (.*) 所有后面可以用 $1 和 $2 来用
比如例子 ^/(\w+)/(.*)$ /$1/index.php last;
对应为:/abc123/bcdfda => /abc123/index.php
4.3 解决该问题的最终配置
5. 针对问题二: Geoserver 升级
进入 Geoserver 下载官网进行学习: http://geoserver.org/download/
由于公司标准运行环境为 jdk1.7.x, 所以主要对 Geoserver2.8.x 和 Geoserver2.9.x 进行了对比研究, 总结如下:
5.1. 运行环境
a. 2.9.x 系列虽然描述为 compatible with Java 8, 个人理解为 jdk7 和 jdk8 应该都可以运行 但是, 分别在 jdk1.7._067 和云上的 1.7._079 上测试过, 不可运行:
b. 在 2.8.X 系列上进行了相关测试, 均可以支持 jdk1.7.x 系列
5.2.geoserver2.8.5 版本的优点
总结优化即是: 强化了三维服务支持集成了更多 (最新) 的插件针对某些特殊情况下的数据发布 (如局域网共享文件安全机制) 导致的闪退等问题进行了修复
公司主要用到的基于本地矢量数据或者 PG 数据的 WMSWFS 服务没有特殊说明的优化和改动
但是 geoserver 的代码架构还是做了不少变化
同时, 针对不带斜杠访问报错问题, 2.8.5 上也做了优化:
5.3. 基于业务的测试
a. 基于公司云上一键安装环境进行测试, 目前部件展示 I 查询网格查询正常:
b 基于 PG 测试, 也是正常
5.4. 但是, 有一个小缺点
整个 2.8.x 系列, 在版本 chrome 63.0.3239.132 上, geoserver 平台在某些弹出框上会出现内容为空但是 IE(9 以上)没有这个问题考虑到这类手动操作不常见, 不影响工程同事使用
6. 学习上的一点感慨
技巧可以规避问题, 知其所以然才可以解决问题
来源: https://www.cnblogs.com/naaoveGIS/p/8413818.html