关于NGINX利用location的匹配规则分流和利用server的server_name分流

本文介绍了Nginx与Tomcat结合使用的多种配置方式,包括基于URL和域名的分流策略,以及如何搭建项目集群。同时,还讨论了不同配置方式对开发和部署的影响。

一、前提:

nginx是可以利用server-->server_name和location的匹配规则进行分流的

 

二、分流1:利用location匹配url

1.nginx配置:

  

server {
        listen        80;
        server_name        x1.cc.com;
        
        location / {
            root   html;
            #index  index.html index.htm;
            index x1.html;
        }
        
        location ^~ /project1/ {
            #root   C:\\Users\\Administrator\\Desktop\\demo\\nginx-1.11.6\\html;
           
            #index /project1.html;
            proxy_pass http://127.0.0.1:8080;
        }
    }

2.tomcat9的配置

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

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


  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
 
  <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 port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
    
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />


    <Engine name="Catalina" defaultHost="localhost">

      <Realm className="org.apache.catalina.realm.LockOutRealm">
   
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
               resourceName="UserDatabase"/>
      </Realm>

      <Host name="localhost"  appBase=""
            unpackWARs="true" autoDeploy="true">
            
            <Context path="/project1/" docBase="C:\Users\Administrator\Desktop\demo\qysxy-erp" reloadable="false"/>
            

      
        <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" />

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

 

此时:x1.cc.com/*这个路径会在nginx下处理,而x1.cc.com/project1/*整个URL就会交给被代理的服务器处理

出现的问题:

  1.由于在开发的时候,不会关注部署的情况,所以,“/project1/”这个URL前缀并不会被考虑到,如果web应用服务器是tomcat的话,就需要配置path:<Context path="/project1/" docBase="C:\Users\Administrator\Desktop\demo\{项目名称}" reloadable="false"/>,这样,一般的请求可以直接处理。但是记住,在开发的时候,如果涉及到重定向的时候,而且重定向的是本项目的服务,由于开发的时候没有考虑到部署的url会有其他的前缀,所以,源代码中的重定向不会加上这个URL前缀,此时会出现重定向失败,(傻瓜式的解决办法就是,在所有重定向中加上url前缀,造成开发上的麻烦)

 

总结:

1.不建议以url的方式进行分流,会造成后期的维护麻烦

 

三、分流2:利用域名的匹配来分流到不同的项目

windows下的实验:
1.修改hosts文件,一般位于 C:\Windows\System32\drivers\etc

# Copyright (c) 1993-2009 Microsoft Corp.
#
# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.
#
# This file contains the mappings of IP addresses to host names. Each
# entry should be kept on an individual line. The IP address should
# be placed in the first column followed by the corresponding host name.
# The IP address and the host name should be separated by at least one
# space.
#
# Additionally, comments (such as these) may be inserted on individual
# lines or following the machine name denoted by a '#' symbol.
#
# For example:
#
#      102.54.94.97     rhino.acme.com          # source server
#       38.25.63.10     x.acme.com              # x client host

# localhost name resolution is handled within DNS itself.
#    127.0.0.1       localhost
#    ::1             localhost
    127.0.0.1        x1.cc.com
    127.0.0.1        x2.cc.com

2.nginx配置

server {
        listen        80;
        server_name        x1.cc.com;
        
        location / {
            root   html;
            #index  index.html index.htm;
            index x1.html;
        }
        
        
    }
    
    server {
        listen        80;
        server_name        x2.cc.com;
        
        location / {
            root   html;
            #index  index.html index.htm;
            index x2.html;
        }
    }

此时:即使是x1.cc.com和x2.cc.com绑定的是同一个IP,不通的域名访问,也会进行不同的处理。

  例如:x1.cc.com/和x2.cc.com/访问得到分别是x1.html和x2.html两个文件

总结:

1、推荐这种做法,开发和部署两个阶段的url是互不影响的,不必相互考虑。但不足的是,需要两个以上的域名,二级域名即可,所以不会造成太多麻烦

 

四、nginx+tomcat  搭建项目集群的简单配置    

1.nginx配置

    upstream project {
        ip_hash;
        server 127.0.0.1:8080;
        server 127.0.0.1:8081;
        
    }
    
    server {
        listen        80;
        server_name        x1.cc.com;

    location / {
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Real-Port $remote_port;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_pass http://project;
    }


    }

注意:如果是nginx+tomcat,此时java程序中的获取ip方法,request.getRemoteAddr()可能会出错,用以下代码获取IP:

public static String getIpAddr(HttpServletRequest request) {
        String ipAddress = null;
        ipAddress = request.getHeader("x-forwarded-for");
        if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("Proxy-Client-IP");
        }

        if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("WL-Proxy-Client-IP");
        }

        if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getRemoteAddr();
            if(ipAddress.equals("127.0.0.1")) {
                InetAddress inet = null;

                try {
                    inet = InetAddress.getLocalHost();
                } catch (UnknownHostException var4) {
                    var4.printStackTrace();
                }

                ipAddress = inet.getHostAddress();
            }
        }

        if(ipAddress != null && ipAddress.length() > 15 && ipAddress.indexOf(",") > 0) {
            ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
        }

        return ipAddress;
    }

 

 

 

 

附录:

一、location匹配规则:

location匹配命令

~      #波浪线表示执行一个正则匹配,区分大小写
~*    #表示执行一个正则匹配,不区分大小写
^~    #^~表示普通字符匹配,如果该选项匹配,只匹配该选项,不匹配别的选项,一般用来匹配目录
=      #进行普通字符精确匹配
@     #"@" 定义一个命名的 location,使用在内部定向时,例如 error_page, try_files

 

location 匹配的优先级(与location在配置文件中的顺序无关)
= 精确匹配会第一个被处理。如果发现精确匹配,nginx停止搜索其他匹配。
普通字符匹配,正则表达式规则和长的块规则将被优先和查询匹配,也就是说如果该项匹配还需去看有没有正则表达式匹配和更长的匹配。
^~ 则只匹配该规则,nginx停止搜索其他匹配,否则nginx会继续处理其他location指令。
最后匹配理带有"~"和"~*"的指令,如果找到相应的匹配,则nginx停止搜索其他匹配;当没有正则表达式或者没有正则表达式被匹配的情况下,那么匹配程度最高的逐字匹配指令会被使用。

location 优先级官方文档

  1. Directives with the = prefix that match the query exactly. If found, searching stops.
  2. All remaining directives with conventional strings, longest match first. If this match used the ^~ prefix, searching stops.
  3. Regular expressions, in order of definition in the configuration file.
  4. If #3 yielded a match, that result is used. Else the match from #2 is used.
  1. =前缀的指令严格匹配这个查询。如果找到,停止搜索。
  2. 所有剩下的常规字符串,最长的匹配。如果这个匹配使用^〜前缀,搜索停止。
  3. 正则表达式,在配置文件中定义的顺序。
  4. 如果第3条规则产生匹配的话,结果被使用。否则,使用第2条规则的结果。  

例如

location = / {
# 只匹配"/".
[ configuration A ]
}
location / {
# 匹配任何请求,因为所有请求都是以"/"开始
# 但是更长字符匹配或者正则表达式匹配会优先匹配
[ configuration B ]
}
location ^~ /images/ {
# 匹配任何以 /images/ 开始的请求,并停止匹配 其它location
[ configuration C ]
}
location ~* .(gif|jpg|jpeg)$ {
# 匹配以 gif, jpg, or jpeg结尾的请求.
# 但是所有 /images/ 目录的请求将由 [Configuration C]处理.
[ configuration D ]
}

 

请求URI例子:

  • / -> 符合configuration A
  • /documents/document.html -> 符合configuration B
  • /images/1.gif -> 符合configuration C
  • /documents/1.jpg ->符合 configuration D

@location 例子
error_page 404 = @fetch;

location @fetch(
proxy_pass http://fetch;
)

转载于:https://www.cnblogs.com/yuan951/p/7635104.html

<think>好的,我现在需要解决用户的问题:如何在Nginx中配置多个server块绑定到同一个端口,并了解相关的最佳实践。首先,我应该回忆一下Nginx的基本配置结构,特别是server块的作用用法。 根据用户提供的引用资料,特别是引用[3][4],Nginx的配置是通过不同的上下文块来组织的,比如http、serverlocation等。每个server块可以定义不同的虚拟主机,处理不同的请求。而server块是放在http上下文中的,不能嵌套在其他块里。接下来,我需要确认多个server块监听同一个端口是否可行,以及如何区分它们。 用户提到想绑定到同一个端口,这通常是通过server_name指令来实现的。Nginx会根据请求的Host头来匹配对应的server块。例如,不同的域名指向同一个IP端口,Nginx会根据域名选择相应的server块处理请求。因此,配置多个server块在同一个端口的关键在于正确设置server_name,并确保每个server块有唯一的server_name或默认处理。 接下来,我需要考虑配置的具体写法。例如,如果有两个域名example.comtest.com都指向同一个服务器的80端口,那么配置中会有两个server块,分别监听80端口,但server_name不同。同时,还需要设置默认的server块,处理不匹配任何server_name的请求,通常返回444错误或者跳转到默认页面。 此外,最佳实践包括正确设置默认服务器,避免配置冲突,使用通配符或正则表达式处理泛域名,以及合理组织配置文件的结构,比如使用include指令将不同的server块分开存放,便于管理。 还要注意SSL/TLS配置的情况,如果使用HTTPS,每个server块需要指定自己的SSL证书密钥,这可能需要在listen指令中添加ssl参数,并配置相应的证书路径。同时,可能需要处理HTTP到HTTPS的重定向,这可以通过单独的server块监听80端口,并返回301重定向到HTTPS的地址。 另外,性能优化方面,确保每个server块的配置高效,避免不必要的复杂匹配规则,优先使用精确匹配server_name,减少Nginx处理请求时的匹配时间。同时,检查配置文件的语法是否正确,使用nginx -t命令测试配置,避免重启服务时出现错误。 最后,根据用户提供的引用[5],提到了使用keepalivedNginx实现高可用,这可能与多个server块配置无直接关系,但可以作为扩展内容,提醒用户在配置高可用环境时的注意事项,比如虚拟IP健康检查脚本的设置。</think>在Nginx中通过多个$server$块绑定到同一端口是典型的虚拟主机配置方法,主要依赖$server_name$指令实现请求分流。以下是具体实现步骤最佳实践: ### 一、基础配置方法 1. **创建多个$server$块** 每个块监听相同端口但处理不同域名请求,例如: ```nginx # 处理example.com的请求 server { listen 80; server_name example.com; root /var/www/example; # 其他配置... } # 处理test.com的请求 server { listen 80; server_name test.test.com; root /var/www/test; # 其他配置... } ``` 2. **设置默认服务器** 定义默认处理未匹配域名的请求,建议返回444状态码关闭连接: ```nginx server { listen 80 default_server; return 444; } ``` ### 二、高级场景实践 1. **通配符域名匹配** 使用星号匹配二级域名: ```nginx server { listen 80; server_name *.example.com; # 处理所有xxx.example.com子域名 } ``` 2. **正则表达式匹配** 使用波浪号定义正则表达式匹配: ```nginx server { listen 80; server_name ~^(www\.)?(?<domain>.+)$; # 捕获带或不带www的域名 } ``` ### 三、HTTPS配置要点 1. **多域名SSL证书配置** 为不同域名指定对应证书: ```nginx server { listen 443 ssl; server_name example.com; ssl_certificate /path/to/example.crt; ssl_certificate_key /path/to/example.key; } server { listen 443 ssl; server_name test.com; ssl_certificate /path/to/test.crt; ssl_certificate_key /path/to/test.key; } ``` 2. **HTTP到HTTPS重定向** 强制所有HTTP请求跳转至HTTPS: ```nginx server { listen 80; server_name example.com; return 301 https://$host$request_uri; } ``` ### 四、最佳实践指南 1. **优先级控制** Nginx按以下顺序匹配$server$块: - 精确域名匹配 - 最长前缀通配符(如*.example.com) - 最长后缀通配符(如mail.*) - 第一个匹配的正则表达式 2. **配置文件管理** 将不同$server$块拆分为单独文件,通过$include$指令加载: ```nginx http { include /etc/nginx/conf.d/*.conf; } ``` 3. **性能优化** - 优先使用精确域名而非正则表达式 - 避免在$server$块内进行复杂计算 - 对静态资源启用$sendfile$缓存 4. **配置验证** 修改后必须执行配置检查: ```bash nginx -t && systemctl reload nginx ``` ### 五、典型错误排查 1. **端口冲突** 确保没有其他进程占用端口,检查命令: ```bash ss -tulpn | grep :80 ``` 2. **DNS解析问题** 验证域名解析正确性: ```bash dig example.com +short ``` 3. **请求头缺失** 当直接通过IP访问时,需设置$Host$头部: ```bash curl -H "Host: example.com" http://server_ip ``` [^1]: [^3]: Nginx通过server块实现虚拟主机配置,不同server_name可共享同一端口[^3] [^2]: [^4]: location指令应放置在server块内处理URI路由[^4]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值