0%

你对自由的理解是什么?说「不」的能力。

用过百度统计的都知道百度使用1x1的空白图片传递统计参数,自己做异步统计的兄弟是否使用静态文件来传递参数。为什么使用空白图片呢,而不是自己存放一张小图呢,nginx里面的空白图片是保存在内存中的,速度绝对比硬盘上读取的快. 看下如何使用empty_gif生成响应1x1的空白图片吧.

或许哪天ttlsa自己要做统计,咱们也可以使用empty_gif来传递参数,说归说,肯定性还是比较小,能用第三方的统计就用第三方统计。

nginx配置

nginx的模块 ngx_http_empty_gif_module, 编译安装

1
2
3
location = /_.gif {
empty_gif;
}

自定义配置

1
2
3
4
5
6
7
8
9
10
11
12
13
server {
listen 80;
server_name test.ttlsa.com;
access_log /data/logs/nginx/test.ttlsa.com.access.log main;

index index.html index.php index.html;
root /data/site/test.ttlsa.com;

location ~* /3145/
{
empty_gif;
}
}

访问

我们在访问的时候带上所要统计的参数就可以

1
test.ttlsa.com/3145?time=hhh

http://nginx.org/en/docs/http/ngx_http_empty_gif_module.html

若家境殷实,谁愿颠沛流离。

docker-compose.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
version: '3'

services:
nginx:
hostname: nginx
image: nginx
ports:
- 8000:80
networks:
- lnmp
volumes:
- ./wwwroot:/usr/share/nginx/html
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/conf.d:/etc/nginx/conf.d/
php:
hostname: php
image: php:7.2.6-fpm
networks:
- lnmp
volumes:
- ./wwwroot:/usr/share/nginx/html
mysql:
hostname: mysql
image: mysql:5.7.22
ports:
- 3307:3306
networks:
- lnmp
volumes:
- ./mysql/conf:/etc/mysql/conf.d
- ./mysql/data:/var/lib/mysql
command: --character-set-server=utf8mb4
environment:
MYSQL_ROOT_PASSWORD: 123456
MYSQL_DATABASE: wp
MYSQL_USER: yangzie
MYSQL_PASSWORD: 123456
networks:
lnmp:
driver: bridge

nginx配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
index index.html index.htm index.php;

location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass php:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_intercept_errors off;
fastcgi_buffer_size 16k;
fastcgi_buffers 4 16k;
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
}

}

mysql

1
mysql -h47.98.174.48 -P 3307 -uroot -p123456

目录

1
2
3
4
5
6
7
8
9
10
11
12
13
├── docker-compose.yml
├── mysql
│   ├── conf
│   └── data
├── nginx
│   ├── conf.d
│   └── nginx.conf
├── php
│   └── ini
└── wwwroot
├── index.php
└── tp5

截图

注意点

  • php容器也要配置目录映射, 不然找不到php文件
  • nginx的server配置中监听9000端口:php:9000
  • 找不到的配置可以在Dockerfile文件中找

不要到处宣扬自己的内心,这世上不止你一个人有故事

使用阿里云ECS服务器, 购买的40G高效云盘已经不够用, 所以又购买了一块云盘, 但是仅仅通过控制台操作并不能将磁盘挂载到系统, 接下来记录我的挂载流程; 为了安全起见, 建议先去做一个磁盘快照

  • 检查磁盘现在的情况

    1
    df -h

    结果

    1
    2
    3
    4
    5
    6
    7
    Filesystem      Size  Used Avail Use% Mounted on
    /dev/vda1 40G 35G 3.2G 92% /
    devtmpfs 3.9G 0 3.9G 0% /dev
    tmpfs 3.9G 0 3.9G 0% /dev/shm
    tmpfs 3.9G 632K 3.9G 1% /run
    tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup
    tmpfs 783M 0 783M 0% /run/user/0
  • 查看硬盘个数及分区

    1
    fdisk -l

    结果

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    Disk /dev/vda: 42.9 GB, 42949672960 bytes, 83886080 sectors
    Units = sectors of 1 * 512 = 512 bytes
    Sector size (logical/physical): 512 bytes / 512 bytes
    I/O size (minimum/optimal): 512 bytes / 512 bytes
    Disk label type: dos
    Disk identifier: 0x0008d73a

    Device Boot Start End Blocks Id System
    /dev/vda1 * 2048 83884031 41940992 83 Linux

    Disk /dev/vdb: 21.5 GB, 21474836480 bytes, 41943040 sectors
    Units = sectors of 1 * 512 = 512 bytes
    Sector size (logical/physical): 512 bytes / 512 bytes
    I/O size (minimum/optimal): 512 bytes / 512 bytes

    我们可以看到那块20GB的磁盘:/dev/xdb

  • 对这块硬盘进行分区

  • 查看

    1
    fdisk -l

    结果

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    Disk /dev/vda: 42.9 GB, 42949672960 bytes, 83886080 sectors
    Units = sectors of 1 * 512 = 512 bytes
    Sector size (logical/physical): 512 bytes / 512 bytes
    I/O size (minimum/optimal): 512 bytes / 512 bytes
    Disk label type: dos
    Disk identifier: 0x0008d73a

    Device Boot Start End Blocks Id System
    /dev/vda1 * 2048 83884031 41940992 83 Linux

    Disk /dev/vdb: 21.5 GB, 21474836480 bytes, 41943040 sectors
    Units = sectors of 1 * 512 = 512 bytes
    Sector size (logical/physical): 512 bytes / 512 bytes
    I/O size (minimum/optimal): 512 bytes / 512 bytes
    Disk label type: dos
    Disk identifier: 0x7a2b9a92

    Device Boot Start End Blocks Id System
    /dev/vdb1 2048 41943039 20970496 83 Linux

  • 格式化新分区

    1
    mkfs.ext3 /dev/vdb1
  • 创建挂载目录
    建议挂载到mnt目录, 也可以自己创建新的目录

  • 挂载分区到目录

    1
    mount /dev/vdb1 /mnt
  • 查看

    1
    df -h

    结果

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    Filesystem      Size  Used Avail Use% Mounted on
    /dev/vda1 40G 35G 3.1G 92% /
    devtmpfs 3.9G 0 3.9G 0% /dev
    tmpfs 3.9G 0 3.9G 0% /dev/shm
    tmpfs 3.9G 636K 3.9G 1% /run
    tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup
    tmpfs 783M 0 783M 0% /run/user/0
    /dev/vdb1 20G 45M 19G 1% /mnt
    ```
    - 设置开机自动挂载
    ```php
    cat /etc/fstab
    #
    # /etc/fstab
    # Created by anaconda on Sun Oct 15 15:19:00 2017
    #
    # Accessible filesystems, by reference, are maintained under '/dev/disk'
    # See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
    #
    UUID=eb448abb-3012-4d8d-bcde-94434d586a31 / ext4 defaults 1 1

    修改

    1
    vi /etc/fstab

    结果

    1
    2
    3
    4
    5
    6
    7
    8
    9
    #
    # /etc/fstab
    # Created by anaconda on Sun Oct 15 15:19:00 2017
    #
    # Accessible filesystems, by reference, are maintained under '/dev/disk'
    # See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
    #
    UUID=eb448abb-3012-4d8d-bcde-94434d586a31 / ext4 defaults 1 1
    /dev/vdb1 /mnt ext3 defaults 0 0
  • 重启

https://help.aliyun.com/document_detail/25426.html
https://blog.csdn.net/wyzhangchengjin123/article/details/50451065

珍贵的东西往往数目稀少,所以你要变得更强,才有力量去抢。

今天遇到了一个问题, 线上的ES服务突然挂了,重启无用, 查看日志后发现是本地磁盘爆了,开启了我的磁盘清理之路

du(disk usage)命令可以计算文件或目录所占的磁盘空间。没有指定任何选项时,它会测量当前工作目录与其所有子目录,分别显示各个目录所占的快数,最后才显示工作目录所占总快数。

  • 查看

    1
    df -lh

    结果

    1
    2
    3
    4
    5
    6
    7
    /dev/vda1        40G   37G  870M  98% /
    devtmpfs 3.9G 0 3.9G 0% /dev
    tmpfs 3.9G 0 3.9G 0% /dev/shm
    tmpfs 3.9G 624K 3.9G 1% /run
    tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup
    tmpfs 783M 0 783M 0% /run/user/0

  • 查找大文件

    1
    du -sh * |grep G

    结果

    1
    2
    3
    1.1G	root
    4.0G usr
    1.6G var
  • 具体分析

    1
    du -sh *

    结果

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    240M	bin
    4.0K etc
    4.0K games
    37M include
    489M lib
    169M lib64
    54M libexec
    2.6G local
    43M sbin
    362M share
    71M src
    0 tmp
  • 以M显示文件大小

    1
    ls -l --block-size=M

    结果

    1
    2
    3
    4
    5
    total 15326M
    -rwxr-xr-x 1 root root 1M Mar 13 19:01 1.sh
    -rwxr-xr-x 1 root root 20M Mar 14 20:47 2
    -rwxr-xr-x 1 root root 20M Mar 15 17:47 btoken-go
    -rw-rw---- 1 root root 243M Jun 27 11:11 btoken.log

让未来到来,让过去过去。

Alpine 操作系统是一个面向安全的轻型 Linux 发行版。它不同于通常 Linux 发行版,Alpine 采用了 musl libc 和 busybox 以减小系统的体积和运行时资源消耗,但功能上比 busybox 又完善的多,因此得到开源社区越来越多的青睐。在保持瘦身的同时,Alpine 还提供了自己的包管理工具 apk,可以通过 https://pkgs.alpinelinux.org/packages 网站上查询包信息,也可以直接通过 apk 命令直接查询和安装各种软件。

Alpine 由非商业组织维护的,支持广泛场景的 Linux发行版,它特别为资深/重度Linux用户而优化,关注安全,性能和资源效能。Alpine 镜像可以适用于更多常用场景,并且是一个优秀的可以适用于生产的基础系统/环境。

Alpine Docker 镜像也继承了 Alpine Linux 发行版的这些优势。相比于其他 Docker 镜像,它的容量非常小,仅仅只有 5 MB 左右(对比 Ubuntu 系列镜像接近 200 MB),且拥有非常友好的包管理机制。官方镜像来自 docker-alpine 项目。

目前 Docker 官方已开始推荐使用 Alpine 替代之前的 Ubuntu 做为基础镜像环境。这样会带来多个好处。包括镜像下载速度加快,镜像安全性提高,主机之间的切换更方便,占用更少磁盘空间等。

Docker下的运行

官方 Alpine 镜像的文档:http://gliderlabs.viewdocs.io/docker-alpine/

可以使用Docker Toolbox,创建一台Docker虚拟主机,在该主机的Docker环境下运行alpine的 Docker容器。该容器就是一个Alpine Linux系统,

1
2
3
docker pull alpine

docker run -it --name myalpine alpine

作为Docker容器的基础镜像

以Alpine为基础镜像,创建一个MySQL容器,镜像大小只有36.5MB,
同样的方式使用Ubuntu系统作为基础镜像,镜像大小有184MB,
Dockerfile文件的内容:

1
2
3
FROM alpine:3.6
RUN apk add --no-cache mysql-client
ENTRYPOINT ["mysql"]

创建一个test/mysqlclient:1.0镜像

1
docker build -t test/mysqlclient:1.0 .

Alpine的配置和使用

网络相关文件

主机名文件

1
/etc/hostname    

主机IP和域名映射文件

1
/etc/hosts    

安装nginx

1
apk add --update nginx   

安装openssh-server服务器

1
apk add openssh-server

相关资源

https://blog.csdn.net/CSDN_duomaomao/article/details/76152416

你不必跑在任何人后边。

Nginx反向代理负载均衡架构图(三台服务器为例)

Nginx负载均衡(图示:192.168.1.1:80服务器配置)

upstream示例配置

1
2
3
4
5
upstream icontact_pool {  
server 192.168.1.1:9000 weight=5 max_fails=3 fail_timeout=20s;
server 192.168.1.2:9000 weight=3 max_fails=3 fail_timeout=20s;
server 192.168.1.3:9000 weight=2 max_fails=3 fail_timeout=20s;
}

ngxin虚拟主机负载均衡配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
server {  
listen 192.168.1.1:80;
server_name 192.168.1.1;

access_log /var/log/nginx/balance/loadbalance.access.log;
error_log /var/log/nginx/balance/loadbalance.error.log;

#允许列目录
location / {
root /balance/;
autoindex on;
autoindex_exact_size off;
autoindex_localtime on;
allow allow;
}

#proxy the php scripts to fpm_pool_upstream
location ~ \.php$ {
root /balance;
include /etc/nginx/fastcgi_params;
#将webserver接收的客户端请求通过fastcgi负载均衡到php5-fpm的池
fastcgi_pass icontact_pool;
}
}

负载均衡服务器处理php请求

192.168.1.1:9000、192.168.1.2:9000、192.168.1.3:9000为后端的三台负载均衡服务器监听的fpm地址和端口号,负载均衡服务器通过fastcgi将http请求和上下文参数发送给这个fpm池,然后fpm负责解析php程序

https://blog.csdn.net/wzy_1988/article/details/8230562

生活总是有很多出人意料的事情,比如,你以为我要举个例子。

php-fpm

  • IP : 47.104.245.210
  • 部署了php-fpm,并成功开启9000端口的访问权限
  • 部署了相关业务代码(/app/www/pandora_php_v1)

nginx

  • IP : 47.104.89.216
  • 部署了nginx
  • 配置文件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    server {
    listen 80;
    #listen 443 ssl http2;
    server_name api2019.dazhi.com;
    root "/app/www/pandora_php_v1/public"; # 这里的目录是php-fpm服务器的代码目录

    index index.html index.htm index.php;

    charset utf-8;

    location / {
    try_files $uri $uri/ /index.php?$query_string;
    }



    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt { access_log off; log_not_found off; }

    access_log off;
    error_log /var/log/nginx/api2019.dazhifund.com.log error;

    sendfile off;

    client_max_body_size 100m;

    location ~ \.php$ {
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_pass 47.104.245.210:9000; # php-fpm环境的地址
    fastcgi_index index.php;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;


    fastcgi_intercept_errors off;
    fastcgi_buffer_size 16k;
    fastcgi_buffers 4 16k;
    fastcgi_connect_timeout 300;
    fastcgi_send_timeout 300;
    fastcgi_read_timeout 300;
    }

    location ~ /\.ht {
    deny all;
    }
    }

  • 检查端口是否可以访问: telnet 47.104.245.210 9000
  • 重启nginx, nginx -s reload

You are my today and all of my tomorrows.

In my article SQL vs NoSQL: The Differences, I mentioned the line between SQL and NoSQL databases has become increasingly blurred with each camp adopting features from the other. MySQL 5.7 InnoDB and PostgreSQL 9.4 databases both directly support JSON document types in a single field. In this article, we’ll examine MySQL’s JSON implementation in more detail.

(PostgreSQL supported JSON before version 9.4 and any database will accept JSON documents as a single string blob. However, MySQL and PostgreSQL now directly support validated JSON data in real key/value pairs rather than a basic string.)

Just Because You Can Store JSON …

… it doesn’t follow you should.

Normalization is a technique used to optimize the database structure. The First Normal Form (1NF) rule governs that every column should hold a single value — which is broken by storing multi-value JSON documents.

If you have clear relational data requirements, use appropriate single-value fields. JSON should be used sparingly as a last resort. JSON value fields cannot be indexed, so avoid using it on columns which are updated or searched regularly. In addition, fewer client applications support JSON, and the technology is newer and possibly less stable than other types.

That said, there are good JSON use-cases for sparsely-populated data or custom attributes.

Create a Table with a JSON Field

Consider a shop selling books. A book table will have an ID, ISBN, title, publisher, number of pages and other relational data which applies to all books. Presume we want to add any number of category tags to any book. We could achieve this in SQL using:

  • a tag table which stored each tag name against a unique ID, and
  • a tagmap table with many-to-many records mapping book IDs to tag IDs

It’ll work, but it’s cumbersome and considerable effort for a minor feature. Therefore, we’ll define a tags JSON field in our MySQL database’s book table:

1
2
3
4
5
6
CREATE TABLE `book` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`title` varchar(200) NOT NULL,
`tags` json DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;

Note that JSON columns cannot have a default value, be used as a primary key, be referenced as a foreign key or have an index. You can create secondary indexes on generated virtual columns, but it’s possibly easier to retain an indexed value in a separate field.

Adding JSON Data

Whole JSON documents can be passed in INSERT or UPDATE statements. For example, our book tags can be passed as an array:

1
2
3
4
5
INSERT INTO `book` (`title`, `tags`)
VALUES (
'ECMAScript 2015: A SitePoint Anthology',
'["JavaScript", "ES2015", "JSON"]'
);

JSON can also be created with the:

  • JSON_ARRAY() function which creates arrays, e.g.

    1
    2
    -- returns [1, 2, "abc"]:
    SELECT JSON_ARRAY(1, 2, 'abc');
  • JSON_OBJECT() function which creates objects, e.g.

    1
    2
    -- returns {"a": 1, "b": 2}:
    SELECT JSON_OBJECT('a', 1, 'b', 2);
  • JSON_MERGE() function to merge documents, e.g.

    1
    2
    -- returns ["a", 1, {"key": "value"}]:
    SELECT JSON_MERGE('["a", 1]', '{"key": "value"}');
  • or you can (CAST anyValue AS JSON).

The JSON_TYPE() function allows you to check JSON value types. It should return OBJECT, ARRAY or an error, e.g.

1
2
3
4
5
6
7
8
-- returns ARRAY:
SELECT JSON_TYPE('[1, 2, "abc"]');

-- returns OBJECT:
SELECT JSON_TYPE('{"a": 1, "b": 2}');

-- returns an error:
SELECT JSON_TYPE('{"a": 1, "b": 2');

Similarly, the JSON_VALID() function returns 1 when the JSON is valid:

1
2
3
4
5
6
7
8
-- returns 1:
SELECT JSON_TYPE('[1, 2, "abc"]');

-- returns 1:
SELECT JSON_TYPE('{"a": 1, "b": 2}');

-- returns 0:
SELECT JSON_TYPE('{"a": 1, "b": 2');

Attempting to insert an invalid JSON document will raise an error, and the whole record will not be inserted/updated.

Searching JSON Data

The JSON_CONTAINS() function accepts the JSON document being searched and another to compare against. It returns 1 when a match is found, e.g.

1
2
3
-- all books with the 'JavaScript' tag:
SELECT * FROM `book`
WHERE JSON_CONTAINS(tags, '["JavaScript"]');

The similar JSON_SEARCH() function returns the path to the given match or NULL when there’s no match. It is passed the JSON document being searched, ‘one’ to find the first match or ‘all’ to find all matches, and a search string, e.g.

1
2
3
-- all books with tags starting 'Java':
SELECT * FROM `book`
WHERE JSON_SEARCH(tags, 'one', 'Java%') IS NOT NULL;

JSON Paths

A JSON path targets values and can be used to extract or modify parts of a document. The JSON_EXTRACT() function demonstrates this by extracting one or more values:

1
2
3
4
5
-- returns "SitePoint":
SELECT JSON_EXTRACT(
'{"id": 1, "website": "SitePoint"}',
'$.website'
);

https://www.sitepoint.com/use-json-data-fields-mysql-databases/

老吾老,以及人之老;幼吾幼,以及人之幼。

nginx中的 location 正则模块

首先看下location 正则匹配的使用。

还记得之前是如何用location来定位.php文件的吗?

1
2
3
4
5
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi.conf;
}

我们用~来表示location开启正则匹配, 这样:location ~。

还可以用这个来匹配静态资源,缓存它们,设置过期时间:

1
2
3
4
5
6
location ~ .*\.(gif|jpg|jpeg|bmp|png|ico|txt|mp3|mp4|swf){
expires 15d;
}
location ~ .*\.(css|js){
expires 12h;
}

expires 用来设置HTTP应答中的Expires和Cache-Control的头标时间,来告诉浏览器访问这个静态文件时,不用再去请求服务器,直接从本地缓存读取就可以了。

1
2
3
语法: expires [time|epoch|max|off]
默认值: expires off
作用域: http, server, location

可以在time值中使用正数或负数。“Expires”头标的值将通过当前系统时间加上您设定的 time 值来获得。

可以设置的参数如下:

  • epoch 指定“Expires”的值为 1 January, 1970, 00:00:01 GMT。
  • max 指定“Expires”的值为 31 December 2037 23:59:59 GMT,“Cache-Control”的值为10年。
  • -1 指定“Expires”的值为 服务器当前时间 -1s,即永远过期
  • 负数:Cache-Control: no-cache
  • 正数或零:Cache-Control: max-age = #, # 会转换为指定时间的秒数。比如:1d、2h、3m。
  • off 表示不修改“Expires”和“Cache-Control”的值

比如再看个例子:

控制图片等过期时间为30天

1
2
3
location~ \.(gif|jpg|jpeg|png|bmp|ico)$ {
expires 30d;
}

我们还可以控制哪一个文件目录的时间,比如控制匹配/resource/或者/mediatorModule/里所有的文件缓存设置到最长时间。

1
2
3
4
location ~ /(resource|mediatorModule)/ {
root /opt/demo;
expires max;
}

URL重写模块(Rewrite)

重写模块与很多模块一起使用。先看一下是怎么用的,看2个例子,然后我们再一点一点讲每个的使用方法:

1
2
3
4
5
6
7
8
location /download/ {
if ($forbidden) {
return 403;
}
if ($slow) {
limit_rate 10k;
}
rewrite ^/(download/.*)/media/(.*)\..*$ /$1/mp3/$2.mp3 break;
1
2
3
4
5
location / {
root html;
index index.html index.htm;
rewrite ^/bbs/(.*)$ http://192.168.18.201/forum/$1;
}

break

break 和变成语言中的用法一样,就是跳出某个逻辑。

语法:break
默认值:none
使用字段:server, location, if

1
2
3
if (!-f $request_filename) {
break;
}

上面这个例子就是在if里面使用break,意思是如果访问的文件名不存在,就跳出。

if

语法:if (condition) { … }
默认值:none
使用字段:server, location

if 判断一个条件,如果条件成立,则后面的大括号内的语句将执行,相关配置从上级继承。

可以在判断语句中指定下列值:

  • 一个变量的名称;不成立的值为:空字符传”“或者一些用“0”开始的字符串。
  • 一个使用=或者!=运算符的比较语句。
  • 使用符号*和模式匹配的正则表达式:
  • ~为区分大小写的匹配。
  • ~*不区分大小写的匹配(firefox匹配FireFox)。
  • !和!*意为“不匹配的”。
  • 使用-f和!-f检查一个文件是否存在。
  • 使用-d和!-d检查一个目录是否存在。
  • 使用-e和!-e检查一个文件,目录或者软链接是否存在。
  • 使用-x和!-x检查一个文件是否为可执行文件。

我们一一来举例看看。

1
2
3
if ($http_user_agent ~ MSIE) {
rewrite ^(.*)$ /msie/$1 break;
}

$http_user_agent变量获取浏览器的agent,使用~ 来匹配大小写
用户如果使用的IE 浏览器,就执行if 里面的操作。

1
2
3
if ($request_method = POST ) {
return 405;
}

$request_method变量获取请求的方法,使用=来判断是否等于POST 。如果复合,就执行if 里面的操作。

```php
if (!-f $request_filename) {
break;
proxy_pass http://127.0.0.1;
}
``
$request_filename变量获取请求的文件名,使用!-f来匹配文件,如果不是一个文件名,就执行if 里面的逻辑。

https://www.zybuluo.com/phper/note/133244

山不厌高,海不厌深;周公吐哺,天下归心

基于域名的虚拟主机

假设我们在本地开发有3个项目,分别在hosts里映射到本地的127.0.0.1上:

1
2
3
127.0.0.1 www.iyangyi.com iyangyi.com
127.0.0.1 api.iyangyi.com
127.0.0.1 admin.iyangyi.com

有这样3个项目,分别对应于web根目录下的3个文件夹,我们用域名对应文件夹名字,这样子好记:

1
2
3
/Users/yangyi/www/www.iyangyi.com/
/Users/yangyi/www/api.iyangyi.com/
/Users/yangyi/www/admin.iyangyi.com/

每个目录下都有一个index.php文件,都素简单的输入自己的域名。

下面我们就来搭建这3个域名的虚拟主机,很显然,我们要新建3个server来完成。为了看起来简洁好看,我们使用require来包含外面的3个server在nginx.conf中,这样就清晰了很多。不会使得这个nginx.conf内容太多:

1
2
3
4
5
6
7
8
9
10
11
12
main
events {
....
}
http {
....
include vhost/www.iyangyi.conf;
include vhost/api.iyangyi.conf;
include vhost/admin.iyangyi.conf;
#或者用 *.conf 包含
# include vhost/*.conf
}

既然每一个conf都是一个server,前面已经学习了一个完整的server写的了。下面就开始:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# www.iyangyi.conf
server {
listen 80;
server_name www.iyangyi.com iyangyi.com;
root /Users/yangyi/www/www.iyangyi.com/;
index index.php index.html index.htm;
access_log /usr/local/var/log/nginx/www.iyangyi.access.log main;
error_log /usr/local/var/log/nginx/www.iyangyi.error.log error;
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi.conf;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# api.iyangyi.conf
server {
listen 80;
server_name api.iyangyi.com;
root /Users/yangyi/www/api.iyangyi.com/;
index index.php index.html index.htm;
access_log /usr/local/var/log/nginx/api.iyangyi.access.log main;
error_log /usr/local/var/log/nginx/api.iyangyi.error.log error;
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi.conf;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# admin.iyangyi.conf
server {
listen 80;
server_name admin.iyangyi.com;
root /Users/yangyi/www/admin.iyangyi.com/;
index index.php index.html index.htm;
access_log /usr/local/var/log/nginx/admin.iyangyi.access.log main;
error_log /usr/local/var/log/nginx/admin.iyangyi.error.log error;
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi.conf;
}
}

这样3个很精简的虚拟域名就搭建好了。重启下nginx,然后打开浏览器访问一下这3个域名,就能看到对应的域名内容了。

反向代理

正向代理

在说啥啥反向代理之前,先说下什么是代理或者正向代理。

正向代理也就是代理,他的工作原理就像一个跳板,简单的说,我访问不了google.com,但是我能访问一个代理服务器A,A能访问google.com,于是我先连上代理服务器A,告诉他我需要google.com的内容,A就去取回来,然后返回给我。从网站的角度,只在代理服务器来取内容的时候有一次记录,有时候并不知道是用户的请求,也隐藏了用户的资料,这取决于代理告不告诉网站。

结论就是,正向代理是一个位于客户端和原始服务器(origin server)之间的服务器。为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。

目前代理软件很多,浏览器上的代理就更多了。什么自由门啊,红杏等。

反向代理

ok,说完正向代理,再来说啥是反向代理!

举个例子,比如我想访问 http://www.test.com/readme,但www.test.com上并不存在readme页面,于是他是偷偷从另外一台服务器上取回来,然后作为自己的内容返回用户,但用户并不知情。这里所提到的 www.test.com 这个域名对应的服务器就设置了反向代理功能。

结论就是,反向代理正好相反,对于客户端而言它就像是原始服务器,并且客户端不需要进行任何特别的设置。客户端向反向代理的命名空间(name-space)中的内容发送普通请求,接着反向代理将判断向何处(原始服务器)转交请求,并将获得的内容返回给客户端,就像这些内容原本就是它自己的一样。

嗯。正向代理和反向代理就基本清楚了,那我们就来用nginx来配置一个反向代理。

nginx 使用反向代理,主要是使用location模块下的proxy_pass选项。

我们直接实战吧!

来个最简单的。当我访问 mac 上的nginx 的 centos.iyangyi.com 的内容时候, 就反向代理到虚拟机centos上的 apache 192.168.33.10 的index.html页面。

192.168.33.10 中的html 是很简单的一句输出:

1
centos apache2 index.html

在hosts里新加上这个域名。

1
2
#vi /etc/hosts 
127.0.0.1 centos.iyangyi.com

在vhost目录中新建一个conf server

1
2
3
4
5
6
7
8
9
10
#centos.iyangyi.conf
server {
listen 80;
server_name centos.iyangyi.com;
access_log /usr/local/var/log/nginx/centos.iyangyi.access.log main;
error_log /usr/local/var/log/nginx/centos.iyangyi.error.log error;
location / {
proxy_pass http://192.168.33.10;
}
}

重启下nginx:

1
sudo nginx -s reload

打开浏览器,就可以看到页面输出了:

1
centos apache2 index.html

负载均衡

先简单说下负载均衡是干嘛的?举个例子:我们的小网站,刚开始就一台nginx服务器,后来,随着业务量增大,用户增多,一台服务器已经不够用了,我们就又多加了几台服务器。那么这几台服务器如何调度?如何均匀的提供访问?这就是负载均衡。

负载均衡的好处是可以集群多台机器一起工作,并且对外的IP 和 域名是一样的,外界看起来就好像一台机器一样。

nginx 也刚好提供了强大而又简单的负载均衡功能。

在第一节中,我详细讲了nginx的负载均衡模块upstream,负载均衡呢,主要是用这个模块。

基于 weight 权重的负载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
upstream webservers{
server 192.168.33.11 weight=10;
server 192.168.33.12 weight=10;
server 192.168.33.13 weight=10;
}
server {
listen 80;
server_name upstream.iyangyi.com;
access_log /usr/local/var/log/nginx/upstream.iyangyi.access.log main;
error_log /usr/local/var/log/nginx/upstream.iyangyi.error.log error;
location / {
proxy_pass http://webservers;
proxy_set_header X-Real-IP $remote_addr;
}
}

重启nginx nginx -s reload,打开浏览器输入upstream.iyangyi.com,不断刷新下,就能看到变化显示web1,web2,web3。说明我们的负载均衡起作用了。