明天的明天 永远的永远 未知的一切 我与你一起承担 ??

是非成败转头空 青山依旧在 几度夕阳红 。。。
  博客园  :: 首页  :: 管理

背景

使用iServer发布服务的时候经常会涉及到nginx代理,负载集群或者反向代理,都是常见的使用场景,下面就nginx代理iServer服务的一些问题做个简单总结。

 

一、Tomcat 配置业务系统,一级域名,正常启用Http协议,自定义内部端口,端口可以不开放公网:

Tomcat 8.5.x\conf\server.xml

<?xml version="1.0" encoding="UTF-8"?>

<Server port="8000" shutdown="SHUTDOWN">
  <Listener className="org.apache.catalina.startup.VersionLoggerListener" />

  <!-- APR library loader. Documentation at /docs/apr.html -->
  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
  <!-- Prevent memory leaks due to use of particular java/javax APIs-->
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />

  <GlobalNamingResources>

    <Resource name="UserDatabase" auth="Container"
              type="org.apache.catalina.UserDatabase"
              description="User database that can be updated and saved"
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
              pathname="conf/tomcat-users.xml" />
  </GlobalNamingResources>

  <Service name="Catalina">  
    <Connector URIEncoding="UTF-8" port="8080" protocol="HTTP/1.1"
               connectionTimeout="8000" redirectPort="8443" /> 
<Engine name="Catalina" defaultHost="localhost"> <!-- Use the LockOutRealm to prevent attempts to guess user passwords via a brute-force attack --> <Realm className="org.apache.catalina.realm.LockOutRealm"> <!-- This Realm uses the UserDatabase configured in the global JNDI resources under the key "UserDatabase". Any edits that are performed against this UserDatabase are immediately available for use by the Realm. --> <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/> </Realm> <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="false" > <Context Path="typg" docBase="/typg/" debug="0" reloadable="false" /> <!-- Access log processes all example. Documentation at: /docs/config/valve.html Note: The pattern used is equivalent to using pattern="common" --> <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log" suffix=".txt" pattern="%h %l %u %t &quot;%r&quot; %s %b" /> <Context crossContext="true" docBase="E:\\biggit\\files" path="/pimages" reloadable="true"></Context> </Host> </Engine> </Service> </Server>

 

第二、Supmap iServer服务发布 (布署采用超图的绿色版免安装包,非war包,区别于业务系统的灵活启动)

supermap-iserver-11.0.0-windows-x64-deploy\conf\server.xml

<?xml version="1.0" encoding="UTF-8"?>
<Server port="8915" shutdown="SHUTDOWN">
  <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
  <!--APR library loader. Documentation at /docs/apr.html -->
  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
  <!-- Prevent memory leaks due to use of particular java/javax APIs-->
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />

  <GlobalNamingResources>
    <Resource name="UserDatabase" auth="Container"
              type="org.apache.catalina.UserDatabase"
              description="User database that can be updated and saved"
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
              pathname="conf/tomcat-users.xml" />
  </GlobalNamingResources>


  <Service name="Catalina">               
    <Connector protocol="org.apache.coyote.http11.Http11NioProtocol"
         port="8443" 
         relaxedPathChars="|{}[],%" relaxedQueryChars="|{}[],%"
         connectionTimeout="8000"
         URIEncoding="utf-8"
         maxThreads="200"
         scheme="https"
         secure="true"
         SSLEnabled="true"
        keystoreFile="d:/ssl/site.pfx"
         keystorePass="8sc1cv5a"
         clientAuth="false"
         sslProtocol="TLS"
         sslEnabledProtocols="TLSv1.2"
         compressableMimeType="text/html,text/xml,text/plain,text/javascript,text/css,application/javascript,application/xml,application/json,application/rjson"
        />
        
    <!-- 此处必须用业务系统的同域名,否则web端启用https后报跨域问题 -->    
    <Engine name="Catalina" defaultHost="www.xxx.cn">
      <Realm className="org.apache.catalina.realm.LockOutRealm">       
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
               resourceName="UserDatabase"/>
      </Realm>

    
<!-- 此处必须用业务系统的同域名,否则web端启用https后报跨域问题 -->
<Host name="www.xxx.cn" appBase="webapps" unpackWARs="true" autoDeploy="true"> 

<!-- not display exception and server info--> 
<Valve className="org.apache.catalina.valves.ErrorReportValve" showReport="false" showServerInfo="false" /> 

</Host> 

</Engine> 
</Service> 
</Server>

iServer服务,若不启用ssl 配置,web端则报以下错误

 

 

三、nginx代理SSL证书,启用Https

nginx的一些基础用法:  https://www.cnblogs.com/Fooo/p/17519317.html

D:\nginx-1.24.0\conf\nginx.conf

#user  nobody;
worker_processes  1;

#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;
    #客户端请求服务器最大允许大小,若超过所设定的大小,返回413错误。
    client_max_body_size 1000m;
    #分配给请求数据的Buffer大小,如果请求的数据小于client_body_buffer_size直接将数据先在内存中存储。
    client_body_buffer_size  1000m;
    
    client_body_timeout 3000;
    client_header_buffer_size 1000k;
    client_header_timeout 3000;

    keepalive_requests 3000;
    large_client_header_buffers 8 1000k;
    reset_timedout_connection on;
    send_timeout 900;
    sendfile_max_chunk 1000k;
    server_names_hash_bucket_size 256;

    fastcgi_connect_timeout 30000;
    fastcgi_send_timeout 30000;
    fastcgi_read_timeout 30000;
    fastcgi_buffer_size 1000k;
    fastcgi_buffers 4 1000k;
    fastcgi_busy_buffers_size 1000k;
    fastcgi_temp_file_write_size 1000k;
    
    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  30000;

    #gzip  on;


    # HTTPS server  
    server {
        listen       443 ssl;
        server_name  www.xxx.cn;

        ssl_certificate      map.crt;
        ssl_certificate_key  map.key;

        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;

        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;
        
        location ^~/iserver/{
            #上传文件
            client_max_body_size 1000m;
            client_body_buffer_size  1000m;
            
            #报504 gateway timeout错误
            proxy_connect_timeout 3600s;
            proxy_send_timeout 3600s;
            proxy_read_timeout 3600s;
          
           #代理必须放最后一行,否则以上参数无效
            proxy_pass https://www.xxx.cn:8443/iserver/;
        
        }

        location /{
            #上传文件
            client_max_body_size 1000m;
            client_body_buffer_size  1000m;
            
            #报504 gateway timeout错误
            proxy_connect_timeout 3600s;
            proxy_send_timeout 3600s;
            proxy_read_timeout 3600s;
          
            #代理必须放最后一行,否则以上参数无效
            proxy_pass http://localhost:8080;
        
        }
    } 
}

 

最终通过 Nginx反向代理,达到业务系统和iserver同一个https域名下(解决启用证书后浏览器跨域限制),且又无需布署在同一个tomcat的同时启动烦恼;

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

代理iServer服务之基本配置

    upstream iserver  {
        #ip_hash;
        #hash $request_uri;
        server 192.168.16.20.9:8090; #Apache
        server 192.168.16.31:8090; #Apache
        server 192.168.16.32:8090; #Apache
    }

②配置location

        location /iserver/{
            proxy_pass    http://iserver/;    
            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 X-Forwarded-Proto $scheme;            
        }

 

代理iServer服务之二级域名

iServer通过nginx代理后,地址名称一般都是iServer,那能否随意指定这个名称呢?答案是可以的,配合相关的替换规则即可

域名
location /iserver_3d/ {
           proxy_pass   http://iserver_3d/iserver/;
           #Proxy Settings
           proxy_redirect     off;
           proxy_set_header   Host $host:8088;
           proxy_set_header   X-Real-IP $remote_addr;
           proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
           proxy_set_header X-Forwarded-Proto $scheme;
           proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
           proxy_max_temp_file_size 0;
           proxy_connect_timeout 300;            
           proxy_send_timeout 300;                
           proxy_read_timeout 600;                
           proxy_buffer_size 256k;                
           proxy_buffers 4 256k;                  
           proxy_busy_buffers_size 256k;          
           proxy_temp_file_write_size 256k;
           sub_filter_once off;
           sub_filter_types *;
           sub_filter 'http://localhost:8088/iserver/' 'http://localhost:8088/iserver_3d/';
        }

 

代理iServer服务之三维场景服务

当使用iServer代理三维场景服务时,请求三维场景集合时,返回结果中会返回iServer内部地址,此时需要通过过滤配置来实现地址的替换

location /mapservices/{
    proxy_pass    http://192.168.16.151:8100;
    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 X-Forwarded-Proto $scheme;
    proxy_connect_timeout      60s;
    proxy_send_timeout         60s;
      proxy_read_timeout         60s;
    client_max_body_size   100m;
    
    #三维场景服务过滤配置
    sub_filter_once off;
    sub_filter_types *;
    sub_filter 'http://192.168.16.151:8100/iserver/' 'http://www.supermap.com:8100/mapservices/iserver/';
}

 

代理iServer服务之会话保持(三维login)

nginx配置如下,增加一个login请求判断,login请求负载到会话保持配置,否则执行默认负载

    upstream iserver  {
        #ip_hash;
        #hash $request_uri;
        server 192.168.16.20.9:8090; #Apache
        server 192.168.16.31:8090; #Apache
        server 192.168.16.32:8090; #Apache
    }
    
    upstream iserver_session  {
        #会话保持
        ip_hash;
        server 192.168.16.20.9:8090; #Apache
        server 192.168.16.31:8090; #Apache
        server 192.168.16.32:8090; #Apache
    }
 
        location /iserver/{
            if ($request_uri ~ realspace/login.json) {
                proxy_pass   http://iserver_session;
                break;
            }
            proxy_pass  http://iserver;
            proxy_ssl_session_reuse 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;
            proxy_connect_timeout      5s;
            proxy_send_timeout         5s;
              proxy_read_timeout         5s;
            client_max_body_size   100m;
            proxy_redirect default;
        }

代理iServer服务之标绘服务

与三维场景服务一样,标绘服务代理时请求标号库也会遇到内部iServer地址暴露信息,与三维场景服务区别在于,标绘服务返回结果进行了压缩处理,配置替换规则时需要增加压缩配置,避免替换失败。

标绘服务
location /server/{
    proxy_pass    http://server/;    
    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 X-Forwarded-Proto $scheme;        
    #服务过滤配置,gzip压缩格式支持
    proxy_set_header Accept-Encoding deflate;
    #服务过滤配置
    sub_filter_once off;
    sub_filter_types *;
    sub_filter 'http://www.test.com:80/iserver/output/SymbolIcon/' 'https://www.test.com:65533/server/iserver/output/SymbolIcon/';    
    sub_filter 'http://192.168.16.11:443/iserver/output/SymbolIcon/' 'https://192.168.16.11/server/iserver/output/SymbolIcon/';    
}

代理iServer服务之负载IP显示

nginx代理iServer服务进行多节点负载时,前端调试过程中需要观察具体是哪个节点响应了请求,可在nginx中做如下配置

        location /iserver/{
            proxy_pass  http://iserver;
            proxy_ssl_session_reuse 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;
            proxy_set_header   X-Forwarded-Proto $https;
            proxy_connect_timeout      5s;
            proxy_send_timeout         5s;
              proxy_read_timeout         5s;
            client_max_body_size   100m;
            proxy_redirect default;
            # 显示具体负载的机器的ip,X-Route-Ip随便命名
            add_header X-Route-Ip $upstream_addr;
            add_header X-Route-Status $upstream_status;            
        }

 

代理iServer至OGC服务,替换xml内容失败

nginx代理iServer发布的OGC服务时,会涉及到替换xml中的内容问题,xml是压缩过的,参考上面步骤开启压缩及替换规则后,仍发现有替换失败现象发生(随机失败)

开启解压缩:gunzip on;
禁用压缩:gzip_disable ".";

        location /mapservices/{
            proxy_pass   http://jetty;
            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;
            proxy_set_header X-Forwarded-Proto  $scheme;
            proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
            proxy_max_temp_file_size 0;
            proxy_connect_timeout      3;
            proxy_send_timeout         3;
            proxy_read_timeout         3;
            proxy_buffer_size          128k;
            proxy_buffers              2 256k;
            proxy_busy_buffers_size    256k;
            index  index.html index.htm;
            #服务过滤配置,gzip压缩格式支持
            #proxy_set_header Accept-Encoding deflate;
            gunzip on;
            gzip_disable ".";
            #服务过滤配置
            sub_filter_once off;
            sub_filter_types *;            
            sub_filter 'http://127.0.0.1/iserver' 'http://127.0.0.1/mapservices/iserver';    
        }