wordpress 固定链接设置后 出现404错误,不能访问文章的解决办法

如果你的Apache、PHP、Mysql系统架构是自己配置的,或使用的某些安装包,可能会有这个问题,本人曾经遇到过,用第五条解决,如下:

AllowOverride Not Enabled 

服务器可能没打开AllowOverride。如果httpd.config的AllowOverride设置的是None,那.htaccess将被忽略。正确的设置:

<Directory />
Options FollowSymLinks
AllowOverride All
</Directory>

也需要在DocumentRoot打开AllowOverride:

<Directory /var/www/html>
# ... other directives...
AllowOverride All
</Directory>

固定链接的其它知识:

1. 首先介绍下,固定链接。

固定链接是你个人博客里的文章、分类以及其他页面的固定链接地址。如果博客的固定链接变化,会造成其他人通过之前的链接地址来浏览博客时出错,所以每篇博客的链接地址都应该固定,而且永久不改———这也是固定链接名字的由来。

固定链接的类型:目前共有三种基本的类型:

(1)默认:http://example.com/?p=N N是文章ID

(2)mod_rewrite: “漂亮的链接”
使用mod_rewrite或lighttpd可以生成更好看的链接地址(查看 漂亮的链接),有各种个样的链接格式,最常见、最通用的格式如下
http://example.com/category/post-name/
http://example.com/year/month/day/post-name

(3)PATHINFO: “比较好的链接”
PATHINFO类型的链接地址和mod_rewrite类型的地址看起来很像,唯一的区别是在前面多了/index.php,如下: http://example.com/index.php/yyyy/mm/dd/post-name/除此之外,和mod_rewrite类型的地址一样,也具有同样的可配置性。任何mod_rewrite链接地址可以做的事情,PATHINFO也可以。

2. 选择你的固定链接结构

在设置 → 固定链接,可以选择默认格式,也可以使用结构标签在自定义结构的输入框里输入你想要的格式。如果想激活PATHINFO类型的链接地址,只要将地址以index.php/开头。

确保以%post_id%或%postname%结尾(如/%year%/%monthnum%/%day%/%postname%/),以便每个地址对应唯一的一篇博客。

出于性能上的考量,不推荐以博客类型、博客标签、博客作者、博客标题作为固定链接地址的开头这些都是纯文本的属性(field),使用它们作为链接的开头,WordPress需要更多的时间区分文章(Post)地址和页面(Page)地址,而且为了区分还要在数据库里存储额外的信息,带来不必要的开销。推荐使用数字的属性(field)作为链接的开头,如年份或文章ID。

%year% 

文章发表的年份,四位数,如 2004

%monthnum% 

月份,如 05

%day% 

天,如 28

%hour% 

小时,如 15

%minute% 

分钟,如 43

%second% 

秒,如 33

%postname% 

文章标题的别名 (编辑文章/页面时的别名栏)。对于文章标题为 “This Is A Great Post!” 的%postname%是this-is-a-great-post(查看 仅仅使用 %postname%)。 出于性能原因,强烈不建议使用%postname%作为链接地址的开头。 *** 注 – 从WordPress 2.0开始这条建议可以无视了。

%post_id% 

文章的唯一ID,如 423

%category% 

分类的别名 (新建/编辑分类时的别名栏)。 有层级关系的类型在链接地址里就像有层级的目录。 出于性能原因,强烈不建议使用%category%作为链接地址的开头。

%tag% 

标签的别名(新建/编辑标签时的别名栏)。 出于性能原因,强烈不建议使用%tag%作为链接地址的开头。

%author% 

作者的别名。

3. 自定义固定链接的问题。

当创建或更新“漂亮”固定链接结构时,WordPress会生成新的重写规则并插入到.htaccess文件中。如果出错,WordPress会提示You should update your .htaccess now并且告诉你哪些重写规则需要拷贝和粘贴到.htaccess文件(粘贴到文件的末尾)。

WordPress不会删除.htaccess中任何已存在的重写规则或目录。如果有其他重写规则,把它们放到WordPress的重写规则的前面。

(1)我的.htaccess在哪里?

WordPress的index.php和.htaccess都在博客地址目录下,博客地址在设置,常规选项里可以查到。由于有个”.”在文件名中,FTP客户端可能看不到,除非你修改FTP客户端的设置,使其显示所有文件,包括隐藏文件。如果你是通过Godaddy Hosting Connection installation来安装WordPress的话,有些主机提供商(如Godaddy)不显示或不允许你修改.htaccess文件。

(2)创建和编辑(.htaccess)

如果还没有.htaccess文件,创建一个。如果能通过shell或ssh连上服务器,直接输入touch .htaccess就创建了。如果使用FTP上传文件,可以在本地创建文件,如1.htaccess,上传到WordPress的跟目录,然后重命名为.htaccess。

可以通过FTP,shell或主机提供商可能提供的控制面板来编辑.htaccess。

如果.htaccess有错而导致(“Internal Server Error (500)”),可以使用FTP或控制面板删除出错的.htaccess。

(3)自动更新 .htaccess

如果WordPress不能自动更新.htaccess,它会告诉你原因,如.htaccess文件可写,才会自动更新,但是目前不是可写的…,这个提示在设置→固定链接面板的底部。

想让WordPress自动更新,必须给WordPress开通.htaccess文件的写权限. 确切的权限依赖于你的服务器环境,尝试给文件拥有者打开写权限,然后作者所在组打开写权限,然后所有人,一步一步测试,一旦WordPress有了写权限,则不要再进一步放宽权限。

(4)不使用mod_rewrite的固定链接

漂亮的固定链接通常需要mod_rewrite,但是IIS(Windows servers)不支持mod_rewrite。(如果在Windows上使用Apache 2.0.54,mod_rewrite可以正常工作,需要在apacheconfhttpd.conf打开这个模块。)

如果使用IIS 7且有服务器的管理权限,可以使用Microsoft的URL Rewrite模块。虽然和mod_rewrite不是完全兼容,但是支持WordPress的“漂亮”链接。安装后打开WordPress文件夹下的web.config,添加下面的规则到 system.webServer节点。

4. 固定链接遇到的问题和解决

.htaccess一般性问题
对于WordPress没有生成.htaccess文件或不将新的重写规则写到已存在的.htaccess文件,原因各种各样,按照下面的步骤,一步一步,注意,当且仅当上一步无效后再继续下一步。

(1)修改权限: 使用chmod将 .htaccess的权限改为666,以便使用template editor编辑,但是不推荐这样做,因为这样的话其他有编辑模板权限的用户也能编辑.htaccess,可以将权限改为660。

(2)服务器阻止修改: 服务器有可能阻止了SERVER_SOFTWARE变量的设置,导致生成.htaccess失败。如果确定使用的是Apache,修改wp-includes/vars.php,跟着下面的步骤走。
详看:http://codex.wordpress.org/zh-cn:%E4%BD%BF%E7%94%A8%E5%9B%BA%E5%AE%9A%E9%93%BE%E6%8E%A5

5. 修复其他问题

如果正确生成.htaccess但固定链接还是有问题,到WordPress论坛How To版发帖子求助。

AllowOverride Not Enabled
服务器可能没打开AllowOverride。

如果httpd.config的AllowOverride设置的是None,那.htaccess将被忽略。正确的设置:

<Directory />
Options FollowSymLinks
AllowOverride All
</Directory>

也需要在DocumentRoot打开AllowOverride:

<Directory /var/www/html>
# ... other directives...
AllowOverride All
</Directory>

对于使用Mac OS X服务器的,还要修改/etc/httpd/sites/中的AllowOverride。

如果不想设为all,参考Apache Core Features.
翻页有问题
有时候翻到第二页或其他页不能正常工作,地址如下:

http://www.example.com/page/2/
http://www.example.name/category/categoryname/page/2/
http://www.example/year/month/day/page/2/
http://www.example/year/month/page/2/

访问上面的任何一个链接,出现提示说: “Sorry, no posts match that criteria.”
这是.htaccess造成的,删掉,重新生成就好了。

如果还不行,到这里看看this support post.

6. 小贴士和小技巧

如果想在Google News上展示你的网站,你的链接地址至少以3个数字结尾,通过%postname%-%post_id%很容易做到,最后生成的URL如http://mysite.com/cooking-tips-tricks-344。

地址以.html结尾
使用结构标签很容易做到这一点,如
需要注意的是,这并不会生成静态的html文件,仅仅是用.html作为后缀,页面还是动态生成的。这是否会给SEO带来好处还无定论,但是当你想从WordPress搬家时,将带来很多便利,因为所有页面可以很容易地变成静态的,而且地址不用改变。

避免固定链接地址被解析成归档链接
也许有的人一天顶多发一篇博客,于是使用%year%%monthnum%%day%这样的固定链接,这样的链接会解析成这一天所有的文章,为了避免这个问题,最好使用%year%%monthnum%%day%%hour%。
检查固定链接结构
检查博客是否有固定链接结构,使用如下代码:

if ( get_option('permalink_structure') != '' ) { echo 'permalinks enabled' }

Linux下安装Apache httpd

httpd是Apache超文本传输协议(HTTP)服务器的主程序。它被设计为一个独立运行的后台进程,它会建立一个处理请求的子进程或线程的池对外提供服务。httpd支持基于 虚拟主机,以及基于HOST、IP、PORT实现虚拟主机,反向代理,负载均衡,路径别名,用户认证,basic,支持第三方模块等众多特性。本文主要描述了Linux下httpd的安装以及相关基本用法。

一、httpd的安装

演示环境及版本

# cat /etc/issue
CentOS release 6.5 (Final)
Kernel r on an m

# uname -r
2.6.32-431.el6.x86_64

查看httpd是否已安装

# rpm -qa httpd

使用yum列出相关httpd安装文件,此处为本地yum源

# yum list |grep httpd     
httpd.x86_64                 2.2.15-29.el6.centos        local_server 
httpd-devel.i686             2.2.15-29.el6.centos        local_server 
httpd-devel.x86_64           2.2.15-29.el6.centos        local_server 
httpd-manual.noarch          2.2.15-29.el6.centos        local_server 
httpd-tools.x86_64           2.2.15-29.el6.centos        local_server 

安装及验证httpd

# yum -y install httpd
# rpm -qa |grep httpd
httpd-tools-2.2.15-29.el6.centos.x86_64
httpd-2.2.15-29.el6.centos.x86_64

使用rpm方式寻找配置文件

# rpm -qc httpd  

常用的配置文件:

/etc/httpd/conf.d/*.conf        ###辅助配置文件
/etc/httpd/conf/httpd.conf      ###主配置文件
/etc/sysconfig/httpd            ###httpd工作模式配置文件

使用rpm方式查看安装位置及生成的二进制文件

# rpm -ql httpd  

主程序:

/usr/sbin/httpd  MPM模式默认
/usr/sbin/httpd.event
/usr/sbin/httpd.worker

使用rpm方式查看包的帮助文件

# rpm -qd httpd   

启动脚本:/etc/rc.d/init.d/httpd

日志文件目录:

/var/log/httpd
    access_log:访问日志
    error_log: 错误日志

站点文档目录:(站点根目录)

/var/www/html

httpd的工作目录:/var/www

二、httpd的工作模式

1、MPM: Multipath Processing Module(多路处理模块)

prefork: 多进程模型,每个进程响应一个请求;稳定性好,但并发能力有限;预先生成多个空闲进程;

由于prefork使用select()系统调用,所以最大并发不能超过1024;

worker:多进程模型,每个进程可生成多个线程,每个线程响应一个请求;预先生成多个空闲线程;

event:一个进程直接响应n个请求;可同时启动多个进程;

httpd-2.2: 测试使用; ### Author : Leshami
httpd-2.4: 可生产使用; ### Blog : http://blog.csdn.net/leshami

2、几种工作方式的切换

prefork模式下

    # service httpd start
    Starting httpd:                                            [  OK  ]
    # ps -ef|grep httpd |grep -v grep ###一个主进程,生成了8个空闲进程
    root       6413      1  0 09:40 ?        00:00:00 /usr/sbin/httpd
    apache     6416   6413  0 09:40 ?        00:00:00 /usr/sbin/httpd
    apache     6417   6413  0 09:40 ?        00:00:00 /usr/sbin/httpd
    apache     6418   6413  0 09:40 ?        00:00:00 /usr/sbin/httpd
    apache     6419   6413  0 09:40 ?        00:00:00 /usr/sbin/httpd
    apache     6420   6413  0 09:40 ?        00:00:00 /usr/sbin/httpd
    apache     6421   6413  0 09:40 ?        00:00:00 /usr/sbin/httpd
    apache     6422   6413  0 09:40 ?        00:00:00 /usr/sbin/httpd
    apache     6423   6413  0 09:40 ?        00:00:00 /usr/sbin/httpd   

    # ss -tulpn |grep httpd
    tcp    LISTEN     0   128  :::80   :::*      users:(("httpd",6413,4),("httpd",6416,4),("httpd",6417,4),("httpd",6418,4),
    ("httpd",6419,4),("httpd",6420,4),("httpd",6421,4),("httpd",6422,4),("httpd",6423,4)

    # netstat -nltp|grep 80
    tcp        0      0 :::80                       :::*          LISTEN      6413/httpd   

worker工作方式

    # cat /etc/sysconfig/httpd|grep -v ^#
    HTTPD=/usr/sbin/httpd.worker

    # service httpd restart
    Stopping httpd:                                            [  OK  ]
    Starting httpd:                                            [  OK  ]
    [root@orasrv1 ~]# ps -ef|grep httpd|grep -v grep
    root       2261      1  0 17:47 ?        00:00:00 /usr/sbin/httpd.worker
    apache     2264   2261  0 17:47 ?        00:00:00 /usr/sbin/httpd.worker
    apache     2265   2261  0 17:47 ?        00:00:00 /usr/sbin/httpd.worker
    apache     2266   2261  0 17:47 ?        00:00:00 /usr/sbin/httpd.worker

event工作方式

注,尽管2.2版本可以设置工作方式为httpd.event,生产环境不建议使用

    # cat /etc/sysconfig/httpd|grep -v ^#
    HTTPD=/usr/sbin/httpd.event
    [root@orasrv1 ~]# service httpd restart
    Stopping httpd:                                            [  OK  ]
    Starting httpd:                                            [  OK  ]
    [root@orasrv1 ~]# ps -ef|grep httpd|grep -v grep
    root       2402      1  0 17:49 ?        00:00:00 /usr/sbin/httpd.event
    apache     2405   2402  0 17:49 ?        00:00:00 /usr/sbin/httpd.event
    apache     2406   2402  0 17:49 ?        00:00:00 /usr/sbin/httpd.event
    apache     2407   2402  0 17:49 ?        00:00:00 /usr/sbin/httpd.event

三、httpd模块化特性

高度模块化

core + modules, 
DSO: Dynamic Shared Object

模块目录:

/etc/httpd/modules: 符号链接文件
/usr/lib64/httpd/modules

模块的查看

    httpd -M          ###查看当前httpd进程的所有模块
    httpd.event -M    ###查看event工作模式下的所有模块 更正@20160712
    httpd.worker -M   ###worker工作模式下的所有模块  更正@20160712
    httpd.worker -l   ###worker工作模式下的核心模块  更正@20160712

模块的查看示例

    # httpd -M
    Loaded Modules:
     core_module (static)
     mpm_prefork_module (static)
     http_module (static)
     so_module (static)
     auth_basic_module (shared)
      ..............

    # httpd.event -l
    Compiled in modules:
      core.c
      event.c
      http_core.c
      mod_so.c

模块的动态装载与卸载

    # cp /etc/httpd/conf/httpd.conf /etc/httpd/conf/httpd.conf.bak
    # cat /etc/httpd/conf/httpd.conf |grep authn_alias_module
    LoadModule authn_alias_module modules/mod_authn_alias.so
    # vi /etc/httpd/conf/httpd.conf  ###注释mod_authn_alias.so模块
    # cat /etc/httpd/conf/httpd.conf |grep authn_alias_module
      #LoadModule authn_alias_module modules/mod_authn_alias.so
    # service httpd restart
    # httpd -M   ###使用该方式前后进行对比即可知道模块是否装载或卸载    

四、验证httpd服务

# echo "<h1>orasrv1.xlk.com</h1>" >/var/www/html/index.html
# curl http://192.168.21.10
<h1>orasrv1.xlk.com</h1>

Apache 安全配置要求及操作指南

范围

适用于中国电信使用的Apache服务器。本规范提出了Apache服务器安全配置要求,

适用于所有的安全等级,可作为编制设备入网测试、安全验收、安全检查规范等文档的参考。

由于版本不同,配置操作有所不同,本规范以 unix 平台上 Apache2.02.2 为例,

给出参考配置操作。

缩略语

未分类

安全配置要求

账号

未分类

授权

编号:1

未分类

编号:2

未分类

日志

未分类

禁止访问外部文件

未分类

目录列出

未分类

错误页面重定向

未分类

拒绝服务防范

未分类

隐藏Apache的版本号

未分类

关闭TRACE

未分类

禁用CGI

未分类

监听地址绑定

未分类

未分类

补丁

未分类

更改默认端口

未分类

删除缺省安装的无用文件

未分类

HTTP加密协议

未分类

连接数设置

未分类

禁用非法HTTP方法

未分类

Apache httpd 目录列表禁用配置(options indexes)

Apache httpd服务器在缺省的情况下,开启了基于目录列表的访问,这是一个存在安全隐患的问题,因此可以关闭这个功能。在Apache 2.4的版本中,不在支持使用-indexes来配置,需要注释该功能。本文对此给出演示,供大家参考。

一、缺省情况目录列表可查看示例

当前环境

[root@centos7-web ~]# more /etc/redhat-release 
CentOS Linux release 7.2.1511 (Core) 

[root@centos7-web ~]# apachectl -v
Server version: Apache/2.4.6 (CentOS)
Server built:  Nov 19 2015 21:43:13

为站点添加index.html页面

# echo "This is a apache test index page" > /var/www/html/index.html
[root@centos7-web ~]# curl http://localhost
This is a apache test index page

移除index.html

[root@centos7-web ~]# mv /var/www/html/index.html /var/www/html/index.tmp

依旧可以访问,不过此时为apache的缺省欢迎页面

未分类

移除apache欢迎页面

[root@centos7-web ~]# mv /etc/httpd/conf.d/welcome.conf /etc/httpd/conf.d/welcome.conf.bk  
[root@centos7-web ~]# cp /usr/share/backgrounds/* /var/www/html/.

未分类

[root@centos7-web ~]# grep -Ev "^$|^#|*#" /etc/httpd/conf/httpd.conf >/etc/httpd/conf/httpd.conf.tmp
[root@centos7-web ~]# cp /etc/httpd/conf/httpd.conf /etc/httpd/conf/httpd.conf.1106 
[root@centos7-web ~]# mv /etc/httpd/conf/httpd.conf.tmp /etc/httpd/conf/httpd.conf
mv: overwrite ‘/etc/httpd/conf/httpd.conf’? yes

二、关闭options 中Indexes(关闭文件列表)

[root@centos7-web ~]# vim /etc/httpd/conf/httpd.conf 
 [root@centos7-web ~]# grep "Indexes" -B1 -A3 /etc/httpd/conf/httpd.conf   查看修改后的结果
<Directory "/var/www/html">
#  Options Indexes FollowSymLinks   ##注释该行
    AllowOverride None
    Require all granted
</Directory>

[root@centos7-web ~]# systemctl reload httpd    
[root@centos7-web ~]# curl http://localhost                    
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>
</head><body>
<h1>Forbidden</h1>
<p>You don't have permission to access /
on this server.</p>
</body></html>

三、关闭FollowSymLinks(关闭访问符号链接文件)

[root@centos7-web ~]# ln -sv /etc/redhat-release /var/www/html/redhat-release.html
‘/var/www/html/redhat-release.html’ -> ‘/etc/redhat-release’
[root@centos7-web ~]# ls -hltr /var/www/html/redhat-release.html
lrwxrwxrwx 1 root root 19 Sep 21 16:15 /var/www/html/redhat-release.html -> /etc/redhat-release

[root@centos7-web ~]# curl http://localhost/redhat-release.html                  
CentOS Linux release 7.2.1511 (Core) 

[root@centos7-web ~]# vim /etc/httpd/conf/httpd.conf 
Options None   ##改成Options None 
[root@centos7-web ~]# systemctl reload httpd 

[root@centos7-web ~]# curl http://localhost/redhat-release.html
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>
</head><body>   ##Author : Leshami
<h1>Forbidden</h1> ## Blog : http://blog.csdn.net/leshami
<p>You don't have permission to access /redhat-release.html
on this server.</p>
</body></html>

Vagrant 开发环境配置

需要安装的软件

  • Vagrant

  • provider

    • VirtualBox(Free, recommend)

    • VMware

    • AWS

常用命令

安装

安装、启动、进入虚拟机就参见这个链接吧。注意:

be careful about rm -rf /, since Vagrant shares a directory at /vagrant with the directory on the host containing your Vagrantfile
vagrant init <box-name-on-cloud> # 生成 Vagrantfile 文件
vagrant up [--provider=virtualbox|vmware_fusion|aws] # 下载、配置、启动虚拟机
vagrant ssh # 连接虚拟机
vagrant destroy
vagrant reload [--provision] # 重新载入配置
vagrant share # 通过 ngrok 内网穿透功能实现让全世界人可以访问虚拟机的服务
vagrant status # 查看虚拟机状态

搜索可用虚拟机镜像(box):Discover Vagrant Boxes – Vagrant Cloud

其他镜像:http://www.vagrantbox.es/

销毁

vagrant suspend # 休眠
vagrant halt # 关机
vagrant destroy # 关机并完全销毁所有相关资源

打包

vagrant package # 打包生成 package.box 文件
vagrant box add <vm-name> <box-file-path> # 添加box

自定义配置

配置都保存在 Vagrantfile 这个文件里。

(待续)

碰到的问题

VBoxManage path on OSX

/Applications/VirtualBox.app/Contents/MacOS/VBoxManage

Fix it by soft link

ln -s /Applications/VirtualBox.app/Contents/MacOS/VBoxManage /usr/local/bin/VBoxMange

vagrant up无反应 on Win7

因为windows上vagrant和virtualbox版本不兼容,参见在windows 7中vagrant up 无反应,没任何信息输出 成功解决,但是出现 0x80004005 错误。

E_FAIL (0x80004005) on Win7

返回 代码: E_FAIL (0x80004005)
组件: Machine
界面: IMachine {480cf695-2d8d-4256-9c7c-cce4184fa048}

Try to solve but failed, possible solutions:

  • vagrant up 出现错误:使用vagrant部署开发环境遇到的坑 – CSDN博客
  • Vagrant error on Windows 10 · Issue #195 · scotch-io/scotch-box

结论

本文介绍了vagrant和安装,配置,启动和打包。还有,垃圾windows!

vagrant+virtualbox遇到的坑

这两天用vagrant+virtualbox搭建环境,按照以前的方法,先把它们都下载下来都是最新版本。接着傻瓜式的安装,添加box、初始化,接着vagrant up启动。然而并没有启动起来,光标一直在那里闪烁。瞬间意识到踩坑了。经过百度,Google,都说是版本问题,果断换版本。
这时候的用的版本VirtualBox-5.1.18-114002-Win.exe、vagrant_1.9.3.msi。完事之后vagrant up,结果命令错误,一个很奇怪的问题,提示没有配置系统变量,但是我已经配置了,还是提示一样的错误。
具体提示

$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
"rsync" could not be found on your PATH. Make sure that rsync
is properly installed on your system and available on the PATH.

解决方法:

打开目录,C:UsersAdministrator.vagrant.dboxescentos7.0virtualboxVagrantfile

Vagrant.configure("2") do |config|
  config.vm.base_mac = "525400cae48b"
  config.vm.synced_folder ".", "/vagrant", type: "rsync"
end

改成

Vagrant.configure("2") do |config|
  config.vm.base_mac = "525400cae48b"
  config.vm.synced_folder ".", "/vagrant", type: "virtualbox"
end

nginx 之前端图片webp

1. 需要有nginx+lua环境(参照前面)

2. 安装libjpeg,libpng

yum install libjpeg-turbo-devel libjpeg-turbo libpng-devel -y

3. 安装LibTIFF

cd /usr/local/src
wget http://download.osgeo.org/libtiff/tiff-4.0.8.tar.gz
tar -zxvf tiff-4.0.8.tar.gz
cd tiff-4.0.8
./configure
make
make install

4. 安装giflib

cd /usr/local/src
wget  https://downloads.sourceforge.net/giflib/giflib-5.1.4.tar.bz2
tar -jxvf giflib-5.1.4.tar.bz2
cd giflib-5.1.4
./configure
make
make install

5. 安装libwebp

cd /usr/local/src
wget http://downloads.webmproject.org/releases/webp/libwebp-0.6.0.tar.gz
tar -zxvf libwebp-0.6.0.tar.gz
cd libwebp-0.6.0
./configure --enable-libwebpmux 
--enable-libwebpdemux 
--enable-libwebpdecoder 
--enable-libwebpextras 
--enable-swap-16bit-csp 
--disable-static

make
make install

6. 测试转换

cwebp -q 75 IIS.png -o IIS-2.webp
cwebp -q 80 image.png -o image.webp

dwebp image.webp -o image.png

7. webp图片生成脚本

[root@tracker waf]# vim /usr/local/nginx/conf/lua/webp.lua
--检测路径是否目录,新增
local function is_dir(sPath)
    if type(sPath) ~= "string" then
        return false
     end
   local response = os.execute("cd " .. sPath)
    if response == 0 then
        return true
    end
    return false
end

-- 检测文件是否存在
function file_exists(name)
   local f=io.open(name,"r")
   if f~=nil then io.close(f) return true else return false end
end

--获取文件路径,新增
function getFileDir(filename)
    return string.match(filename, "(.+)/[^/]*%.%w+$")
end

-- 检测图片路径,新增
--if not is_dir(getFileDir(ngx.var.img_thumb_path)) then
--    os.execute("mkdir -p " .. getFileDir(ngx.var.img_thumb_path))
--  end
if not is_dir(getFileDir(ngx.var.filename)) then
    os.execute("mkdir -p " .. getFileDir(ngx.var.filename))
   end

local newFile = ngx.var.request_filename;
local originalFile = newFile:sub(1, #newFile - 5); -- 去掉 .webp 的后缀


if not file_exists(originalFile) then -- 原文件不存在
  ngx.exit(404);
  return;
end

--local command = [[/usr/local/GraphicsMagick/bin/gm convert -quality 75 -density 72 +profile "*"  ]] .. ngx.var.request_filepath ..  originalUri  .. " -geometry "  .. " " .. ngx.var.request_filename;
os.execute("/usr/local/bin/cwebp -q 75 " .. originalFile  .. " -o " .. newFile);   -- 转换原图片到 webp 格式,这里的质量是 75 ,你也可以改成别的

if file_exists(newFile) then -- 如果新文件存在(转换成功)
    ngx.exec(ngx.var.uri) -- Internal Redirect
else
    ngx.exit(404)
end

8. vhost.conf配置

server {
        listen 8216;
        #charset utf-8;
        server_name 10.160.43.105;
        index  index.php index.html;

        root /data/wwwroot/v2.50/wap.static/dist_dev;

        #if (!-e $request_filename) {
        #     rewrite .* /index.php last;
        #}
        # goole ngx_pagespeed
        # include extra/pagespeed.conf;

                #PHP support
                location ~ .*.php$ {
                        fastcgi_pass  127.0.0.1:9000;
                        fastcgi_index index.php;
                        include fastcgi.conf;
                }

                location ~* ^(.+.(jpg|jpeg|gif|png)).webp$ {
                        set     $webp_root /data/wwwroot/v2.50/wap.static/dist_dev;
                        root    $webp_root;
                        #if (!-f $request_filename) {
                        set $filename $webp_root$uri;
                        if (!-f $filename) {
                                set $request_filepath $webp_root$1;
                                content_by_lua_file "/usr/local/nginx/conf/lua/webp.lua";
                        }
                }
                location / {
                        proxy_set_header Host $host;
                        proxy_set_header X-Real-IP $remote_addr;
                        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                }

                # 测试lua安装是否成功
                # location /hello {
                #       default_type 'text/plain';
                #       content_by_lua 'ngx.say("hello, lua")';
                #}

        #log file
         access_log  logs/m250_access.log access;
}

Lua之异常捕获

如果需要在 Lua 中处理错误,必须使用函数 pcall(protected call)来包装需要执行的代码。 pcall 接收一个函数和要传递给后者的参数,并执行,执行结果:有错误、无错误;返回值 true 或者或 false, errorinfo。

pcall本质上是使用“保护模式”来运行第一参数,因此可以捕获运行过程中的错误。

给一个Cjson的例子:

local json = require("cjson")
local str  = [[ {"key:"value"} ]]

local t    = json.decode(str)
ngx.say(" --> ", type(t))

可以看到,需要解析的str是不完整的,缺少一个”,如果运行,将直接返回500内部错误。这显然不是我们想看到的。为了捕获这个问题,我们将decode封装一层,然后使用pcall来调用。

local json = require("cjson")
local str  = [[ {"key:"value"} ]]

function _json_decode(str)
    return json.decode(str)
end

function json_decode(str)
    local ok, t = pcall(_json_decode, str)
    if not ok then
        return nil    
    else
        return t
    end
end

local t = json_decode(str)

ngx.say(" --> ", type(t))

我们将json.decode封装起来,并使用pcall函数来调用,同样传入错误的字符串,函数会判断实行有异常,然后返回nil。这样我们就有了处理异常的机制。

Innodb索引以及查询优化的一些见解

聚集索引

索引如果没有特指,一般是指B+TREE,通常意味着所有值都是顺序存放,因此对于范围查询会非常快。InnoDB按照原数据格式进行存储。InnoDB存储引擎表是索引组织表,表中数据按照主键存放(InnoDB会隐式定义一个主键作为聚集索引,切记不能重复定义)。索引的叶节点中存放表的行记录,使叶节点成为数据页。而普通索引仅仅存放键值以及偏移量而已。(ps:MYISAM使用前缀压缩使索引更小,表中数据是通过索引所记录的数据物理的位置,直接引用的。)

Tips1:

范围查询非常快

eg:limit 优化

select * from yanxue8_visit limit 10,10

多次运行,时间保持在0.0004-0.0005之间

Select * From yanxue8_visit Where vid >=(
Select vid From yanxue8_visit Order By vid limit 10,1
) limit 10

Tips2:

在使用索引时需要独立的列

eg:

select * from tablename where id +1 = 5

这样的写法是不能用索引的,这也是为什么很多mysql优化语句中常提到的一点。

Tip3:

可以使用前缀索引

eg:

alter table tablename add key(a(7))

这样可以使索引变小并变快,节约空间,提高索引效率。但会减小索引的选择性。

前缀索引,一种优化索引大小的解决方案: https://yq.aliyun.com/articles/39841

事实上,聚集索引页有些缺点,提高了使用磁盘I/O的次数。并且要严格按照插入顺序插入,否则可能面临数据页分裂,耗用更多空间并降低性能。因此我们都需要一个自增长键作为主键,保证数据顺序写入。若使用UUID情况会变糟糕,所以现在分布式系统基本放弃了原生的UUID寻找替代品。

辅助索引(非聚集索引)

辅助索引只是存取了聚集索引的书签。若想查询需要对辅助索引遍历一遍再在聚集索引遍历一遍,遍历深度由索引树高度决定。

联合索引

联合索引顾名思义是多索引组成的联合索引.
如一张t表中有两列,a与b,其中a为主键,b为普通列
创建:alter table t add key idx_a_b(a,b)

未分类

如上图,数据先根据a排放,a值相同则根据b排放。既该索引包括了a与b的笛卡尔积。若where a = xxx and b = xxx 以及 where a = xxx则可以利用该索引,但where b = xxx 就不能利用该索引。(最左前缀)

好处:

可以联合读取多个列
可以做联合排序

Tip1:

利用多列条件做分页操作

创建:alter table tablename add key idx_a_b(a,b)

select * from tablename t1
left join(
select id from tablename
where a = 1 oder by b limit 1000,10) t2
on t1.id = t2.id

但事实上,也不能一棒子拍死。查询结果会非常依赖于选定的具体指,会对其他查询不公平,会使服务器运行不如预期。其顺序必须以选择性高低进行排序。事实上实际开发中,本人是因为某个查询量大的业务才建立联合索引,基本业务也是单个索引(但要注意重复索引,如我创建了(a,b)就得把(a)索引删除)。

哈希表

InnoDB中只用哈希对字典进行查找,事实上,哈希表只需理解有这么个东西就行。InnoDB会自动创建哈希表并维护,并只是对字典查询会变快(where a = ‘xxx’),不对范围查询起作用。

innodb_adaptive_hash_index 启用/禁用特性
innodb_buffer_pool_size/256=哈希的槽数

使用分析工具

explain

非常强大的工具,分析sql语句的性能以及所运用的索引。可以解决绝大多数sql性能问题。

慢查询日志

超过阈值的SQL语句记录的日志。

show index from tablename

可以分析表中索引,有些字段对于分析该表索引非常有用,如Cardinality。

analyze table

能优化索引存储,使索引更好工作.可每周或每天凌晨运行一次。

值得注意的地方

mysql在查询时,若数据大于整张表的20%,则会放弃索引

参考书籍

高性能MySQL: https://book.douban.com/subject/23008813/

MySQL技术内幕: https://book.douban.com/subject/5373022/

Mysql InnoDB的索引,锁如何协调作用以实现事务隔离级别?

未分类

MySQL的InnoDB存储引擎行锁是加在索引上的,所以只当增删改查操作是通过索引找到指定数据行的时候,才能对相应数据行的索引加锁,否则只能对整个表加表锁,表共享读锁或表独占写锁。

当一个事务不经过索引查询数据,即顺序读取(全表扫描)时,先获取表的意向共享锁,然后对表添加共享读锁,阻止其他事务对表的更新,新增和删除操作,但不影响查询操作,共享读锁之间是兼容的。

当一个事务不经过索引更新,删除数据,即全表扫描符合条件的数据行时,先获取表的意向独占锁,然后对表添加独占写锁,在执行更新,删除时阻止其他事务对表的读及写操作。

当一个事务使用索引去查询数据,即随机读取时,先获得表的意向共享锁,然后对符合条件的的索引区间加共享读锁(聚集索引肯定会加锁,若用到了非聚集索引一样加锁),共享读锁之间是兼容的,因此不影响其他事务对被锁数据行的访问。当其他事务想要修改,删除加锁的数据行时,若未使用索引则在获取表独占写锁时会失败。若使用索引检索这些数据行,则可能会在非聚集索引处被阻塞(查询事务和修改事务使用同一个索引检索数据行),也可能在聚集索引处被阻塞(通过非聚集索引查询到聚集索引的键,通过此键查询到相应的聚集索引,同时读到数据航,这是读和写,写和写之间的事务串行化保证),只能等待查询事务释放索引区间的共享读锁,然后执行更新,删除操作。当一个事务想要将新的数据行插入到被加锁的数据行中,也需要等待共享读锁的释放。因为InnoDB实现了间隙锁机制,即当一个事务按一个条件(id < 10,id列含有索引)加锁数据行时,其他事务不能在锁释放前将符合此条件的数据行(id = 5)插入到表中,此机制一定程度防止了幻读的出现。猜测实现机制:前一个事务对数据行的索引加了锁(聚集索引和非聚集索引),其他的事务插入数据时,需要新增聚集/非聚集索引,但是此时符合条件的聚集/非聚集索引区间已经被加锁,不能实时插入索引,需要等到索引区间的锁被释放,这个可能是间隙锁的实现原理。

当一个事务通过索引去更新,删除数据行时,先获取表的意向排他锁,然后对符合条件的数据行的索引加锁(聚集/非聚集),阻止其他事务对被锁数据行的读,写。同理实现间隙锁。