【转】一文弄懂Nginx的location匹配

由于团队在进行前后端分离,前端接管了Nginx和node层,在日常的工作中,跟Nginx打交道的时候挺多的。之前对location的匹配规则是一知半解的,为了搞明白location是如何匹配的,查了些资料总结此文。希望能给大家带来帮助。

语法规则

location [ = | ~ | ~* | ^~ ] uri { ... }
location @name { ... }

语法规则很简单,一个location关键字,后面跟着可选的修饰符,后面是要匹配的字符,花括号中是要执行的操作。

修饰符

  • = 表示精确匹配。只有请求的url路径与后面的字符串完全相等时,才会命中。
  • ~ 表示该规则是使用正则定义的,区分大小写。
  • ~* 表示该规则是使用正则定义的,不区分大小写。
  • ^~ 表示如果该符号后面的字符是最佳匹配,采用该规则,不再进行后续的查找。

匹配过程

对请求的url序列化。例如,对%xx等字符进行解码,去除url中多个相连的/,解析url中的...等。这一步是匹配的前置工作。

location有两种表示形式,一种是使用前缀字符,一种是使用正则。如果是正则的话,前面有~~*修饰符。

具体的匹配过程如下:

首先先检查使用前缀字符定义的location,选择最长匹配的项并记录下来。

如果找到了精确匹配的location,也就是使用了=修饰符的location,结束查找,使用它的配置。

然后按顺序查找使用正则定义的location,如果匹配则停止查找,使用它定义的配置。

如果没有匹配的正则location,则使用前面记录的最长匹配前缀字符location。

基于以上的匹配过程,我们可以得到以下两点启示:

  1. 使用正则定义的location在配置文件中出现的顺序很重要。因为找到第一个匹配的正则后,查找就停止了,后面定义的正则就是再匹配也没有机会了。
  2. 使用精确匹配可以提高查找的速度。例如经常请求/的话,可以使用=来定义location。

示例

接下来我们以一个例子来具体说明一下匹配过程。

假如我们有下面的一段配置文件:

location = / {
    [ configuration A ]
}

location / {
    [ configuration B ]
}

location /user/ {
    [ configuration C ]
}

location ^~ /images/ {
    [ configuration D ]
}

location ~* \.(gif|jpg|jpeg)$ {
    [ configuration E ]
}

请求/精准匹配A,不再往下查找。

请求/index.html匹配B。首先查找匹配的前缀字符,找到最长匹配是配置B,接着又按照顺序查找匹配的正则。结果没有找到,因此使用先前标记的最长匹配,即配置B。

请求/user/index.html匹配C。首先找到最长匹配C,由于后面没有匹配的正则,所以使用最长匹配C。
请求/user/1.jpg匹配E。首先进行前缀字符的查找,找到最长匹配项C,继续进行正则查找,找到匹配项E。因此使用E。

请求/images/1.jpg匹配D。首先进行前缀字符的查找,找到最长匹配D。但是,特殊的是它使用了^~修饰符,不再进行接下来的正则的匹配查找,因此使用D。这里,如果没有前面的修饰符,其实最终的匹配是E。大家可以想一想为什么。

请求/documents/about.html匹配B。因为B表示任何以/开头的URL都匹配。在上面的配置中,只有B能满足,所以匹配B。

location @name的用法

@用来定义一个命名location。主要用于内部重定向,不能用来处理正常的请求。其用法如下:

location / {
    try_files $uri $uri/ @custom
}
location @custom {
    # ...do something
}

上例中,当尝试访问url找不到对应的文件就重定向到我们自定义的命名location(此处为custom)。

值得注意的是,命名location中不能再嵌套其它的命名location。

URL尾部的/需不需要

关于URL尾部的/有三点也需要说明一下。第一点与location配置有关,其他两点无关。

  1. location中的字符有没有/都没有影响。也就是说/user//user是一样的。
  2. 如果URL结构是https://domain.com/的形式,尾部有没有/都不会造成重定向。因为浏览器在发起请求的时候,默认加上了/。虽然很多浏览器在地址栏里也不会显示/。这一点,可以访问baidu验证一下。
  3. 如果URL的结构是https://domain.com/some-dir/。尾部如果缺少/将导致重定向。因为根据约定,URL尾部的/表示目录,没有/表示文件。所以访问/some-dir/时,服务器会自动去该目录下找对应的默认文件。如果访问/some-dir的话,服务器会先去找some-dir文件,找不到的话会将some-dir当成目录,重定向到/some-dir/,去该目录下找默认文件。可以去测试一下你的网站是不是这样的。

总结

location的配置有两种形式,前缀字符和正则。查找匹配的时候,先查找前缀字符,选择最长匹配项,再查找正则。正则的优先级高于前缀字符。

正则的查找是按照在配置文件中的顺序进行的。因此正则的顺序很重要,建议越精细的放的越靠前。

使用=精准匹配可以加快查找的顺序,如果根域名经常被访问的话建议使用=

拓展

转自:https://segmentfault.com/a/1190000013267839

电影《摇滚小子》2018

电影《摇滚小子》2018

影片讲述了小主人公“宝贝”在爸妈分居后,因妈妈工作原因,转学到姥姥家附近学校后发生的故事:“宝贝”妈妈忙于工作,忽视了对他的陪伴,使“宝贝”在陌生的环境里感觉更加孤单,但好在他遇到了一些新的朋友。他们一起在周边闯荡“冒险”,机缘巧合偶遇了自己的音乐启蒙导师……在经历了众多动人心弦的故事后,他们组建了自己的乐队,并参加了迷笛音乐节……

豆瓣预告片

纯音乐 Because of You – Josh Vietti

《妈妈》——摇滚小子电影主题曲影片。

腾讯视频VIP观看


记录一下,暂时不太写影评啊. 😂

mongoose 连接 MongoDB 数据库的 useNewUrlParser 警告解决办法

useNewUrlParser

用下面这段代码连接MongoDB数据库出现了警告提示:

const mongoose = require('mongoose');

mongoose.connect('mongodb://localhost/test');

警告提示:

(node:10626) DeprecationWarning: current URL string parser is deprecated, and will be removed in a future version. To use the new parser, pass option { useNewUrlParser: true } to MongoClient.connect.

更改为一下代码即可:

const mongoose = require('mongoose');

mongoose.connect('mongodb://localhost/test', { useNewUrlParser: true }, (err,res) => {
    if (!err) {
        console.log('连接数据成功!')
    } else {
        console.log('连接数据失败!');
    }
})

MongoDB 配置文件mongod.conf

配置文件及简单注释(参考官方3.2文档):

systemLog:
   # verbosity: 0  #日志等级,0-5,默认0
   # quiet: false  #限制日志输出,
   # traceAllExceptions: true  #详细错误日志
   # syslogFacility: user #记录到操作系统的日志级别,指定的值必须是操作系统支持的,并且要以--syslog启动
   path: /Users/mhq/projects/db/mongo/logs/log.txt  #日志路径。
   logAppend: false #启动时,日志追加在已有日志文件内还是备份旧日志后,创建新文件记录日志, 默认false
   logRotate: rename #rename/reopen。rename,重命名旧日志文件,创建新文件记录;reopen,重新打开旧日志记录,需logAppend为true
   destination: file #日志输出方式。file/syslog,如果是file,需指定path,默认是输出到标准输出流中
   timeStampFormat: iso8601-local #日志日期格式。ctime/iso8601-utc/iso8601-local, 默认iso8601-local
   # component: #各组件的日志级别
   #    accessControl:
   #       verbosity: <int>
   #    command:
   #       verbosity: <int>

processManagement:
   fork: true #以守护进程运行 默认false
   # pidFilePath: <string> #PID 文件位置

net:
   port: 27017 #监听端口,默认27017
   bindIp: 127.0.0.1 #绑定监听的ip,deb和rpm包里有默认的配置文件(/etc/mongod.conf)里面默认配置为127.0.0.1,若不限制IP,务必确保认证安全,多个Ip用逗号分隔
   maxIncomingConnections: 65536 #最大连接数,可接受的连接数还受限于操作系统配置的最大连接数
   wireObjectCheck: true #校验客户端的请求,防止错误的或无效BSON插入,多层文档嵌套的对象会有轻微性能影响,默认true
   ipv6: false #是否启用ipv6,3.0以上版本始终开启
   unixDomainSocket: #unix socket监听,仅适用于基于unix的系统
      enabled: false #默认true
      pathPrefix: /tmp #路径前缀,默认/temp
      filePermissions: 0700 #文件权限 默认0700
   http: #警告 确保生产环境禁用HTTP status接口、REST API以及JSON API以防止数据暴露和漏洞攻击
      enabled: false #是否启用HTTP接口、启用会增加网络暴露。3.2版本后停止使用HTTP interface
      JSONPEnabled: false #JSONP的HTTP接口
      RESTInterfaceEnabled: false #REST API接口
   # ssl: #估计用不到,所以没有自己看
   #    sslOnNormalPorts: <boolean>  # deprecated since 2.6
   #    mode: <string>
   #    PEMKeyFile: <string>
   #    PEMKeyPassword: <string>
   #    clusterFile: <string>
   #    clusterPassword: <string>
   #    CAFile: <string>
   #    CRLFile: <string>
   #    allowConnectionsWithoutCertificates: <boolean>
   #    allowInvalidCertificates: <boolean>
   #    allowInvalidHostnames: <boolean>
   #    disabledProtocols: <string>
   #    FIPSMode: <boolean>

security:
   authorization: enabled # enabled/disabled #开启客户端认证
   javascriptEnabled:  true #启用或禁用服务器端JavaScript执行
   # keyFile: <string> #密钥路径
   # clusterAuthMode: <string> #集群认证方式
   # enableEncryption: <boolean>
   # encryptionCipherMode: <string>
   # encryptionKeyFile: <string>
   # kmip:
   #    keyIdentifier: <string>
   #    rotateMasterKey: <boolean>
   #    serverName: <string>
   #    port: <string>
   #    clientCertificateFile: <string>
   #    clientCertificatePassword: <string>
   #    serverCAFile: <string>
   # sasl:
   #    hostName: <string>
   #    serviceName: <string>
   #    saslauthdSocketPath: <string>
   

# setParameter: #设置参数
#    <parameter1>: <value1>
#    <parameter2>: <value2>

storage:
   dbPath: /Users/mhq/projects/db/mongo/test/ #数据库,默认/data/db,如果使用软件包管理安装的查看/etc/mongod.conf
   indexBuildRetry: true #重启时,重建不完整的索引
   # repairPath: <string>  #--repair操作时的临时工作目录,默认为dbPath下的一个_tmp_repairDatabase_<num>的目录
   journal: 
      enabled: true #启动journal,64位系统默认开启,32位默认关闭
      # commitIntervalMs: <num> #journal操作的最大时间间隔,默认100或30
   directoryPerDB: false #使用单独的目录来存储每个数据库的数据,默认false,如果需要更改,要备份数据,删除掉dbPath下的文件,重建后导入数据
   # syncPeriodSecs: 60 #使用fsync来将数据写入磁盘的延迟时间量,建议使用默认值
   engine: wiredTiger #存储引擎,mmapv1/wiredTiger/inMemory 默认wiredTiger
   # mmapv1:
   #    preallocDataFiles: <boolean>
   #    nsSize: <int>
   #    quota:
   #       enforced: <boolean>
   #       maxFilesPerDB: <int>
   #    smallFiles: <boolean>
   #    journal:
   #       debugFlags: <int>
   #       commitIntervalMs: <num>
   # wiredTiger:
   #    engineConfig:
   #       cacheSizeGB: <number>  #缓存大小
   #       journalCompressor: <string> #数据压缩格式 none/snappy/zlib
   #       directoryForIndexes: <boolean> #将索引和集合存储在单独的子目录下,默认false
   #    collectionConfig:
   #       blockCompressor: <string> #集合数据压缩格式 
   #    indexConfig:
   #       prefixCompression: <boolean> #启用索引的前缀压缩
   # inMemory:
   #    engineConfig:
   #       inMemorySizeGB: <number>
 
operationProfiling: #性能分析
   slowOpThresholdMs: 100 #认定为查询速度缓慢的时间阈值,超过该时间的查询即为缓慢查询,会被记录到日志中, 默认100
   mode: off #operationProfiling模式 off/slowOp/all 默认off

# replication: #复制集相关
#    oplogSizeMB: <int>
#    replSetName: <string>
#    secondaryIndexPrefetch: <string>
#    enableMajorityReadConcern: <boolean>
# sharding: #集群分片相关
#    clusterRole: <string>
#    archiveMovedChunks: <boolean>

# auditLog:
#    destination: <string>
#    format: <string>
#    path: <string>
#    filter: <string>

# snmp:
#    subagent: <boolean> #当设置为true,SNMP作为代理运行
#    master: <boolean> #当设置为true,SNMP作为主服务器运行

# basisTech:
#    rootDirectory: <string>

<!– more –>

转自:https://www.jianshu.com/p/f179ce608391

CentOS 安装 MongoDB

1. 配置安装源

vi /etc/yum.repos.d/mongodb-org-3.4.repo

添加内容

[mongodb-org-3.4]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.4/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-3.4.asc

安装

yum install -y mongodb-org

设置可连接IP

vi /etc/mongod.conf

找到以下代码片段:

# network interfaces
net:
  port: 27017
  bindIp: 127.0.0.1  # Listen to local interface only, comment to listen on all interfaces.

修改 bindIp 为:

  bindIp: 0.0.0.0

0.0.0.0 为所以 IP 均可连接。

管理

开启:service mongod start
关闭:service mongod stop
重启:service mongod restart
运行中重启:service mongod try-restart 它只会在服务已经在运行中的时候重启服务。
重新加载:service mongod reload
强制重新加载:service mongod force-reload
状态:service mongod status

macOS 升级后出现xcrun: error: invalid active developer path

Xcode CommandLineTools

发现 macOS 升级系统之后总会报错 git 找不到,无论是 macOS High Sierra ,还是 macOS Mojave

错误信息:

xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun

解决方法,重装 xcode CommandLineTools:

xcode-select --install

如果没有解决问题,执行以下命令

sudo xcode-select -switch /

微信小程序“MP3”无法播放的问题

音频通道1

为小程序『我为学习狂』添加了26个英文字母读音之后,发现一个神奇的 bug ,在 MacBook 上开发可以正常播放,手机上调试就无法不放,手机上带上耳机也可以播放,发正式环境下也是无法播放。工作项目忙就一直没有解决。

今天就查看了一下mp3文件信息,发现无法正常播放的 MP3 的“音频通道”(音频通道:2)和可以正常播放的 MP3 不一样(音频通道:1),没做过音频处理,不晓得怎么改变 MP3 的音频通道。然后换了一个资源文件就可以播放了。

如果你也碰到类似 MP3 无法播放的问题,可以尝试看下自己的 MP3 资源文件的音频通道是否是“1”。

特此Mark一下。

<!– more –>

怎么播放 MP3

Page({
  data: {
    motto: '26个英文字母读音'
  },
  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady: function () {
    this.playAudio('https://m10.music.126.net/20180904013509/d01ab86edc3f28b25c2f02182ee74866/ymusic/69d2/0fd2/dda6/6035fc3521bce8f32548c4500000162e.mp3');
  },
  playAudio: function (src) {
    const innerAudioContext = wx.createInnerAudioContext()
    innerAudioContext.src = src;
    innerAudioContext.playbackRate = 0.5;
    innerAudioContext.play();
    innerAudioContext.onPlay(() => {
      console.log('开始播放')
    })
    innerAudioContext.onEnded(() => {
      console.log('播放结束')
      innerAudioContext.destroy;
    })
  }
})

TODO

如何改变 MP3 的音频通道?

wiki

wx.createInnerAudioContext()

我为学习狂

修改iTerm2“@”后面的显示名称

规则是这样的:

user@hostname

  • user: 终端输入:who an I 即可看见
  • hostname: 终端输入:hostname 即可看见

修改hostname:

示例

sudo hostname webclown

修改成功,新打开一个终端tab或者关闭终端再次打开即可看见效果

拓展