转【nginx】常见的陷阱和错误

本文出自:https://www.cnblogs.com/chenpingzhao/p/4978284.html

很多人都可以碰到一个陷阱。下面我们列出,我们经常看到的问题,以及解释如何解决这些问题。在Freenode上的#nginx IRC频道这些讨论很频繁。

1、权限

从来不要使用777权限,查看目录的权限

1
namei -om /path/to/check

2、root设置

BAD:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
server {
    server_name www.example.com;
    location / {
        root /var/www/nginx-default/;
        # [...]
      }
    location /foo {
        root /var/www/nginx-default/;
        # [...]
    }
    location /bar {
        root /var/www/nginx-default/;
        # [...]
    }
}

GOOD:

1
2
3
4
5
6
7
8
9
10
11
12
13
server {
    server_name www.example.com;
    root /var/www/nginx-default/;
    location / {
        # [...]
    }
    location /foo {
        # [...]
    }
    location /bar {
        # [...]
    }
}

3、索引设置

BAD:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
http {
    index index.php index.htm index.html;
    server {
        server_name www.example.com;
        location / {
            index index.php index.htm index.html;
            # [...]
        }
    }
    server {
        server_name example.com;
        location / {
            index index.php index.htm index.html;
            # [...]
        }
        location /foo {
            index index.php;
            # [...]
        }
    }
}

GOOD:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
http {
    index index.php index.htm index.html;
    server {
        server_name www.example.com;
        location / {
            # [...]
        }
    }
    server {
        server_name example.com;
        location / {
            # [...]
        }
        location /foo {
            # [...]
        }
    }
}

4、Using If

if 是邪恶的 参见 If Is Evil

5、Server Name (If)

BAD:

1
2
3
4
5
6
7
8
9
server {
    server_name example.com *.example.com;
        if ($host ~* ^www\.(.+)) {
            set $raw_domain $1;
            rewrite ^/(.*)$ $raw_domain/$1 permanent;
        }
        # [...]
    }
}

每次都要检测主机头,这是低效的,你应该避免,推荐使用下面的

GOOD:

1
2
3
4
5
6
7
8
server {
    server_name www.example.com;
    return 301 $scheme://example.com$request_uri;
}
server {
    server_name example.com;
    # [...]
}

这样方式便于阅读,降低了nginx的处理要求,而且也避免了硬编码(http or https)

6、Check (If) File Exists

使用if来判断是可怕的,你应该使用 try_files

BAD:

1
2
3
4
5
6
7
8
server {
    root /var/www/example.com;
    location / {
        if (!-f $request_filename) {
            break;
        }
    }
}

GOOD:

1
2
3
4
5
6
server {
    root /var/www/example.com;
    location / {
        try_files $uri $uri/ /index.html;
    }
}

try_files 意味着你测试一个队列 uri=>uri=>uri/ => index.html,这种方法简单,而且可以避免if

7、Web Apps中的控制器

Drupal, Joomla, etc. to work, just use this:

1
try_files $uri $uri/ /index.php?q=$uri&$args;

Note – the parameter names are different based on the package you’re using. For example:

  • “q” is the parameter used by Drupal, Joomla, WordPress
  • “page” is used by CMS Made Simple

一些软件不需要 query string, 可以读取 REQUEST_URI (例如,WordPress):

1
try_files $uri $uri/ /index.php;

如果你不关心目录是否存在,你可以移除 $uri/

8、Passing Uncontrolled Requests to PHP

很多PHP网站中,配置nginx的例子中建议使用 .php (to the PHP interpretet)作为uri的结尾,这例有一个严重的安全问题对于大多数PHP程序,因为它可能允许执行任何第三方代码

The problem section usually looks like this:

1
2
3
4
location ~* \.php$ {
    fastcgi_pass backend;
    # [...]
}

Here, every request ending in .php will be passed to the FastCGI backend. The issue with this is that the default PHP configuration tries to guess which file you want to execute if the full path does not lead to an actual file on the filesystem.

For instance, if a request is made for /forum/avatar/1232.jpg/file.php which does not exist but if/forum/avatar/1232.jpg does, the PHP interpreter will process /forum/avatar/1232.jpg instead. If this contains embedded PHP code, this code will be executed accordingly.

Options for avoiding this are:

  • Set cgi.fix_pathinfo=0 in php.ini. This causes the PHP interpreter to only try the literal path given and to stop processing if the file is not found.
  • Ensure that NGINX only passes specific PHP files for execution:
1
2
3
4
location ~* (file_a|file_b|file_c)\.php$ {
    fastcgi_pass backend;
    # [...]
}
  • 在上传目录禁止执行任何PHP代码
1
2
3
4
location /uploaddir {
    location ~ \.php$ {return 403;}
    # [...]
}
  • 使用try_files指令过滤
1
2
3
4
5
location ~* \.php$ {
    try_files $uri =404;
    fastcgi_pass backend;
    # [...]
}
  • 使用嵌套位置过滤
1
2
3
4
5
location ~* \.php$ {
    location ~ \..*/.*\.php$ {return 404;}
    fastcgi_pass backend;
    # [...]
}

9、FastCGI Path in Script Filename

尽量使用 include fastcgi_params 中的变量,不管什么语言都是一样

GOOD:

1
fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;

BAD:

1
fastcgi_param  SCRIPT_FILENAME    /var/www/yoursite.com/$fastcgi_script_name;

10、Taxing Rewrites

我们应该努力让他们保持整洁。很简单,不添加冗余代码。

BAD:

1
rewrite ^/(.*)$ http://example.com/$1 permanent;

GOOD:

1
rewrite ^ http://example.com$request_uri? permanent;

BETTER:

1
return 301 http://example.com$request_uri;

通过使用内置的变量$ REQUEST_URI,我们可以有效地避免做任何捕获或匹配的。

11、Rewrite Missing http://

很简单,除非你告诉NGINX他们不是重写是相对的。一个重写绝对很简单。添加一个scheme

BAD:

1
rewrite ^ example.com permanent;

GOOD:

1
rewrite ^ http://example.com permanent;

添加 http:// 到重写规则内,简单,高效

12、Proxy Everything

BAD:

1
2
3
4
5
6
7
8
9
server {
    server_name _;
    root /var/www/site;
    location / {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass unix:/tmp/phpcgi.socket;
    }
}

Yucky. In this instance, you pass EVERYTHING to PHP. Why? Apache might do this, you don’t need to. Let me put it this way… The try_files directive exists for an amazing reason. It tries files in a specific order. This means that NGINX can first try to server the static content. If it can’t, then it moves on. This means PHP doesn’t get involved at all. MUCH faster. Especially if you’re serving a 1MB image over PHP a few thousand times versus serving it directly. Let’s take a look at how to do that.

GOOD:

1
2
3
4
5
6
7
8
9
10
11
12
server {
    server_name _;
    root /var/www/site;
    location / {
        try_files $uri $uri/ @proxy;
    }
    location @proxy {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass unix:/tmp/phpcgi.socket;
    }
}

Also GOOD:

1
2
3
4
5
6
7
8
9
10
11
12
server {
    server_name _;
    root /var/www/site;
    location / {
        try_files $uri $uri/ /index.php;
    }
    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass unix:/tmp/phpcgi.socket;
    }
}

It’s easy, right? You see if the requested URI exists and can be served by NGINX. If not, is it a directory that can be served. If not, then you pass it to your proxy. Only when NGINX can’t serve that requested URI directly does your proxy overhead get involved.

Now.. consider how much of your requests are static content, such as images, css, javascript, etc. That’s probably a lot of overhead you just saved.

12、Config Changes Not Reflected

Browser cache. Your configuration may be perfect but you’ll sit there and beat your head against a cement wall for a month. What’s wrong is your browser cache. When you download something, your browser stores it. It also stores how that file was served. If you are playing with a types{} block you’ll encounter this.

The fix:

  • In Firefox press Ctrl+Shift+Delete, check Cache, click Clear Now. In any other browser just ask your favorite search engine. Do this after every change (unless you know it’s not needed) and you’ll save yourself a lot of headaches.
  • Use curl.

13、VirtualBox

If this does not work, and you’re running NGINX on a virtual machine in VirtualBox, it may be sendfile() that is causing the trouble. Simply comment out the sendfile directive or set it to “off”. The directive is most likely found in your nginx.conf file.:

1
sendfile off;

13、Missing (disappearing) HTTP Headers

If you do not explicitly set underscores_in_headers on, NGINX will silently drop HTTP headers with underscores (which are perfectly valid according to the HTTP standard). This is done in order to prevent ambiguities when mapping headers to CGI variables as both dashes and underscores are mapped to underscores during that process.

14、Not Using Standard Document Root Locations

Some directories in any file system should never be used for hosting data from. Some of these include / androot. You should never use these as your document root.

Doing this leaves you open to a request outside of your expected area returning private data.

NEVER DO THIS!!! (yes, we have seen this)

1
2
3
4
5
6
7
8
9
10
11
server {
    root /;
    location / {
        try_files /web/$uri $uri @php;
    }
    location @php {
        [...]
    }
}

When a request is made for /foo, the request is passed to php because the file isn’t found. This can appear fine, until a request in made for /etc/passwd. Yup, you just gave us a list of all users on that server. In some cases, the NGINX server is even set up run workers as root. Yup, we now have your user list as well as password hashes and how they’ve been hashed. We now own your box.

The Filesystem Hierarchy Standard defines where data should exist. You should definitely read it. The short version is that you want your web content to exist in either /var/www//srv/usr/share/www.

15、Using the Default Document Root

NGINX packages that exist in Ubuntu, Debian, or other operating systems, as an easy-to-install package will often provide a ‘default’ configuration file as an example of configuration methods, and will often include a document root to hold a basic HTML file.

Most of these packaging systems do not check to see if files are modified or exist within the default document root, which can result in code loss when the packages are upgraded. Experienced system administrators know that there is no expectation of the data inside the default document root to remain untouched during upgrades.

You should not use the default document root for any site-critical files. There is no expectation that the default document root will be left untouched by the system and there is an extremely high possibility that your site-critical data may be lost upon updates and upgrades to the NGINX packages for your operating system.

16、Using a Hostname to Resolve Addresses

BAD:

1
2
3
4
5
6
7
8
upstream {
    server http://someserver;
}
server {
    listen myhostname:80;
    # [...]
}

You should never use a hostname in a listen directive. While this may work, it will come with a large number of issues. One such issue being that the hostname may not resolve at boot time or during a service restart. This can cause NGINX to be unable to bind to the desired TCP socket which will prevent NGINX from starting at all.

A safer practice is to know the IP address that needs to be bound to and use that address instead of the hostname. This prevents NGINX from needing to look up the address and removes dependencies on external and internal resolvers.

This same issue applies to upstream locations. While it may not always be possible to avoid using a hostname in an upstream block, it is bad practice and will require careful considerations to prevent issues.

GOOD:

1
2
3
4
5
6
7
8
upstream {
    server http://10.48.41.12;
}
server {
    listen 127.0.0.16:80;
    # [...]
}

17、Using SSLv3 with HTTPS

由于SSLv3的POODLE 漏洞,建议使用在SSL网站禁用,仅仅使用TLS协议代替

1
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; 

原文:https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/

【转】MySQL优化:explain分析sql语句执行效率

本文出自:https://www.cnblogs.com/clphp/p/5403215.html

Explain命令在解决数据库性能上是第一推荐使用命令,大部分的性能问题可以通过此命令来简单的解决,Explain可以用来查看SQL语句的执行效 果,可以帮助选择更好的索引和优化查询语句,写出更好的优化语句。

Explain语法:explain select … from … [where …]

例如:explain select * from news;

输出:

+----+-------------+-------+-------+-------------------+---------+---------+-------+------
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+-------------------+---------+---------+-------+------

下面对各个属性进行了解:

1、id:这是SELECT的查询序列号

2、select_type:select_type就是select的类型,可以有以下几种:

SIMPLE:简单SELECT(不使用UNION或子查询等)

PRIMARY:最外面的SELECT

UNION:UNION中的第二个或后面的SELECT语句

DEPENDENT UNION:UNION中的第二个或后面的SELECT语句,取决于外面的查询

UNION RESULT:UNION的结果。

SUBQUERY:子查询中的第一个SELECT

DEPENDENT SUBQUERY:子查询中的第一个SELECT,取决于外面的查询

DERIVED:导出表的SELECT(FROM子句的子查询)

3、table:显示这一行的数据是关于哪张表的

4、type:这列最重要,显示了连接使用了哪种类别,有无使用索引,是使用Explain命令分析性能瓶颈的关键项之一。

结果值从好到坏依次是:

system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL

一般来说,得保证查询至少达到range级别,最好能达到ref,否则就可能会出现性能问题。

5、possible_keys:列指出MySQL能使用哪个索引在该表中找到行

6、key:显示MySQL实际决定使用的键(索引)。如果没有选择索引,键是NULL

7、key_len:显示MySQL决定使用的键长度。如果键是NULL,则长度为NULL。使用的索引的长度。在不损失精确性的情况下,长度越短越好

8、ref:显示使用哪个列或常数与key一起从表中选择行。

9、rows:显示MySQL认为它执行查询时必须检查的行数。

10、Extra:包含MySQL解决查询的详细信息,也是关键参考项之一。

Distinct
一旦MYSQL找到了与行相联合匹配的行,就不再搜索了

Not exists
MYSQL 优化了LEFT JOIN,一旦它找到了匹配LEFT JOIN标准的行,

就不再搜索了

Range checked for each

Record(index map:#)
没有找到理想的索引,因此对于从前面表中来的每一 个行组合,MYSQL检查使用哪个索引,并用它来从表中返回行。这是使用索引的最慢的连接之一

Using filesort
看 到这个的时候,查询就需要优化了。MYSQL需要进行额外的步骤来发现如何对返回的行排序。它根据连接类型以及存储排序键值和匹配条件的全部行的行指针来 排序全部行

Using index
列数据是从仅仅使用了索引中的信息而没有读取实际的行动的表返回的,这发生在对表 的全部的请求列都是同一个索引的部分的时候

Using temporary
看到这个的时候,查询需要优化了。这 里,MYSQL需要创建一个临时表来存储结果,这通常发生在对不同的列集进行ORDER BY上,而不是GROUP BY上

Using where
使用了WHERE从句来限制哪些行将与下一张表匹配或者是返回给用户。如果不想返回表中的全部行,并且连接类型ALL或index, 这就会发生,或者是查询有问题

其他一些Tip:

  1. 当type 显示为 “index” 时,并且Extra显示为“Using Index”, 表明使用了覆盖索引。

来源:http://www.cnblogs.com/hailexuexi/archive/2011/11/20/2256020.html

微信小程序机票预定系统

经过两三个月的开发,我们的机票订购系统终于开发完毕。下周就可以上线了。

IBE终究还是Amadeus.

查询入口:

 

票价列表:

 

选择航班:

 

 

 

 

 

 

填写出行人信息:

 

确认订单:

 

微信支付:

 

 

 

CentOS 5 时代终结

今天发现服务器CentOS 5 已经无法用YUM命令安装软件了。原来已经停止更新了。

CentOS 5 – is now End of Life

Postby TrevorH » 2016/04/12 22:27:47

CentOS 5 has reached end of life upstream.

As there will be no more fixes for RHEL 5 released public upstream by Redhat then there will be no more updates for CentOS 5 either. You are encouraged to migrate any remaining systems to CentOS 7 or to CentOS 6 (which itself enters Production Phase 3 upstream in May 2017 with End of Life coming in 2020).

Expect the current CentOS 5 mirror content to migrate to vault.centos.org in the near future.

This notice was originally posted when CentOS 5 had one year of supported life left. It now has 6 1 month 1 week. You are encouraged to put your migration plans into action now if you haven’t already done so. CentOS 6 goes EOL in 2020, CentOS 7 in 2024.

Don’t delay, get migrating today

Redhat have issued a 3 month retirement notice that you can read on http://rhn.redhat.com/errata/RHSA-2016-2997.html

As per the announcement upstream, http://rhn.redhat.com/errata/RHSA-2016-0561.html you should know that CentOS 5 now has one year of support life left. People using CentOS 5 are encouraged to start their migration process to a supported version.

It should be noted that, unlike RHEL, there is no extended support option for CentOS. Once RHEL 5 goes EOL upstream on March 31st 2017, there will be no further updates for CentOS 5 at all. Those using CentOS 5 and requiring more than 1 year 3 2 1 month of life are encouraged to investigate the RH extended support program although that will require a migration to RHEL 5 as it does not apply to CentOS 5.

https://www.centos.org/forums/viewtopic.php?f=9&t=57398

在CentOS 7.2 运行Laravel 5.3项目

最近公司的代理商后台重构了。也有一台新机器配置还不错。

所以就安装了最高版本的PHP,用于跑Laravel 5.3项目。

服务器是CentOS 7.2, PHP7, Nginx 1.10, Laravel 5.3相关支持, 其它组件自行安装。

 rpm -Uvh https://mirror.webtatic.com/yum/el7/webtatic-release.rpm

 yum install php70w

yum install nginx

systemctl enable nginx

systemctl enable php-fpm


 

公司的Apps已经上线

经历了两个多个月的开发,公司的Apps已经上线Google Play和App Store.

接下来还有好多东西要做,觉得要累成狗。

 

 

 

 

 

Google Play Download Link:

https://play.google.com/store/apps/details?id=com.kaytrip.trip.kaytrip

 

 

 

 

 

 

App Store Download Link:

https://itunes.apple.com/cn/app/kai-yuan-lu-you/id808656290?l=en&mt=8