Nginx Location配置总结[转载]

注意

nginx配置时要特别注意语法问题比如if后面要留空格,

分别匹配指定资源跳转和是否存在自定义header头跳转,需要开启下划线支持

location ~ \.(gif|jpg|png|js|css)$ {
  rewrite ^(.*)$  https://$host$1 last;
}
if ( $http_ver ~ ^$ ){
  rewrite ^(.*)$  https://$host$1 last;
}

 

语法规则

location [=|~|~*|^~] /uri/ { … }

= 开头表示精确匹配
^~ 开头表示uri以某个常规字符串开头,理解为匹配 url路径即可。nginx不对url做编码,因此请求为/static/20%/aa,可以被规则^~ /static/ /aa匹配到(注意是空格)。
~ 开头表示区分大小写的正则匹配
~*  开头表示不区分大小写的正则匹配
!~和!~*分别为区分大小写不匹配及不区分大小写不匹配 的正则
/ 通用匹配,任何请求都会匹配到。
多个location配置的情况下匹配顺序为(参考资料而来,还未实际验证,试试就知道了,不必拘泥,仅供参考):
首先匹配 =,其次匹配^~, 其次是按文件中顺序的正则匹配,最后是交给 / 通用匹配。当有匹配成功时候,停止匹配,按当前匹配规则处理请求。
例子,有如下匹配规则:
location = / {
  #规则A
}
location = /login {
  #规则B
}
location ^~ /static/ {
  #规则C
}
location ~ \.(gif|jpg|png|js|css)$ {
  #规则D
}
location ~* \.png$ {
  #规则E
}
location !~ \.xhtml$ {
  #规则F
}
location !~* \.xhtml$ {
  #规则G
}
location / {
  #规则H
}
那么产生的效果如下:
访问根目录/, 比如http://localhost/ 将匹配规则A
访问 http://localhost/login 将匹配规则B,http://localhost/register 则匹配规则H
访问 http://localhost/static/a.html 将匹配规则C
访问 http://localhost/a.gif, http://localhost/b.jpg 将匹配规则D和规则E,但是规则D顺序优先,规则E不起作用,而 http://localhost/static/c.png 则优先匹配到规则C
访问 http://localhost/a.PNG 则匹配规则E,而不会匹配规则D,因为规则E不区分大小写。
访问 http://localhost/a.xhtml 不会匹配规则F和规则G,http://localhost/a.XHTML不会匹配规则G,因为不区分大小写。规则F,规则G属于排除法,符合匹配规则但是不会匹配到,所以想想看实际应用中哪里会用到。
访问 http://localhost/category/id/1111 则最终匹配到规则H,因为以上规则都不匹配,这个时候应该是nginx转发请求给后端应用服务器,比如FastCGI(php),tomcat(jsp),nginx作为方向代理服务器存在。
所以实际使用中,个人觉得至少有三个匹配规则定义,如下:
#直接匹配网站根,通过域名访问网站首页比较频繁,使用这个会加速处理,官网如是说。
#这里是直接转发给后端应用服务器了,也可以是一个静态首页
# 第一个必选规则
location = / {
   proxy_pass http://tomcat:8080/index
}
# 第二个必选规则是处理静态文件请求,这是nginx作为http服务器的强项
# 有两种配置模式,目录匹配或后缀匹配,任选其一或搭配使用
location ^~ /static/ {
   root /webroot/static/;
}
location ~* \.(gif|jpg|jpeg|png|css|js|ico)$ {
   root /webroot/res/;
}
#第三个规则就是通用规则,用来转发动态请求到后端应用服务器
#非静态文件请求就默认是动态请求,自己根据实际把握
#毕竟目前的一些框架的流行,带.php,.jsp后缀的情况很少了
location / {
   proxy_pass http://tomcat:8080/
}

ReWrite语法

last – 基本上都用这个Flag。
break – 中止Rewirte,不在继续匹配
redirect – 返回临时重定向的HTTP状态302
permanent – 返回永久重定向的HTTP状态301
1、下面是可以用来判断的表达式:
-f和!-f用来判断是否存在文件
-d和!-d用来判断是否存在目录
-e和!-e用来判断是否存在文件或目录
-x和!-x用来判断文件是否可执行
2、下面是可以用作判断的全局变量
例:http://localhost:88/test1/test2/test.php
$host:localhost
$server_port:88
$request_uri:http://localhost:88/test1/test2/test.php
$document_uri:/test1/test2/test.php
$document_root:D:\nginx/html
$request_filename:D:\nginx/html/test1/test2/test.php

Redirect语法(302跳转)
server {
listen 80;
server_name start.igrow.cn;
index index.html index.php;
root html;
if ($http_host !~ “^star\.igrow\.cn$&quot {
rewrite ^(.*) http://star.igrow.cn$1 redirect;
}
}
防盗链
location ~* \.(gif|jpg|swf)$ {
valid_referers none blocked start.igrow.cn sta.igrow.cn;
if ($invalid_referer) {
rewrite ^/ http://$host/logo.png;
}
}
根据文件类型设置过期时间
location ~* \.(js|css|jpg|jpeg|gif|png|swf)$ {
if (-f $request_filename) {
expires 1h;
break;
}
}
禁止访问某个目录
location ~* \.(txt|doc)${
root /data/www/wwwroot/linuxtone/test;
deny all;
}

一些可用的全局变量

$args
$content_length
$content_type
$document_root
$document_uri
$host
$http_user_agent
$http_cookie
$limit_rate
$request_body_file
$request_method
$remote_addr
$remote_port
$remote_user
$request_filename
$request_uri
$query_string
$scheme
$server_protocol
$server_addr
$server_name
$server_port
$uri

服务器流量异常分析

服务器流量分析工具常用的有两个

  1. iftop 查看某个网卡流量和对应的请求ip地址与端口
  2. nethogs 查看进程流量

分别安装两个工具:

yum install iftop
yum install nethogs

分析步骤

  1. 使用nethogs查看是否有进程产生异常流量
  2. 使用iftop检查所有网卡流量和出入流量ip地址与端口
  3. 通过netstat查看占用的端口程序和用户信息
  4. 禁用对应ip请求

大致使用到的命令如下:

#nethogs
#iftop -i eth0
#netstat -antp
#iptables -I INPUT -s xxx.xxx.xxx.xxx -j DROP

工具使用说明

iftop常用命令

默认监控第一块网卡流量,默认ip要倒过来读,如1.180.97.119应该为119.97.180.1,默认情况下通信双方都会占用一个端口,=>代表发送数据,<= 代表接收数据

  • -i 指定网卡
  • 按n切换显示本机的IP或主机名;
  • 按D切换是否显示远端目标主机的端口信息;
  • 按S切换是否显示本机的端口信息;
  • 按N切换显示端口号或端口服务名称;
  • 按o切换是否固定只显示当前的连接;

显示说明:

TX:发送流量
RX:接收流量
TOTAL:总流量
peak:流量峰值
rates:分别表示过去 2s 10s 40s 的平均流量

netstat 查看端口信息

netstat查看哪些端口已经被开启或者正在通信

常用命令 -antp

  • -a 所有连接
  • -n 只查看ip,禁用域名解析功能
  • -t 列出TCP协议的连接
  • -p 查看进程信息

端口状态

  • LISTEN 正在监听
  • ESTABLISHED 正在通信
  • CLOSE_WAIT 对方主动关闭连接或者网络异常导致连接中断
  • TIME_WAIT 我方主动调用close()断开连接

iptables 禁用请求

列出 INPUT链 所有的规则:iptables -L INPUT --line-numbers
删除某条规则,其中5代表序号(序号可用上面的命令查看):iptables -D INPUT 5
开放指定的端口:iptables -A INPUT -p tcp --dport 80 -j ACCEPT
禁止指定的端口:iptables -A INPUT -p tcp --dport 80 -j DROP
禁止指定的IP: iptables -I INPUT -s 119.97.180.61 -j DROP
允许指定的IP: iptables -D INPUT -s 61.183.163.214 -j DROP

拒绝所有的端口:iptables -A INPUT -j DROP

INPUT 入网流量 (用户访问)
OUTPUT 出网流量 (Linux本身发送)

总结

使用netstat可以查看服务器是否有异常通信端口被开启

mongodb连接数暴增导致 Remote server has closed the connection拒绝连接的问题处理

问题描述

线上服务器突然报Failed to connect to: 127.0.0.1:27017: Remote server has closed the connection 重启后没过多久问题依旧,通过查询得知每个php-fpm都会占用一个连接资源并不会使用后及时释放,查看线上服务,发现php-fpm进程存在600+,存在大量PPID不存在的进程

处理过程与原因分析

查看cpu和磁盘io发现没有异常,通过查看mongo日志发现有大量连接请求,因为有多处用到了mongodb,为了判断请求源,临时修改项目mongodb配置ip地址,发现请求停止,分析大量请求的原因可能是由什么系统定时任务引起, 临时暂停所有系统定时任务.

根据php-fpm进程数量初步排除mongodb自身问题,重点检查php-fpm进程产生的原因分析有如下几个:

  1. php-fpm数量由php-fpm.con配置,检查php-fpm.conf发现配置文件一切正常,可能的是由其他方式启动的php-fpm进程,并不受限制
  2. 启动的php-fpm因为异常操作导致僵死

因为有php-fpm.conf文件限制,所以判断可能是第一点引起,回想系统有地方用到了pcntl_fork方法利用子进程处理推送等操作,通过查询系统日志和php-fpm进程产生时间,发现基本都有类似子进程的操作.通过网络搜索pcntl_fork产生大量进程原因发现确实会有这种问题发生使用pcntl_fork前需要注册SIGCHLD信号.修改代码后重启php-fpm,观察效果,准备后期全部改用列队处理

后续处理

假设子进程是正常生成的并且可以被正常回收,但是如果一时刻有大量推送产生那么还是会出现上述问题,只需剥离推送代码使用列队处理即可.

 

使用到的技能

  • 通过strace -p 调试进程执行调用情况
  • 通过进程产生时间核对日志查找查找原因
  • 子进程的正确处理方式
  • php-fpm慢日志查询与设置
  • 通过追踪notice和Warning类型的日志有时会有意外收获

https ssl证书申请和部署流程

1.申请免费的StartSSL证书http://www.itbulu.com/startssl.html

2.获取startssl官方的根证书

wget http://www.startssl.com/certs/ca.pem
wget http://www.startssl.com/certs/sub.class1.server.ca.pem
#合并两个证书 cat ca.pem sub.class1.server.ca.pem >> www.wwjie.cn.crt

3.配置通过openssl安装导入,避免nginx启动时输入密码

openssl rsa -in ssl.key -out /etc/nginx/conf.d/ssl/ssl_ca.key

2.配置nginx加载证书

listen       443;
ssl    on;
ssl_certificate    /usr/local/nginx/conf/www.wwjie.cn.crt;   #你从StartSSL下载证书放的路径
ssl_certificate_key     /usr/local/nginx/conf/ssl_ca.key;  #openssl生成key路径
ssl_session_timeout 5m;

强制https

server {  
    listen  80;  
    server_name www.wwjie.com wwjie.cn;  
    rewrite ^(.*)$  https://$host$1 permanent;  
}

 

JAVA环境配置

 

使用rpm更简单的安装方式

wget http://download.oracle.com/otn-pub/java/jdk/8u111-b14/jdk-8u111-linux-x64.rpm?AuthParam=1482392334_3efc8569d413a3dfe7743b92d33715d0
#rpm -ivh jdkxxxx.rpm

java -version   不是openjdk则成功,如果没有成功则修改环境变量,参考下面的配置环境变量

vim /etc/profile 加入如下


JAVA_HOME=/usr/java/jdk1.8.0_91
PATH=$JAVA_HOME/bin:$PATH
CLASSPATH=$JAVA_HOME/jre/lib/ext:$JAVA_HOME/lib/tools.jar
export PATH JAVA_HOME CLASSPATH

source /etc/profile

 

转载 http://www.cnblogs.com/jilianggqq/p/4141641.html

安装jdk

  1. http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html中下载jdk的安装文件。由于我的Linux是32位的,因此我下载jdk-8u25-linux-i586.tar.gz文件。
  2. 新建/usr/java文件夹,将jdk-8u25-linux-i586.tar.gz放到该文件夹中,并将工作目录切换到/usr/java目录下。
  3. 执行命令tar -zxvf jdk-8u25-linux-i586.gz 进行解压,解压后发现/usr/java多了一个jdk1.8.0_25文件夹。
  4. 通过以上步骤,jdk就已经全部安装完成了。下面,就是环境变量的配置。

配置环境变量

  1. 使用vim /etc/profile编辑profile文件
  2. 在/etc/profile底部加入如下内容

JAVA_HOME=/usr/java/jdk1.8.0_25
PATH=$JAVA_HOME/bin:$PATH
CLASSPATH=$JAVA_HOME/jre/lib/ext:$JAVA_HOME/lib/tools.jar
export PATH JAVA_HOME CLASSPATH

  1. 以上,环境变量配置完成。需要注意的是,PATH在配置的时候,一定要把$JAVA_HOME/bin放在前面,不然使用java命令时,系统会找到以前的java,再不往下找了。这样java这个可执行文件运行的目录其实不在$JAVA_HOME/bin下,而在其它目录下,会造成很大的问题。
  2. 还要注意,以前其它教程写的CLASSPATH=$JAVA_HOME/lib.tools.jar,不知道以前的版本是怎么样的,现在的版本是没有这样的jar包的
  3. 最后使用source /etc/profile让profile文件立即生效。

命令测试

  1. 使用javac命令,不会出现command not found错误
  2. 使用java -version,出现版本为java version “1.8.0_25”
  3. echo $JAVA_HOME, echo $CLASSPATH, echo $PATH,看看自己的配置是否都正确。

使用intellij IDEA配置Golang开发环境

配置步骤

一.下载安装 intellij IDEA

二.新建一个go项目目录目录,点击file->open打开新建的go项目然后新建一个.go结尾的文件,打开文件后会提示安装golang插件,按提示安装插件并重启idea

三.配置SDK点击 file->Project Structure

QQ截图20160322182010

单机右侧的SDKs几点+选择GoSDK

QQ截图20160322182025

在弹出的选择框中选择GO的安装目录即可.

linux虚拟机网卡配置

linux虚拟复制后经常会出现无法获取ip或网卡无法启动等问题,处理过程如下:

1.在虚拟机网卡设置界面重新生成MAC地址

2.修改对应网卡硬件配置文件

#将网卡编号修改为对应的编号,如eth0,MAC地址修改为生成的MAC地址
vim /etc/udev/rules.d/*-net.rules

3.修改网卡启动参数

#将网卡编号修改为对应的编号,如eth0,MAC地址修改为生成的MAC地址
vim /etc/sysconfig/network-scripts/ifcfg-eth0

 

修改centos6源,添加Atomic源

Atomic源支持Fedora,RHEL和CentOS的YUM包管理。这里系统是CentOS6.2。

安装方法很简单:

wget -q -O – http://www.atomicorp.com/installers/atomic | sh

在导入key的界面等待几秒会自动导入,  然后输入yes可以设置成默认源

安装完后在/etc/yum.repos.d/目录会有一个atomic.repo文件。

AB(Apache Benchmark)测试工具使用

安装Apache Benchmark

Install apr-util(need to run ab):

yum install apr-util

Install yum-utils:

yum install yum-utils

Download httpd an extract ab:

mkdir ~/httpd
cd ~/httpd
yumdownloader httpd
rpm2cpio httpd-2.2.3-43.el5.centos.3.i386.rpm | cpio -idmv
mv usr/bin/ab /usr/bin/ab
cd ~
rm -rf ~/httpd

常用命令

  • -c    并发数
  • -n    总请求次数
  • -t     等待最大秒数
  • -s    每个响应最大超时时间

官方文档

执行结果

$ ab -c 10 -n 10000 http://localhost:8080/ 
This is ApacheBench, Version 2.3 <$Revision: 1663405 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
Completed 6000 requests
Completed 7000 requests
Completed 8000 requests
Completed 9000 requests
Completed 10000 requests
Finished 10000 requests


Server Software:        
Server Hostname:        localhost
Server Port:            8080

Document Path:          /
Document Length:        0 bytes

Concurrency Level:      10
Time taken for tests:   0.290 seconds
Complete requests:      10000
Failed requests:        0
Total transferred:      1160000 bytes
HTML transferred:       0 bytes
Requests per second:    34461.01 [#/sec] (mean)
Time per request:       0.290 [ms] (mean)
Time per request:       0.029 [ms] (mean, across all concurrent requests)
Transfer rate:          3903.79 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.0      0       2
Processing:     0    0   0.2      0       5
Waiting:        0    0   0.2      0       5
Total:          0    0   0.2      0       5

Percentage of the requests served within a certain time (ms)
  50%      0
  66%      0
  75%      0
  80%      0
  90%      0
  95%      1
  98%      1
  99%      1
 100%      5 (longest request)

 

Golang学习笔记

Go安装

1.linux下编译安装

安装gcc等工具

sudo apt-get install gcc libc6-dev

下载源码,运行all.bash即可

hg clone -u release https://code.google.com/p/go
cd go/src
./all.bash

2.windows下安装

下载.msi文件安装即可

3.环境变量配置

  1. 添加C:Go\bin目录到path (直接使用命令调用go)
  2. 添加C:Go\目录到GOROOT (配置Go安装目录,编译时需要调用扩展包)
  3. 添加C:\Users\wang\Desktop\golang (项目地址,底下包含三个目录bin,pkg,src, src存放源代码)

linux 使用export GOPATH=/home/apple/mygo  添加,或者加入~/.bash_profile(单一用户)

信号处理

通常程序需要监听系统信号来实现平稳退出等操作,golang可以很方便的处理系统信号

import (
	"os/signal"
	"syscall"
	"os"
)

func main() {
	sigs := make(chan os.Signal, 1)
	signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
	<-sigs //阻塞等待信号
}

可以将<-sigs 这一步单独交给一个线程来监控

linux信号列表

$ kill -l
 1) SIGHUP	 2) SIGINT	 3) SIGQUIT	 4) SIGILL	 5) SIGTRAP
 6) SIGABRT	 7) SIGBUS	 8) SIGFPE	 9) SIGKILL	10) SIGUSR1
11) SIGSEGV	12) SIGUSR2	13) SIGPIPE	14) SIGALRM	15) SIGTERM
16) SIGSTKFLT	17) SIGCHLD	18) SIGCONT	19) SIGSTOP	20) SIGTSTP
21) SIGTTIN	22) SIGTTOU	23) SIGURG	24) SIGXCPU	25) SIGXFSZ
26) SIGVTALRM	27) SIGPROF	28) SIGWINCH	29) SIGIO	30) SIGPWR
31) SIGSYS	34) SIGRTMIN	35) SIGRTMIN+1	36) SIGRTMIN+2	37) SIGRTMIN+3
38) SIGRTMIN+4	39) SIGRTMIN+5	40) SIGRTMIN+6	41) SIGRTMIN+7	42) SIGRTMIN+8
43) SIGRTMIN+9	44) SIGRTMIN+10	45) SIGRTMIN+11	46) SIGRTMIN+12	47) SIGRTMIN+13
48) SIGRTMIN+14	49) SIGRTMIN+15	50) SIGRTMAX-14	51) SIGRTMAX-13	52) SIGRTMAX-12
53) SIGRTMAX-11	54) SIGRTMAX-10	55) SIGRTMAX-9	56) SIGRTMAX-8	57) SIGRTMAX-7
58) SIGRTMAX-6	59) SIGRTMAX-5	60) SIGRTMAX-4	61) SIGRTMAX-3	62) SIGRTMAX-2
63) SIGRTMAX-1	64) SIGRTMAX

其中SIGINT 一般为Ctrl+C

参考linux信号列表

Golang原子操作

golang提供了sync/*原子操作方法,其中常用的包括:

只执行一次某个函数Once

package main
import (
    "sync"
)
var once sync.Once
onceFunc(){
    //todo....
}
func main(){
    go  once.Do(onceFunc)
    go  once.Do(onceFunc)
    //sleep ..
}

原子计数操作atomic

package main
import (
    "sync/atomic"
)
var count int32 = 0
func add(){
    atomic.AddInt32(&count, 1)
    Println("count:", atomic.LoadInt32(&count))
}
func main(){
    go add()
    go add()
    //sleep ..
}

等待一组线程结束WaitGroup

package main
import (
    "sync"
)
var count int32 = 0
func EchoNumber(n int){
    Println(n)
}
func main(){
    var wg sync.WaitGroup
	for i := 0; i < 5; i = i + 1 {
		wg.Add(1)
		go func(n int) {
			defer wg.Add(-1)
			EchoNumber(n)
		}(i)
	}
    wg.Wait()
}