解决nginx开启http2不生效问题

先感受一下http2的优势

https://http2.akamai.com/demo

nginx在1.9起就开始支持http2了, 如下配置即可开启

listen 443 ssl http2;
server_name www.koyoz.com koyoz.com;

ssl on;
ssl_certificate fullchain.pem;
ssl_certificate_key privkey.pem;

验证是否开启: Chrome 安装 HTTP/2 and SPDY indicator, 若变成蓝色闪电就表示http2开启了

如果用以上配置后, 仍未开启 那说明编译时openssl的版本太低了. 下载最新openssl-1.0.2h
并指定 –with-openssl 为刚刚下载的新版本, 重新编译nginx, 即可开启https

效果如下:
h2

用curl测速

命令

curl -o /dev/null -s -w 'DNS:%{time_namelookup}\nConnect:%{time_connect}\nStart:%{time_starttransfer}\nTotal:%{time_total}\nSpeed:%{speed_download} byte/s' https://koyoz.com/blog/

返回结果:
DNS:0.030
Connect:0.078
Start:0.503
Total:0.515
Speed:60306.000 byte/s

字段含义:
time_connect 建立到服务器的 TCP 连接所用的时间
time_starttransfer 在发出请求之后,Web 服务器返回数据的第一个字节所用的时间
time_total 完成请求所用的时间
time_namelookup DNS解析时间,从请求开始到DNS解析完毕所用时间(记得关掉 Linux 的 nscd 的服务测试)
speed_download 下载速度,单位-字节每秒。

使用letsencrypt完全免费的https (nginx)

letsencrypt 已经开始公测了, 现在可以免费使用他提供的ssl证书了.

以linux下nginx为例.


git clone https://github.com/letsencrypt/letsencrypt
cd letsencrypt
./letsencrypt-auto certonly --standalone --email webmaster@koyoz.com -d koyoz.com -d www.koyoz.com

成功之后会提示如下信息

IMPORTANT NOTES:
- If you lose your account credentials, you can recover through
e-mails sent to webmaster@koyoz.com.
- Congratulations! Your certificate and chain have been saved at
/etc/letsencrypt/live/koyoz.com/fullchain.pem. Your cert will
expire on 2016-04-27. To obtain a new version of the certificate in
the future, simply run Let's Encrypt again.
- Your account credentials have been saved in your Let's Encrypt
configuration directory at /etc/letsencrypt. You should make a
secure backup of this folder now. This configuration directory will
also contain certificates and private keys obtained by Let's
Encrypt so making regular backups of this folder is ideal.
- If like Let's Encrypt, please consider supporting our work by:

Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le

开始配置nginx

listen 443 ssl spdy;
server_name koyoz.com;

ssl on;

ssl_certificate /etc/letsencrypt/live/koyoz.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/koyoz.com/privkey.pem;

ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;

其中ssl_ciphers可以通过 openssl ciphers 查看和选择

ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-DSS-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA256:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:DHE-RSA-CAMELLIA256-SHA:DHE-DSS-CAMELLIA256-SHA:ECDH-RSA-AES256-GCM-SHA384:ECDH-ECDSA-AES256-GCM-SHA384:ECDH-RSA-AES256-SHA384:ECDH-ECDSA-AES256-SHA384:ECDH-RSA-AES256-SHA:ECDH-ECDSA-AES256-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:CAMELLIA256-SHA:PSK-AES256-CBC-SHA:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:DHE-DSS-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-SHA256:DHE-DSS-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:DHE-RSA-SEED-SHA:DHE-DSS-SEED-SHA:DHE-RSA-CAMELLIA128-SHA:DHE-DSS-CAMELLIA128-SHA:EDH-RSA-DES-CBC3-SHA:EDH-DSS-DES-CBC3-SHA:ECDH-RSA-AES128-GCM-SHA256:ECDH-ECDSA-AES128-GCM-SHA256:ECDH-RSA-AES128-SHA256:ECDH-ECDSA-AES128-SHA256:ECDH-RSA-AES128-SHA:ECDH-ECDSA-AES128-SHA:ECDH-RSA-DES-CBC3-SHA:ECDH-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:SEED-SHA:CAMELLIA128-SHA:DES-CBC3-SHA:IDEA-CBC-SHA:PSK-AES128-CBC-SHA:PSK-3DES-EDE-CBC-SHA:KRB5-IDEA-CBC-SHA:KRB5-DES-CBC3-SHA:KRB5-IDEA-CBC-MD5:KRB5-DES-CBC3-MD5:ECDHE-RSA-RC4-SHA:ECDHE-ECDSA-RC4-SHA:ECDH-RSA-RC4-SHA:ECDH-ECDSA-RC4-SHA:RC4-SHA:RC4-MD5:PSK-RC4-SHA:KRB5-RC4-SHA:KRB5-RC4-MD5

1. letsencrypt的证书只有90天的使用期限, 但是可以通过脚本快速的更新. 据说已经有自动化脚本了.
2. letsencrypt并不会验证域名所有人等信息, 他主要是对传输加密, 防止窃听和篡改(防止某些运营商想在你的网站加入广告).

Elasticsearch 多字段评分排序

有这样一个需求: 展示一个用户列表, 有头像的优先展示, 有认证的优先展示, 有相册的优先展示, 同时拥有这些条件越多的则优先级更高, 第二排序条件是注册时间逆序.

通常是用条件进行过滤, 但往往是将不符合的条件数据去掉了, 而不是将其排在后面. 而对于多个条件时, 过滤更无能为力.

自定义脚本, 进行多字段评分排序, 可以很方便可以实现:

1. 写入配置文件, 开启script支持, 并重启Elasticsearch

script.groovy.sandbox.enabled: true

script.inline: on
script.indexed: on
script.search: on
script.engine.groovy.inline.aggs: on
script.engine.groovy.inline.search: on

2. 创建索引

PUT /users
{
  "mappings": {
    "list" : {
      "properties": {
        "Name": {
          "type": "string",
          "analyzer": "standard",
          "index": "analyzed"
        },
        "HasAvatar": {
          "type": "long"
        },
        "HasAlbum": {
          "type": "long"
        },
        "HasAuth": {
          "type": "long"
        },
        "RegTime": {
          "type": "date",
          "format": "yyyy-MM-dd HH:mm:ss"
        }
      }
    }
  }
}

3. 添加测试数据

POST /users/list/_bulk
{"index": {"_id": 1}}
{"Name": "Allen", "HasAvatar": 1, "HasAlbum": 1, "HasAuth": 1, "RegTime": "2015-12-01 00:00:00"}
{"index": {"_id": 2}}
{"Name": "Burnell", "HasAvatar": 0, "HasAlbum": 0, "HasAuth": 0, "RegTime": "2015-11-02 00:00:00"}
{"index": {"_id": 3}}
{"Name": "Chasel", "HasAvatar": 0, "HasAlbum": 0, "HasAuth": 0, "RegTime": "2015-11-22 00:00:00"}
{"index": {"_id": 4}}
{"Name": "Eden", "HasAvatar": 1, "HasAlbum": 0, "HasAuth": 1, "RegTime": "2015-12-02 00:00:00"}
{"index": {"_id": 5}}
{"Name": "Ford", "HasAvatar": 1, "HasAlbum": 1, "HasAuth": 0, "RegTime": "2015-12-03 00:00:00"}
{"index": {"_id": 6}}
{"Name": "Gordon", "HasAvatar": 1, "HasAlbum": 0, "HasAuth": 0, "RegTime": "2015-12-04 00:00:00"}

4. 按条件搜索

GET /users/list/_search
{
  "sort": [{
    "_script": {
      "script": "doc['HasAvatar'].value  + doc['HasAlbum'].value + doc['HasAuth'].value",
      "type": "number",
      "order": "desc"
    },
    "RegTime":{"order": "desc"}
  }]
}

看看结果是不是符合预期:

{
   "took": 8,
   "timed_out": false,
   "_shards": {
      "total": 5,
      "successful": 5,
      "failed": 0
   },
   "hits": {
      "total": 6,
      "max_score": null,
      "hits": [
         {
            "_index": "users",
            "_type": "list",
            "_id": "1",
            "_score": null,
            "_source": {
               "Name": "Allen",
               "HasAvatar": 1,
               "HasAlbum": 1,
               "HasAuth": 1,
               "RegTime": "2015-12-01 00:00:00"
            },
            "sort": [
               3,
               1448928000000
            ]
         },
         {
            "_index": "users",
            "_type": "list",
            "_id": "5",
            "_score": null,
            "_source": {
               "Name": "Ford",
               "HasAvatar": 1,
               "HasAlbum": 1,
               "HasAuth": 0,
               "RegTime": "2015-12-03 00:00:00"
            },
            "sort": [
               2,
               1449100800000
            ]
         },
         {
            "_index": "users",
            "_type": "list",
            "_id": "4",
            "_score": null,
            "_source": {
               "Name": "Eden",
               "HasAvatar": 1,
               "HasAlbum": 0,
               "HasAuth": 1,
               "RegTime": "2015-12-02 00:00:00"
            },
            "sort": [
               2,
               1449014400000
            ]
         },
         {
            "_index": "users",
            "_type": "list",
            "_id": "6",
            "_score": null,
            "_source": {
               "Name": "Gordon",
               "HasAvatar": 1,
               "HasAlbum": 0,
               "HasAuth": 0,
               "RegTime": "2015-12-04 00:00:00"
            },
            "sort": [
               1,
               1449187200000
            ]
         },
         {
            "_index": "users",
            "_type": "list",
            "_id": "3",
            "_score": null,
            "_source": {
               "Name": "Chasel",
               "HasAvatar": 0,
               "HasAlbum": 0,
               "HasAuth": 0,
               "RegTime": "2015-11-22 00:00:00"
            },
            "sort": [
               0,
               1448150400000
            ]
         },
         {
            "_index": "users",
            "_type": "list",
            "_id": "2",
            "_score": null,
            "_source": {
               "Name": "Burnell",
               "HasAvatar": 0,
               "HasAlbum": 0,
               "HasAuth": 0,
               "RegTime": "2015-11-02 00:00:00"
            },
            "sort": [
               0,
               1446422400000
            ]
         }
      ]
   }
}

字段评分还能根据不同需要给予权重, 同样可以用于带搜索词的情况中, 只需要设置好对应的评分权重即可.

解决MySQL5.6版本”innodb_table_stats” not found

MySQL启动时, 在error log中报错如下

2015-01-30 17:00:45 7f4d6a59c700 InnoDB: Error: Table "mysql"."innodb_table_stats" not found.
2015-01-30 17:00:45 7f4d6a59c700 InnoDB: Error: Fetch of persistent statistics requested for table "xxx"."wp3_options" but the required system tables mysql.innodb_table_stats and mysql.innodb_index_stats are not present or have unexpected structure. Using transient stats instead.
......

以root登陆mysql

use mysql;

drop table `innodb_index_stats`;

drop table `innodb_table_stats`;

drop table `slave_master_info`;

drop table `slave_relay_log_info`;

drop table `slave_worker_info`;

执行时若报table不存在的错误,可以不用管.

然后进入mysql的datadir, 执行

rm -f innodb_* slave_*

在到mysql中, 执行

source /yourpath/five-tables.sql

附件: five-tables

重启MySQL, 错误不再有了.

 

新的开始

godaddy的空间到期了, 换到了linode vps上, 价格是有点小贵, 但质量确实不错.

之前一直用sablog , 年久失修,  换成wordpress了, 老数据也不想再转移了.

旧版地址: http://koyoz.com/sablog/

貌似早已不流行写blog了, 看之前的友情链接, 不是打不开了, 就是改做其他内容了.

无所谓了,  放一个有空就记录点什么.