蒙奇日记

国庆长假回家当小孩儿

今天国庆节回老家去了,还记得上一次国庆节回家还是在大一的时候,那时候一个人去大学报道,在郑州陇海站被小偷把整个钱包都偷走了,里边放着一两千的现金、银行卡以及身份证,没办法只好等国庆回家办一张新的身份证。因为这件事也让我长了不少记性。

  • 不要在钱包带太多现金,平常只用带够可以应急用的就够了
  • 在人多嘈杂的环境下,要时刻注意自己的东西
  • 农历七月十五这一天,最好就在家呆着别乱跑,因为这一天是我们家的「倒霉日」(我爸定的)

其实本来是打算骑着山地车回去的,为此也准备了回去需要的东西,奈何天不如人愿,看着天气预报里连着几天的下雨天气还是打了退堂鼓,心里还想着下雨还骑车回去那不是纯纯的傻帽吗,于是就买了张高铁票打算做高铁回家。之前几次回家都是坐的拼车回家,因为可以直接给送到家门口,可以省下路途周转的功夫,但是人家只管接送郑州三环以内的,我现在住的远,也不想坐地铁去三环内,想想还是算了。

出发这天在郑州已经下了好几场雨了,所以气温比较温和湿润,虽然看着天气预报说是要降温,也象征性的带了一件卫衣,以为这一件就差不多可以了。谁想着刚回来这一天老家比郑州高好几度,在外边站着都一直冒汗,他妈的第二天温度骤降十五度,给人都要冻傻了都,于是便问我弟弟要了一件厚一点的外套穿。现在他很多衣服在很久以前都是我的,哈哈哈因为我弟弟很多衣服都是我穿不上淘汰下来的,我妈还说为此省了不少钱呢,笑死我了。

我弟弟,07年的小伙子,与我相差11岁11天,今年已经读初三了。过年见他的时候,感觉还是个小矮子,这次回来都快一米七了,而且说话的嗓音也变的很粗很浑厚,再也不是那种一听他说话就知道他是个小孩的那种稚气未脱的感觉,一下子感觉他好像长大了,我也不能再把他当小孩了。他学习挺好的,至少要比他这个哥要强多了,这就是所谓了「老二必定比老大强」吗?

虽说考试成绩挺好,但是有个毛病,就是字写的太差,不仔细看都看不懂,我爸也经常拿这个说教他,「字写成这样成绩能上去吗」、「字写的跟狗之叉一样」、「跟你哥学学,你哥的字可写的比你工整多了」(实话,没毛病)等等。为此我跟他说了我当初是怎么怎么坚持练字的,他说他知道,他在一个补习班的时候,听他班主任的说过了。这个老师就是我初二的班主任,在其他同学都放弃练字的时候我仍然在坚持练习,以至于她对我刮目相看。可是后来啊,唉……

说来也奇怪,我没怎么在他身上看见叛逆的影子,或许是我不经常在家,或许是我那时候太叛逆以至于我以为大家都那样,真的要比我那时候懂事多了,真好。不过不知道是不是因为在我面前不敢放肆,懂得都懂,血脉压制。

我还把我的卡西欧G-Shock头文字D周杰伦同款小方块手表送给我弟弟了,毕竟读中三了,有个手表对时间的管理也会好点。而且他也快生日了,我也想过这就当是送给他的生日礼物了,虽然说不是新的,不过这都是家人们,怎么会介意呢,哈哈哈,而且也是真的家人们。

这次回家也见到了爸妈,他俩还是老样子,我爸来来回回唠叨那几句话,「要注意身体,多休息,少熬夜」,「学着自己做饭,别经常点外卖」,「多锻炼,没事出去走走,别没事一直待屋里」等等,听的耳朵都要出茧子了。我妈则是老跟我唠他干啥了干啥了,衣服收拾的多好,做的被子多厚实多暖和等等,还说着「看你妈厉害吧,看看你爸,懒的跟呢啥一样」,哈哈哈可爱。这次回去我也不知道怎么回事,似乎是放的太开了,说话老带个「求」字,就是那个「去求」的「求」,我们那叫「说话带把儿」,于是便经常有了如下对话:

「你要是再不好好说话,信不信我揍你」

「你说话不是也老骂人吗?,你咋还好意思说我」

「那咱俩就谁也别说脏话了,害,这娃」

「……」

我妈是一个典型的农村妇女,家里生活上的事情都是我妈一手操劳的,性格也比较大大咧咧,有些事情也是我妈主事。因为很多东西都不舍得扔,导致家里有些地方堆满了旧的衣物啥的,每次回去都要跟她说把这些不用的东西都扔了得了,她就嚷嚷我,让我一边去……。我爸也说不过我妈,不过我现在发现我爸已经被我妈带的同化了,这就导致我奶现在对他俩意见都挺大的。

「让你爸把东西收拾收拾,就是不收拾,犟的跟驴一样,你回来了可跟你爸说说」

「跟他说了,我哪能说的动,你比他还大一级都说不动,何况我这还比他小一级」

「真服了这人,***」

回家待了三天,看着天气老是下雨,再加上感觉再待下去就该要烦我了,我就提前回郑州了。

这次回来感触最深的就是晚上一家人围着一个桌子吃晚饭的时候,说说笑笑,放下了所有在外饭局上的心思,就好像一个年龄稍大的小孩,放松且自然。

我平常不怎么爱回家,或许是野惯了,或许是回家有压力,又或许是嫌麻烦,理由可以找很多很多。

不过这次回去感觉还挺好的,或许是掌握了一个技能。

一个耳朵进,一个耳朵出。

上岸第一剑,先斩意中人

今天看完了路遥的《人生》

同情剧中的巧珍,那么的爱着高加林

单纯,勇敢,洒脱……

可是即使是这样,结果却还是被动的那一个

 

反观加林

虽然有着身为年轻人该有的事业心野心抱负心

虽然通过自己的努力距离自己的目标越来越近

却也滋生了本不该有的傲慢

是啊,是要远走高飞,是要去那旷阔天地大有作为

觉得巧珍不识字,农村妇女,两个人不合适

自己应该是要和黄亚萍这样的知识分子结合在一起的

 

于是便选择了黄亚萍

可是他又哪能想的到,自己因为走捷径而被人揭发

被赶回到生他养他的那个农村,那个他一直想逃离的农村

此刻他后悔了,后悔自己做的决定

正如他自己所说的那样,本来得到的是一块金子,却被他当作土疙瘩给扔掉了

 

这不免就让我想到了现实生活,有很多相恋的人,为了实现自己心中的目标,毅然决然的选择结束自己的感情

所以就又回到那个议题,爱情和面包哪个重要。

 


本来上面写的那些是在日记里写着的,仅仅是写一下读完这本书的感觉,写到 爱情和面包哪个重要 这句话的时候,已经很困了,索性就直接睡觉了得了,虽然也没写完。

然而过了几天,又想到了这本书,看着之前写的这段话,回忆一下刚看完的感觉,很难受很惋惜很愤恨。高加林他怎么这样,黄亚萍有那么好吗??以至于我写的日记字里行间也都带着情绪。

这本书算是路遥的成名作,很多名人也都推荐过。所以我就在想,我只从这本书里看到这些年轻人的爱情,是不是有点狭隘了。一本爱情小说而已,何以值得这么多人称赞。好吧,我承认这里是有偏见,可能我认为爱情都太俗了。

于是我从上帝的视角挣脱出来,进入书中的角色,想象自己是高加林,想象自己从小就在农村,想象自己读过书,不同于农村其他没读过书的孩子,有那种读书人的傲气,自己和别人不一样。

其实也不用想象,我们很多地方都差不多,我也是土生土长的农村人,吃过种庄稼的苦,也曾经觉得自己读的书比别人多而觉得自己是所谓的文化人,懂得比别人多,也认为自己前途无量,应该是要搞一番大事业。

好像书中的人就是我,可是,我没有走后门的能力,现在依旧在破旧的生活中沉沦。

当我处在他的人生时,我会做什么选择,会不会因为自己迫切的野心而放弃自己珍贵的东西,就如书中放弃爱情一样。现在也只能说:不清楚,不知道。

现在再看日记里的随手写的一个疑问:爱情和面包哪个重要似乎是不正确的,应该是爱情和事业哪个重要。

那么爱情和事业哪个重要?鱼和熊掌不可兼得,选择必然伴随着代价,但是我想大多数人的选择应该和高加林的一样,选择后者吧,现实就是这样。

「上岸第一剑,先斩意中人」,这些不就是我们现实生活中经常发生的事情。

书中的扉页这样写道:“人生的道路虽然漫长,但紧要处常常只有几步,特别是当人年轻的时候。没有一个人的生活道路是笔直的、没有岔道的。有些岔道口,譬如政治上的岔道口,事业上的岔道口,个人生活上的岔道口,你走错一步,可以影响人生的一个时期,也可以影响一生。

好像是在说人生处处都是选择,到处都是岔路口,不要做错误的选择。

可是现在我们看完整个故事是可以下结论说高加林的选择是错误的,但我们自己的人生又怎能知道那未来,又怎能确定当下的选择是正确与否。

或许这就是人生吧。

毕竟,我也不懂人生,我也才二十几岁,我也还年轻。

当潮流爱新鲜,当旁人爱标签

时隔多年,又再一次听到了Eason的歌,回忆在脑海中翻滚。犹记得高中的时候,手机里放的最多的就是Eason的歌,这些俨然已经成为我青春的一部分。

那时候青春懵懂,不是很懂感情,好不容易遇到喜欢的女孩,终于鼓起勇气向对方表白,收到的却是干脆的拒绝,两个人也因此不再说话,即使说话也是恶意中伤的话。

被拒绝的感觉不好受,本来这个年纪就是矫情的年纪。

对于世上的不管是音乐亦或是电影,只要感到特别喜欢,那么一定是与自己的经历、思想、亦或是深藏的感情不谋而合,产生强烈的共振。

而Eason的歌就是这样,嗓音沙哑且稳定,徐徐道来自己的故事,温柔且坚定。

有人说他的歌丧,可真的伤心难过时去听他的歌,能感受到的却是温暖和慰藉。

仔细想想我也好久没有听过Eason的歌了,可能是感情生活过的还算如意,不需要像当时一样寻求慰藉。但就在当时来说,Eason就真像人们称呼的那样,像医生一样治疗人们内心的感情创伤。

附上这首时隔多日唤起回忆的歌——*《无条件》*

当潮流爱新鲜,当旁人爱标签

幸得伴着你我,是窝心的自然

当闲言再尖酸,给他妒忌多点

因世上的至爱,是不计较条件

科学有效的上网方法

看这这个挺高大上的标题,好像就像是标题党一样,其实真正的标题用正常人的话来说,就是如何科学的上网,只不过生活在大陆这个环境下,已经习惯了用各种隐晦的词来描述某些东西。算了,标题党就标题党吧。

写这篇的主要原因也是因为最近腾讯云把我的一个香港服务器给封禁了,理由也是意料之中的「存在通过技术手段使其成为跨境访问节点等行为」,刚开始还以为是先发出警告,等我连接服务器的时候发现直接是把服务器给封掉了,连22端口都没得用。幸亏部署的服务都是静态方式存储的,而且大多数还都有备份,这要是没有备份的话,真的要气死人了。

没办法只好重新搞一台服务器了,不过这次选用的国外的服务器,服务器拿到手就直接通过脚本部署了一套SSR,刚用了几个小时就被Q了,切换IP同样操作之后还是没过多久就又不行了,于是尝试更换方案,经过了解尝试使用V2Ray+websocket+tls+web的方式来构建服务。

V2Ray+websocket+tls+web是目前最稳定的翻Q技术之一,即使在敏感时期也稳如泰山。和SSR的流量混淆不同,V2Ray+ws+tls用真正的https流量FQ,没有必要做任何混淆。在长城看来,流量和不计其数的https流量没有任何区别。但是如果GFW尝试主动嗅探的话,发现流量的目的地没有真正的网站,从而被识破然后被Q。所以要在这个服务外面加一个真正的网站做掩护,从而假装是访问真正的网站。

Cloudflare配置DNS

这次部署过程中,使用的是Cloudflare作为DNS服务器,Cloudflare是世界上最大的CDN提供商,全球半数的网站都在使用Cloudflare。使用不用担心隐私泄露或钓鱼风险,而且也可以提供免费的CDN服务,只不过对于国内来说,访问速度可能会慢一点。

jFu3MfCB

  • DNS类型为A类型
  • 名称为要解析的域名地址,可以顶级,也可以是二级域名
  • 内容就是要解析的IP地址
  • 代理状态为「仅限DNS」,注意小云朵是灰色

配置完成之后可以使用 ping命令测试是否可以ping通,如果可以,那就说明配置没问题。

V2Ray安装和配置

网上已经有很多一键安装脚本,这里选用的是 https://github.com/v2fly/fhs-install-v2ray,此脚本需要在root用户下运行,并且会安装如下文件:

installed: /usr/local/bin/v2ray
installed: /usr/local/bin/v2ctl
installed: /usr/local/share/v2ray/geoip.dat
installed: /usr/local/share/v2ray/geosite.dat
installed: /usr/local/etc/v2ray/config.json
installed: /var/log/v2ray/
installed: /var/log/v2ray/access.log
installed: /var/log/v2ray/error.log
installed: /etc/systemd/system/v2ray.service
installed: /etc/systemd/system/v2ray@.service

此脚本会配置自动运行脚本。自动运行脚本会在系统重启之后,自动运行 V2Ray。目前自动运行脚本只支持带有 Systemd 的系统,以及 Debian / Ubuntu 全系列。

其中路径/usr/local/etc/v2ray/config.json就是配置文件的路径,安装完成之后只用修改这个文件即可。

关于V2Ray的配置网上已经有很多,我们只需要下载一个,其中需要修改的地方改成我们自己的即可。可以参考我的配置:

{
    "inbound": {
        "protocol": "vmess",
        "listen": "127.0.0.1",
        "port": 8080,
        "settings": {
            "clients": [
                {
                    "id": "◆◆◆◆◆◆◆◆◆◆◆◆",
                    "afterId": 0,
                }
            ]
        },
        "streamSettings": {
            "network": "ws",
            "wsSettings": {
                "path": "/★★★★★★★★★★★★"
            }
        }
    },
    "outbound": {
        "protocol": "freedom",
    "ip": ["geoip:provate"],
    "outboundTag": "blocked"
    }
}

在这个配置文件中,需要将标记的信息换成自己的即可:

"◆◆◆◆◆◆◆◆◆◆◆◆":uuid,自己生成或者通过在线网站生成,例如:63c0042a-4a85-4d03-a488-3ba383142461

"★★★★★★★★★★★★":这个地方填写的则是一个随机字符串,越没有规律越好,越乱越好,可以在键盘上胡乱打一串或者程序生成。其实这个字符串就是websocket路径,在配置客户端的时候需要用到。

Nginx配置反代

因为上面已经配置了DNS的解析服务,而且也不适合直接用IP,所以这时候就需要用Nginx来代理websocket,配置文件内容如下:

server {
    ### 1:
    server_name ●●●●●●●●●●●●;

    listen 80 reuseport fastopen=10;
    rewrite ^(.*) https://$server_name$1 permanent;
    if ($request_method  !~ ^(POST|GET)$) { return  501; }
    autoindex off;
    server_tokens off;
}

server {
    ### 2:
    ssl_certificate /etc/letsencrypt/live/●●●●●●●●●●●●/fullchain.pem;

    ### 3:
    ssl_certificate_key /etc/letsencrypt/live/●●●●●●●●●●●●/privkey.pem;

    ### 4:
    location /★★★★★★★★★★★★
    {
        proxy_pass http://127.0.0.1:8964;
        proxy_redirect off;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;

        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_requests 10000;
        keepalive_timeout 2h;
        proxy_buffering off;
    }

    listen 443 ssl reuseport fastopen=10;
    server_name $server_name;
    charset utf-8;

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_requests 10000;
    keepalive_timeout 2h;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-128-GCM-SHA256:TLS13-AES-256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
    ssl_ecdh_curve secp384r1;
    ssl_prefer_server_ciphers off;

    ssl_session_cache shared:SSL:60m;
    ssl_session_timeout 1d;
    ssl_session_tickets off;
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8 8.8.4.4 valid=300s;
    resolver_timeout 10s;

    if ($request_method  !~ ^(POST|GET)$) { return 501; }
    add_header X-Frame-Options DENY;
    add_header X-XSS-Protection "1; mode=block";
    add_header X-Content-Type-Options nosniff;
    add_header Strict-Transport-Security max-age=31536000 always;
    autoindex off;
    server_tokens off;

    index index.html index.htm  index.php;
    location ~ .*\.(js|jpg|JPG|jpeg|JPEG|css|bmp|gif|GIF|png)$ { access_log off; }
    location / { index index.html; }
}

看上去很长,实际上只有四处需要填写,配置文件里用#1,#2,#3,#4标出了位置,把标符号的地方换成你自己的信息。

●●●●●●●●●●●●:标注“●”的地方填写域名,注意这里的域名带www

★★★★★★★★★★★★:标注“★”的地方填写一个随机字符串,这个随机字符串必须和V2Ray配置中的一样,不然无法工作。注意不要删掉前面的斜杠。

最后,把Nginx的配置文件另存为default.conf(注意扩展名就是.conf),放在/etc/nginx/conf.d/下。

配置SSL证书

为了用真正的https流量翻墙,网站就必须有合法的SSL证书。可以用自动化工具Certbot申请证书,只要把以下命令复制到命令窗口,依次执行即可。

这里说的“证书”,实际指的是“数字证书”。当然申请完全是免费的,申请时需要邮箱地址。如有必要,可以使用匿名邮箱。

安装certbot

由于服务器系统自带的Python环境是v3.7,但是没有安装pip,所以首先安装pip工具。

apt install python3-pip

安装好pip之后即可安装certbot

pip3 install certbot

生成证书

certbot certonly --standalone --agree-tos -n -d www.●●●●●●●●●●●● -d ●●●●●●●●●●●● -m ●●●●●●●●●●●●@●●●●●●●●●●●●

第一个-d加一个带www的域名,第二个-d加一个不带www的域名,-m后面加你的电子邮箱。注意前后要带空格。

运行这条命令后,如果显示:

IMPORTANT NOTES:

- Congratulations! Your certificate and chain have been saved at:
  /etc/letsencrypt/live/www.hrw1rdzqa7c5a8u3ibkn.website/fullchain.pem
  Your key file has been saved at:
  /etc/letsencrypt/live/www.hrw1rdzqa7c5a8u3ibkn.website/privkey.pem
  Your cert will expire on 2020-06-04. To obtain a new or tweaked
  version of this certificate in the future, simply run certbot
  again. To non-interactively renew *all* of your certificates, run
  "certbot renew"

- Your account credentials have been saved in your Certbot
  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 Certbot so
  making regular backups of this folder is ideal.

- If you like Certbot, please consider supporting our work by:

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

表示证书生成成功。

注意:在生成证书的时候容易出现问题,就比如我在生成证书的时候就出现如下错误:

x86_64-linux-gnu-gcc -pthread -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fno-strict-aliasing -Wdate-time -D_FORTIFY_SOURCE=2 -g -fdebug-prefix-map=/build/python2.7-PPrPZj/python2.7-2.7.15=. -fstack-protector-strong -Wformat -Werror=format-security -fPIC -DUSE__THREAD -DHAVE_SYNC_SYNCHRONIZE -I/usr/include/ffi -I/usr/include/libffi -I/usr/include/python2.7 -c c/_cffi_backend.c -o build/temp.linux-x86_64-2.7/c/_cffi_backend.o
  c/_cffi_backend.c:15:10: fatal error: ffi.h: No such file or directory
   #include <ffi.h>
            ^~~~~~~
  compilation terminated.
  error: command 'x86_64-linux-gnu-gcc' failed with exit status 1

解决办法是安装相关依赖即可。

apt install libffi-dev

同样的因为这个问题导致的cryptographypyopenssl版本问题,也可以通过升级安装包解决。

另外通过这种方式生成的证书时限只有三个月,所以我们通过定时任务,让他自从申请证书,从而达到证书的 自动续命

echo "0 0 1 */2 * service nginx stop; certbot renew; service nginx start;" | crontab

启动服务

测试V2Ray配置是否正常

/usr/local/bin/v2ray -test -config=/usr/local/etc/v2ray/config.json

如果显示:

V2Ray 4.x.x (V2Fly, a community-driven edition of V2Ray.)
A unified platform for anti-censorship.
Configuration OK.

测试nginx配置是否正常

nginx -t

如果显示:

nginx: the configuration file /etc/nginx/ngin短网址nf syntax is ok
nginx: configuration file /etc/nginx/ngin短网址nf test is successful

说明配置没有问题。

测试V2Ray和Nginx配置正常之后即可启动服务了。启动服务通过service命令启动

启动V2Ray:

service v2ray start

启动Nginx

service nginx start

配置完成后,可以在浏览器里输入网址,如果显示Nginx的欢迎页面,就说明网址配置成功了! 接下来要做的是上传一个网页模板,这样别人访问你的服务器就会看到一个真的网站。

在网上找一些静态网页模版,放在目录/usr/share/nginx/html/下即可,最好是找一些全英文的网站,存在中文的话可能会增加一些被墙的概率。

客户端配置

这里使用的客户端是著名的代理软件Shadowsockets(小火箭),这是一款iOS生态下全平台通用的一款软件,配置也相对简单。

XUEexvP4

点【服务器】按钮,选择【添加VMess】服务器。

  • 地址:域名地址,当然也可以IP地址
  • 端口:443
  • UUID:就是上面说的V2Ray配置文件里的UUID
  • 额外ID:0,最新的V2Ray版本已经强制为0,至于原因可以自行Google
  • 算法:随便选。
  • 传输方式:选WebSocket;Host:域名地址;路径:即前面的随机字符串,注意前面必须要加上斜杠“/”

image-20220720124353424

  • 别名:随便填。
  • TLS:打开

到这里基本上就算完成了,当然还有一些其他优化项,比如:

  • CDN隐藏域名IP
  • BBR加速(debian10以上自动开启)
  • 配置防火墙

想要了解的可以自行Google,我太懒了,也没有做这些配置,就不一一赘述了,逃。

参考链接:https://pincong.rocks/article/15493

你真没意思啊

无聊之中想到自己的生活怎么这么无趣,要是变得有趣一点就好了。于是就突然想到「有趣」这个词,想了想还觉得挺有意思的,到底什么才算是有趣呢,我们会怎么评价一个人有趣呢?是网上那些人吗?那些有着奇思妙想的人,那些可乐搞笑的人,那些满腹经纶的人,还是那些勇敢自由的人呢。我们好像普遍喜欢称呼这些人就是有趣人的人,喜欢在网上关注这些人,还会时不时的评论一句:「我要是像你一样就好了」

或许是普通人的生活太过规律平淡,三点一线已成为生活的主旋律,吃饭、工作、睡觉。娱乐活动也就那么几个,看剧打球打游戏。我们评价这些为无趣的生活。或许是我们对于习以为常的事情会感到厌倦,又或许是对于目前这操蛋的生活感到疲惫,我们开始抱怨,我们想要改变自己的生活,想要这平淡泛起波澜,想要挣脱这牢笼,想要自由。

那些被称作有趣的人满足了我们对于自己该有生活的期望,让精神得以享受,我们喜欢这种感觉。是的,好像这种有趣的人对于我们来说是精神食粮,我们称呼一个人有趣,是因为他们拥有取悦我们的能力。

可是还有一些人,他们喜欢打游戏看剧,我们会评价这些人为无趣的人,甚至还会时不时来上一句「你真没意思」,更有甚至「无趣」也终结了很多亲密关系。

然而我们评价一个人怎么怎么样,不过是站在自我的角度来看的,就如同上面所说的那样,当这个人没有达到让自己快乐的点的时候,我们是不愿意同这种「没意思」的人打交道的。

那么这些人真的是无趣的人吗,我无法进行评价,但是可以知道的是,他们沉浸在自己的小世界中,做着自己喜欢做的事来取悦自己,那么我想对于他们自己来说,自己还是「有趣」的。

不知不觉写了这些,也不知道写的主题是啥,大聪明脑袋总是时不时的不聪明,不过刚好今天空闲,就动动手指把想的啥给记下来吧。

权当就是胡说八道得了。

理想主义下的web3

前些日子没事了解到了web3,甚至还有很多人扬言要辍学然后all in web3,不知道他们为何如此疯狂,猜测他们可能为了实现财富自由而选择赌一把,或者是愿意义无反顾的投入到这个在目前看来还是理想主义的虚拟世界中。我想还是前者应该更多一点吧。

web2存在的问题

说到web3,那就不可避免的要谈论web2。在web2时代,人们活跃在诸如微博、知乎之类的大型平台上,将自己的想法发布在平台上,但是这条内容仍然不是归属个人所有,平台可以随意删除这条内容或者封禁自己的账号。

平台垄断让言论自由似乎成了笑话。

再比如通过支付宝或者微信转账,我们在手机里输入的金额,只不过是他们数据库里的一条记录,所有的交易都要通过支付宝公司的银行账户,此时支付宝决定着你的财产,当账号被冻结时,财产也随之被冻结。

诸如此类的还有很多问题,如大数据收割、信息贩卖等。

俗话说,压迫之下必有革命,web3就是在这个背景下衍生出来,用来对抗web2时代的这些巨头的垄断霸权,人们从那些巨头手里夺回自己所有物的完全控制权,不再受其控制。

web3该怎么定义

去中心化”是web3发展的灵魂,因其自由和平等的精神令人心驰神往。web3发展至今,仍然还是在非常早期的阶段,人们一听web3就觉得是区块链是炒币,是骗局。其实区块链只是web3的一种解决方式而已,至少目前来看是唯一的解决方式。至于虚拟币和web3的关系,那是因为区块链的每一个节点的搭建是需要发放激励代币的,人们通过将自己的电脑搭建成矿机之后,作为区块链中的一块,这条链会为这个用户发放激励代币,用来奖励该用户,不然人们凭什么要贡献自己的计算资源。

区块链技术当中的智能合约,是Web3.0的一个基石,其宗旨是“code is law”,代码即法律、代码即规定,一切规则被写进协议,一旦开启便不可篡改,代码开源、公开透明,接受所有人的检查,同时区块链节点分布式的协同共识,把信任的需求降到最低,人们不需要信任,只需要代码验证即可。

所以用户发布的信息,也不再将收到平台的这种审查,因为这里没有一个中心化的管理者,或者说人人都是管理者,从而真正实现言论的自由和平等。

web3存在的一些问题

就先从虚拟币来看,目前有太多投机者和Ponzi以及赌狗,因为人人都可以发币,只要有打着web3的口号,就可以疯狂炒作自己的币种,致使那些想要暴富的人陷入FOMO的情绪当中而倾家荡产。

其次就是自由必然带来混乱,比如可以在链上发布一些暴力和Pron的内容,然而这些内容是无法篡改和删除,这种混乱又该如何有一个良好的治理,仍然需要继续探索。还有既然是代码组成的世界,那么也必然就会有漏洞,所以就会被“科学家”通过漏洞盗走财产。

然后就是与现实的割裂,链上的“无政府主义”始终是虚拟世界的,当肉身处于一个现实世界中,当有关机构一声令下,现实中的人又哪有抵抗的能力呢。

web3的未来会是什么样

首先web3无疑会是一场革命,至于最终会发展成什么样子,还是一团迷雾,需要人们不断探索。

至少最近几年甚至十几年应该是没有什么大的进展,只是一种乌托邦式的理想主义。

也许只有在经过混乱、贪婪、疯狂的情绪之后沉淀下来,才会有新的突破,也许那时候已经不是区块链,而是更先进的技术。

web3的未来就交给时间来验证吧,毕竟时代的车轮总是在向前推进。

There is no web3 in China.

2021年终总结

马上2021就要结束了,所以又到了该年终总结的时候,坐在电脑桌前回想着这一年,依旧是浑浑噩噩,想不起来自己做过什么了不起的事,对社会更没做什么贡献,只记得生活和工作被乱七八糟的事情搞得一团糟。

有很多想学的东西,到最后也不过是三分钟热度。

有一直想去的地方,但是因为疫情和工作,到最后也只是窝在自己的出租屋里。

想让自己生活变得有趣,可又拿自己一个人没意思为借口拒绝做了很多事,到最后还感慨生活真是无趣。

经典emo开场,不过,其实仔细想一想,也并不是什么都没有收获的,至少收获了一年的时间呀。

Done

  • 画画。虽然到现在为止画的依然像是「狗支叉」,但我找到了一种新的解压方式:在哔哩哔哩看别人画画。看着简简单单的笔画线条,一笔一画的绘出一幅完整的漫画,感觉真的很美好。至于为什么看别人画漫画,特么的还不是因为自己不会:)

  • 减肥,0.0。说来也挺好笑的,减肥这个词本来是从来不应该出现在我的词典里的,因为我向来都是怎么吃都吃不胖。奈何工作几年之后,经常吃饱就在那坐着,日积月累,最后挺着一大肚子。对于还是比较注意形象的我,开始走上了减肚子的道路。因为已经是秋冬的季节了,在外跑步的话害怕着凉,就选择在家锻炼。每天晚上跟着视频做20-30分钟的锻炼,晚餐只吃两个鸡蛋加一杯牛奶,就这样坚持了快两个月,体重由134→131。。。虽然体重没减多少,但是肚子是真的变小了,而且也可以摸到一点点腹肌了。

  • 背单词。今年陆陆续续的背了将近有八百个左右的单词吧,后来测试的时候结果只记着一半,现在记着的估计更少了,别人都是过目不忘,而我偏偏是过目就忘。

  • Coding。今年基本上没有学习什么新的技术,更多的是在继续深入已经学习的东西。

  • 人生中第一次在天安门前看升国旗,可是人太多了,凌晨三点去的时候也只能排在最后了。

  • 学会了用Figma,然而现在练的少,审美也还跟不上,还要多看多练。

Life

  • 抽烟变少了。仔细想想,今年好像抽的烟也很少了,一天抽烟的次数基本上等同于自己蹲厕所的次数,如果忘拿了的话就不抽。但是,虽然说有时候不抽,但是身边不能没有,一没有就没有安全感,可买了又只是在桌子上放着,也不知道这是什么毛病。
  • 因为游戏无聊,所以不怎么玩游戏了,在steam上买了好几个单机游戏也都是登录了一下就没再玩了。想等以后两个人住了,买台PS游戏机,没事的时候两个人在家一起玩。
  • 用碎片化的时间开始阅读,特别是在地铁上的时候,通勤时间比较长,这应该是最适合消磨时间的方式了。
  • 本来期望的是今年可以好好自己做做饭,顺便学着做一些好吃的,可基本上是都点外卖了,做饭的次数屈指可数。
  • 吃饭这件事要全面发展,不能只吃一类东西,补充营养要全面均衡,不然就容易出毛病。比如口腔溃疡,这真的是很痛的领悟。

Event

印象里最深的事也就是720那场水灾吧。上一次经历水灾的时候在1998年,但是那时候还是个小屁孩,只记得跟在姐姐后面玩的时候,从水里蹦出来一个特别大的蛤蟆给我吓哭了,后来才知道那东西叫牛蛙。

水灾之后因为交通瘫痪,骑了两个月的电动车去上班,单个路程大概需要一个多小时。也正是因为骑电动车,在路上也看到了很多不同于地铁里沉闷嘈杂的风景,所以在路上的感觉也还挺开心的。今天下班的时候,在路上会看到什么呢。

地铁内是人挤人,大街上却是车挤车,一不留神就容易跟人怼上,还怼的不轻。

刚跟人怼上的时候只感觉擦破了皮,去包扎一下就好了。然后就是好些天右胳膊提不起来重物,一使劲就劲疼。所以以后一定要好好做检查,可别落下什么隐疾了。

Best buy

MacBook Air

其实很早就想拥有一台MacBook,奈何觉得太贵,花这么多钱买个这不值得,就在换电脑的时候买了台便宜点的Thinkpad。

可能是因为经历过那次水灾之后,觉得人活着不容易,满足自己一些喜欢的东西没什么不好的,再加上新的芯片也很受大家的吹捧,所以就没忍住买了一台,结果就是真的香。

Mi band 6

便宜不贵,和手机的兼容性也好。

既可以记录睡眠、心率,又可以当跑步记录仪,充一次电可以用好多天。

和昂贵的Apple Watch比真是太高的性价比了。

Books list

  • 三体
  • 亲密关系
  • 君主论
  • 爱的博弈
  • 绝叫
  • 狂人日记
  • 人间失格
  • 旅行之木
  • 人类简史

Hope

  • 多做饭,少点外卖,学着做些好吃的
  • 多一些有意义的爱好,让自己变得有趣
  • 学一些新技术或者新技能,技多不压身嘛
  • 拍照技术可以好点,看见别人随手一拍就是美景,真是羡慕
  • 疫情赶快过去吧,太特么烦了

The end, but new beginning.

迷之操作|Django版静态Note生成器

Powered by Django

正如这句话而言,目前这个网站是用Django来搭建的,至于当初为什么要选择Django,可能是因为它作为最流行的Web框架之一,开发迅速,以及自带的admin管理,可以迅速成型一个小型站点,YYDS。

Why change

最初这个网站是部署在HK的一个VPS上的,配置也是最低配置,解析是套了一层CF,所以造成国内访问非常慢。不过也可以忍受,就没在这上面折腾。按理说这种网站是用来写的,但我好像不务正业的折腾起来了页面,每换一种风格,用不了多久就觉得看着不舒服,于是又重新改了一套页面,于是又重复于此。

前段时间正好赶上各大云厂商双11做活动,于是在结束的最后一天在良心云上薅了一台国内的VPS,配置要比之前的好一点,而且在国内速度跟之前比也是起飞一般的速度。

在迁移项目的时候突然想到,现在的数据都是在当前主机上的,万一哪一天服务器忘记续费的话,等到期的时候数据岂不是就全丢了,要是把数据全上传到Git,这样不就不用担心了,而且切换服务器的时候,直接把项目拉下来直接就能跑,就像Page服务一样,那岂不是妙哉。

Ready to go

切换数据库从MySQL到SqlLite

因为SqlLite数据库是一个本地文件数据库,对于这种小型站点来说,十分便携方便,而且还可以直接上传到Git,所以就把数据全导入到这个数据库里边了。

全站静态化

首先统计网站的页面都有哪些,每个页面的路由都是什么,通过这些可以组织静态网页存放的目录结构,而且这些在之后的Nginx配置中也十分重要。

比如我的文章路由为https://itsso.cool/blog/django-staticize.html,那么文章 django-staticize.html就应该放在静态文件根目录的 blog目录下。

由于平时写笔记喜欢在Typora上写完之后,在把文章源码复制到在线的编辑器内,再保存上传发布,同时笔记文件也会同时上传到Github以做备份。但是这样就会存在一个问题,假入想要修改其中某一篇内容的话,重复上面的步骤,实在繁琐,要是把笔记文件连同静态文件在项目部署的时候一起打包发布就好了。

所以就开始改造模型,修改文章内容字段为FileField,将笔记文件的相对路径保存到本地数据库内,每次写完就直接把文件上传。

在构建静态文件的时候,数据来源从本地保存的文件来读取,这样一来既可以将笔记备份,同时在修改内容的时候也可以极大的缩减上传步骤。

给Typora配置专属图片上传服务器

在写笔记的时候难免会有一些图片,在上传这些图片的时候就会比较麻烦,因为Typora里边文件存放的只是一个当前主机的绝对路径,直接将笔记发布到线上的时候,图片会因为路径的问题加载不出来。此时就需要将图片保存到一个公网可以访问的一个图床内。

好多人的做法是将自己的图片上传到微博、知乎、csdn等一些知名网站上,然后再将这些图片链接插入到自己的笔记内。这样做虽然是很方便快速,但是也会存在一些问题,就比如微博在某一天,突然给自己的链接加上了防盗链,导致了所有的图片在自己以外的网站不能继续使用。

另外的像GitHub/Gitee Page服务,也可以将自己的图片上传到他们的服务器,但是据说会存在不稳定的情况,想了想还是算了。

自己的东西掌握在自己手里才踏实,于是就自己搞了一个专属于自己的图床服务,这次倒是没有选择Django,而且选择了更合适轻量化的Flask。

#!/usr/bin/python
# -*- coding: UTF-8 -*-
import os
import random
import string
from datetime import datetime

from flask import Flask, request
from markupsafe import escape
from werkzeug.utils import secure_filename

from dotenv import load_dotenv

env_path = '.env'
load_dotenv(dotenv_path=env_path)

STATIC_FOLDER = "images"
STATIC_URL = "/img/"

app = Flask(__name__, static_folder=STATIC_FOLDER, static_url_path=STATIC_URL)

app.config['UPLOAD_FOLDER'] = STATIC_FOLDER
basedir = os.path.abspath(os.path.dirname(__file__))
ALLOWED_EXTENSIONS = {'txt', 'png', 'jpg', 'xls', 'JPG', 'PNG', 'xlsx', 'gif', 'GIF'}

HOSTNAME = os.getenv('HOSTNAME')


# 用于判断文件后缀
def allowed_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS


# 上传文件
@app.route('/api/upload', methods=['POST'], strict_slashes=False)
def api_upload():
    access_token = request.form.get("access_token") or " "
    if access_token != os.getenv("ACCESS_TOKEN"):
        return "error", 403

    time_path = datetime.now().strftime("%Y/%m/")
    file_dir = os.path.join(basedir, app.config['UPLOAD_FOLDER'], time_path)
    if not os.path.exists(file_dir):
        os.makedirs(file_dir)
    f = request.files['file']  # 从表单的file字段获取文件,myfile为该表单的name值
    if f and allowed_file(f.filename):  # 判断是否是允许上传的文件类型
        filename = secure_filename(f.filename)
        ext = filename.rsplit('.', 1)[-1]  # 获取文件后缀
        ran_str = ''.join(random.sample(string.ascii_letters + string.digits, 8))
        new_filename = ran_str + '.' + ext  # 修改了上传的文件名
        f.save(os.path.join(file_dir, new_filename))  # 保存文件到upload目录
        return HOSTNAME + STATIC_URL + time_path + escape(new_filename)
    else:
        return "不支持的文件格式!"


if __name__ == '__main__':
    app.run(debug=True, port=8080)

仅需这些代码就可以搭建一个轻量的图片上传服务器,Flask真香~

接下来就是配置Typora,在图片复制进来的时候自动上传到服务器

在Typora→Preferences→Image→Image Uploader选择Custom Command,同时在When Insert选择Upload image

kwhpUo4f

部署到服务器,接下来我们选择使用脚本来上传,那么就需要一个脚本来对接我们的图片服务器

#!/bin/bash

# 各类配置信息
base_url="https://img.itsso.cool/api/upload/"
access_token="xxxxxxxxxx"

# 上传图片
for i in "$@"; do
    curl -POST $base_url -H "Content-Type:multipart/form-data" -F "file=@$i" -F "access_token=$access_token"
    echo ""
done

点击Test Uploader就可以测试一下我们脚本是否可以正常上传

swQeFOjS

现在来看一下效果如何,复制一张图片到Typora。

LAbunMRk

配置WebHook让远程服务器自动拉取更新代码

所谓webhook,就是用户可以自定义一种回调函数,通过这种回调函数来改变web应用的行为,这些回调函数可以是web应用的开发者,也可以是第三方用户,并且与原始的web应用没有关联。

这里采用的是Flask搭建一个webhook服务,并通过该服务触发脚本来完成整个流程操作

首先在GitHub上开通webhook,并添加secret,选择settings→webhooks

使用Flask搭建一个简易的webhook服务,其中要注意对请求来源做验证,GitHub官方已经提供了验证方法

Note: For backward-compatibility, we also include the X-Hub-Signature header that is generated using the SHA-1 hash function. If possible, we recommend that you use the X-Hub-Signature-256 header for improved security. The example below demonstrates using the X-Hub-Signature-256 header.

接下来就是完整的代码:webhook.py

import hmac
from flask import Flask, request, jsonify
import subprocess

app = Flask(__name__)
# github中webhooks的secret
github_secret = 'xxxxxxxx'

def encryption(data):
    key = github_secret.encode('utf-8')
    obj = hmac.new(key, msg=data, digestmod='sha256')
    return obj.hexdigest()

@app.route('/hook', methods=['POST'])
def post_data():
    """
    github加密是将post提交的data和WebHooks的secret通过hmac的sha256加密,放到HTTP headers的
    X-Hub-Signature256参数中
    """
    post_data = request.data
    token = encryption(post_data)
    # 认证签名是否有效
    signature = request.headers.get('X-Hub-Signature-256', '').split('=')[-1]
    if signature != token:
        return "token认证无效", 401
    # 运行shell脚本,更新代码
    subprocess.run(["bash", "auto_deploy.sh"])
    return jsonify({"status": 200})

if __name__ == '__main__':
    app.run(port=9000)

要触发的脚本文件:auto_deploy.sh

cd "$(dirname "$0")"
echo '--------Git fetch------------'
git fetch
echo '--------Git merge------------'
git merge
echo '-----Already up-to-date------'
echo '----- reload nginx-----'
nginx -s reload

接下来将webhook服务部署好,在项目文件夹下push代码的时候,就会触发该hook,在远程服务器自动将更新的代码拉取下来。

到此为止,用了奇奇怪怪的方法实现了自己奇奇怪怪的想法。

其实现在已经有很多很成熟的静态博客生成器,比如Hugo,Jekyll以及Hexo等等,以前搞过一次,后来网站没了,再加上觉得上传方式并不是那么Geek,也有可能是我没找到一些方便的方法,就直接放弃了。

后来重新搭建网站的时候,就打算干脆直接搭建一个动态的网站,至少很多东西要比静态的灵活方便。

至于现在为什么又变成这样了,那可能是

脑子抽风了吧。

Django批量创建时出现bulk_create内存异常

背景

因为需要往项目数据库上传大量数据,数据是以文件的方式存储,所以采用django的bulk_create批量读取并上传,但是在上传过程中发现,上传程序占用的内存一直在上升,甚至到最后直接把内存占满了。

排查问题

刚开始首先怀疑的就是程序代码有问题导致内存没有释放,自己看没发现什么问题,请教同事帮忙看也没有发现什么问题,所以干脆就硬着头皮去试代码。在每次循环之后都加入gc.collect(),尝试主动释放内存,发现问题仍然存在。

于是开始尝试内存排查工具tracemalloc来排查什么地方一直在增加内存

def batch_insert(filepath):
    tracemalloc.start()
    start_snapshot=tracemalloc.take_snapshot()  # 建立快照
    path = Path(filepath)
    for i, p in enumerate(sorted(path.glob('**/*.json')), start=1):
        with p.open(encoding='utf-8') as f:
            data = json.load(f)
    			... # 内容整理
        with transaction.atomic():
            try:
              	# 批量插入数据库
                Regulation.objects.bulk_create(rules)
            except Exception as e:
                print(e)

        gc.collect()	# 主动释放内存,
       	end_snapshot = tracemalloc.take_snapshot()
        top_stats = snapshot.compare_to(start_snapshot, 'lineno')
        for index, stat in enumerate(top_stats[:50], 1):
            frame = stat.traceback[0]
            print("#%s: %s:%s: %.1f KiB"
                  % (index, frame.filename, frame.lineno, stat.size / 1024))

RFK6GbLQ

ewSJd0CP

发现内存主要的增长是在第一行,而且后面也主要和MySQLdb有关,那么就去看看到底是怎么回事,点开源码在发现django/utils/encoding.py:62

def force_str(s, encoding='utf-8', strings_only=False, errors='strict'):
    """
    Similar to smart_str(), except that lazy instances are resolved to
    strings, rather than kept as lazy objects.

    If strings_only is True, don't convert (some) non-string-like objects.
    """
    # Handle the common case first for performance reasons.
    if issubclass(type(s), str):
        return s
    if strings_only and is_protected_type(s):
        return s
    try:
        if isinstance(s, bytes):
            s = str(s, encoding, errors)
        else:
            s = str(s)
    except UnicodeDecodeError as e:
        raise DjangoUnicodeDecodeError(s, *e.args)
    return s

虽然有注解,但还是不明所以,那最起码看看是谁在调用这个方法总也行吧

grep -nr 'force_str('

发现还不少调用,那就找到关键的信息继续往上追溯

上面那么多虽然都有调用,但是与我们实际的使用情况不符,因为使用的mysql,所以发现红线部分挺符合预期,继续查看代码django/db/backends/mysql/operations.py:171

def last_executed_query(self, cursor, sql, params):
    # With MySQLdb, cursor objects have an (undocumented) "_executed"
    # attribute where the exact query sent to the database is saved.
    # See MySQLdb/cursors.py in the source distribution.
    # MySQLdb returns string, PyMySQL bytes.
    return force_str(getattr(cursor, '_executed', None), errors='replace')

继续查找调用改方法的地方

grep -nr 'last_executed_query('

找到源码django./db/backends/utils.py:113

@contextmanager
def debug_sql(self, sql=None, params=None, use_last_executed_query=False, many=False):
    start = time.monotonic()
  try:
    yield
  finally:
    stop = time.monotonic()
    duration = stop - start
    if use_last_executed_query:
      sql = self.db.ops.last_executed_query(self.cursor, sql, params)
      try:
        times = len(params) if many else ''
        except TypeError:
          # params could be an iterator.
          times = '?'
          self.db.queries_log.append({
            'sql': '%s times: %s' % (times, sql) if many else sql,
            'time': '%.3f' % duration,
          })
          logger.debug(
            '(%.3f) %s; args=%s',
            duration,
            sql,
            params,
            extra={'duration': duration, 'sql': sql, 'params': params},
          )

研究一下代码发现,sql = self.db.ops.last_executed_query(self.cursor, sql, params),在批量上传的时候,会将所有要上传的内容变成一条sql语句,到此为止目前还没发现有什么异常。

但是看到下面这一段,Django将生成的sql语句保存起来,那这个对象会清空之前保存的sql吗?

self.db.queries_log.append({
                'sql': '%s times: %s' % (times, sql) if many else sql,
                'time': '%.3f' % duration,
            })
            logger.debug(
                '(%.3f) %s; args=%s',
                duration,
                sql,
                params,
                extra={'duration': duration, 'sql': sql, 'params': params},
            )

经过Debug发现,是不会的,每生成一条sql就添加到self.db.queries_log里,只要程序没有停止,那么这里边的sql就永远不会消失,所以真相大白,原来就是这个家伙导致的内存一直飙升。

继续向上看,寻找是否存在参数可以选择是否保存这些sql,在django/db/backends/utils.py:97发现这段代码

def execute(self, sql, params=None):
    with self.debug_sql(sql, params, use_last_executed_query=True):
            return super().execute(sql, params)

发现确实存在一个参数use_last_executed_query,但是这个参数已经写死在代码里。。。

尝试修改源码将use_last_executed_query设置为False,运行代码发现问题解决。

后来有尝试将sql语句放入self.db.queries_log这段代码注释掉,运行代码仍然可以解决。

至此已经发现问题的真正根源出在什么地方了,但是通过修改源码的方式总归是不合适的,继续尝试有没有Django自带的方案。经过查找发现django/db/__init.py:26

# Register an event to reset saved queries when a Django request is started.
def reset_queries(**kwargs):
    for conn in connections.all():
        conn.queries_log.clear()

于是尝试在代码中引入该方法

from django.db import reset_queries

...
# 插入数据库之前首先清空
reset_queries()
# 批量插入数据库
Regulation.objects.bulk_create(rules)

发现问题完美的得到解决,完美!

后来在官方文档中发现,已经有这个方法的相关文档

dmTAMrGI

文档中还说只有在DEBUG=True时,这些sql语句才会保存起来以便有需要的时候查看sql。

这也解答了我心中的一个疑问,系统运行时产生的sql为什么要保存起来呢,现在看来是我知识浅薄了。

所以最终这个问题的解决方案有两个:

一、将DEBUG设置为False

二、手动清除,引入django.db.reset_queries

就第一种方案而言,只有在生产环境下,DEBUG选项才会为False,所以在自己的电脑上或者测试机上运行,还是第二种方案比较好。

Elasticsearch相关汇总

在使用Elasticsearch的过程中,难免会要去官网翻看文档,由于目前还没有读完文档,以至于在找一些没用过的API时还挺费劲,有时候甚至还可能找不到。因此就把目前已经用到过的地方在这里汇总记录一下,方便以后碰到的话可以直接去查看。

Index

Aliases

索引的一个别名,在某些情况下非常有用,比如在无缝切换索引的时候。

Mappings

索引的mapping定义十分重要,他决定了我们的数据是如何保存在索引内,以及保存的数据都有什么字段,各个字段的数据类型又是什么。

Setting

Query

Full text queries

全文检索相关,主要包含match querymatch_bool_prefix querymatch_phrase querymatch_phrase_prefix querymulti_match queryquery_string querymatch_bool_prefix querymatch_phrase querymatch_phrase_prefix querymulti_match queryquery_string query

Compound queries

混合索引,包含bool queryboosting queryconstant_score querydis_max queryfunction_score query

Function score query

用户可以通过自定义一个或多个查询语句来提高某些文档的比分权重,

还可以通过script_score使用脚本给每个文档重新打分

Highlight

Prefix query

使用前缀查询可以返回前缀为指定前缀的文档,多用于即时搜索一类的提示。

Match phrase prefix query

当需要对一个短语或词组进行前缀查询时,就需要用到来进行搜索了

Named query

通过使用_name参数可以在多字段查询时知道是哪个子查询语句命中了该文档,并将结果返回在每个响应文档的matched_queries字段内。

Nested query

Exists query

在某些情况下,并不是所有的字段都存在确切的值,可以通过Exists来或者筛选包含某些字段的文档,同时配合must_not可以来筛选所有存在该字段的文档。

Scripts

ES的脚本语言是painless,语法与Java类似,可直接按照Java的语法来编写检索脚本,具体可见地址:Shard API

这里只记录一下自己使用到的,以便以后再遇到可直接CV。

删除数组内满足条件的元素

使用removeIf来完成,例如删除ID为10的元素

{
  "script": {
    "source": "ctx._source.members.removeIf(list_item -> list_item.id == params.member_id)",
    "lang": "painless",
    "params": {
      "member_id": 10
    }
  }
}

判断数组内是否包含某一个对象

使用contains来完成,返回包含name张三的文档

{
  "script": {
    "source": "ctx._source.members.contains(params.name)",
    "lang": "painless",
    "params": {
      "name": "张三"
    }
  }
}

根据时间提高某些文档的权重

使用时间格式化方法toInstanttoEpochMilli来完成,将时间转换成毫秒级权重因子

{
    "script": {
        "lang": "painless", 
        "source": "double dateScore; try {dateScore = Math.abs(doc['enforcementDate'].value.toInstant().toEpochMilli()/1e12);} catch (Exception e) {dateScore=0;} return dateScore;"
    }
}

我不报歉|人间失格

《人间失格》作为著名的“丧”文化代表,其实在读高中的时候就早已耳闻,只不过那时候学校赶的紧,再加上自己也不喜欢看书,就不了了之了。后来随着年纪的增长,虽说已经有大把的时间可以读完这本书,但这时自己又抗拒又害怕那种“丧”,所以也就一直没有去看过。

至于为什么又突然看起来这本书了,可能是最近心情低落,而我又偏喜欢在心情不好的时候找些比较致郁的东西来听或者看,这样反而会觉得有那么一丝愉悦......

断断续续用了将近两天的时间看完,书的内容确实很阴郁,整篇采用第一人称的方式,就好像一个坐在你面前的人,在絮絮叨叨他的一生。

可能是没有什么文学素养,再或者是觉得他人的悲惨与自己无关,总之看的过程很平静,就好像是在观看一场一个人的悲惨演出而已。唯一一次动容的时刻,是在直治自杀之后写给姐姐的遗书里有这一段话。

我早就该死了。只是,唯一让我牵挂不下的便是慈爱的妈妈,想到这个我才没有去死。人,就像享有自由生存的权利一样,也享有决定自己什么时候死的权利,可是我觉得,只要母亲在世,这个死的权利是不得行使的,否则就等于是亲手将自己的母亲杀死。

大概是因为在漫长的阴郁里,突然出现了一抹温柔吧。

其实看到叶藏费尽心思去迎合别人的时候,也好像看到了以前自己的影子。

学着抽烟,因为大家都抽烟

学着打架,因为兄弟们打架不能少了你

学着寒暄扯皮,因为你要嘴皮子玩的溜

不懂拒绝,因为拒绝可能会伤了对方的心

年轻人看到什么书就以为自己是什么样的人,越仔细回想,就越有代入感,幸好以前并没有看这本书。

倘若叶藏可以摒弃自己的懦弱和骄傲,包容自己的不足,他是不是就不会变成那样,包括直治也是。

把他们当作是一部反面教材,鞭策自己,包容自己,活出自我。这样是否也算是这本灰暗阴郁的书的正面意义呢。

最后附上书中的一句话:

一切都会过去的

平庸者的崩坏|绝叫

最近看了一本日本的悬疑推理小说,讲的是一名出生在昭和年代的女人挣扎的前半生,读的过程一度绝望,甚至一度觉得它就是《被嫌弃的阳子的一生》。泡沫经济,失业,大地震,家庭暴力,校园暴力,自杀率攀升等种种因素结合在一起的日本社会,在这样的社会背景下,平庸的普通人只能一步一步的陷入黑暗。

整本书是由三个线路分别同时叙事,同时也保证了结构安排合理,伏笔也埋的不深,所以整体读下来还是比较流畅的。

首先一条线就是以第二人称为叙述方式,仿佛自己就是站在局外人或者是高高在上的审判者的角度一样,评论叙述着铃木阳子的一生,刚开始读的时候还很不习惯,直到最后才觉得这种叙述方式的巧妙之处。

另外一条线是以女警官凌乃的角度来写的,作为这场刑事案件的负责人,对案件进行深入调查之后,发现腐烂在房间的死尸就是铃木阳子。同时在调查的过程中,两个人甚至还有了交集。

最后一条线则是以对一个嫌疑犯八木审讯来记录的,刚开始看的时候会觉得莫名其妙,甚至一度因为他的审讯记录就觉得猜到了结局,其实则不然,这条线感觉更像是一个画外音。

铃木阳子出生在一个重男轻女的家庭,自小都不受家庭重视,甚至连名字都是随便起的。

自从弟弟纯子出生以后,阳子就备受母亲的忽视和否定。当纯子遭受校园暴力自杀之后,可笑的母亲甚至还相信纯子在学校里和其他人相处的很好,对阳子的态度始终如一。

之后日本经济大崩盘,无数人失业自杀,阳子的父亲因为轻信股票可以带来高收益,导致负债上千万,又遇裁员致使失踪。因为阳子父亲的负债导致房子抵押,只好搬出去住,此时的母亲却独自一个人跑去舅舅家住,抛下阳子一个人不管。至此这个家已经完全分崩离析。

之后阳子在当客服之后,遇到了当初暗恋的山崎,俩人成婚之后因为山崎的外遇和失业,又被迫离婚,期间只有两年多的时间。

离婚之后的阳子又当上了保险推销员,在这期间经历了职场PUA,但是缺爱的他却以为上司是对他好,爱上了这个上司。甚至为了他去出卖的自己身体,通过性交易的手段来拉拢客户,去满足上司的要求。

最后阳子虽然发现上司是一个渣男之后,但是他已经无法从这种泥沼中摆脱自我,辞去了保险的工作之后就去做了应召女。在做应召女的过程中,由于身心俱疲,无法辨识牛郎的陷阱,对牛郎的慰问呵护无法自拔。谁能想这个牛郎却也是个烂人,对阳子家暴,无付出一味的索取。

突然有一天阳子下班的时候,被神代和其同伙拖上了车,抢走身上所有的钱财,并且强奸了阳子,阳子一度窒息而亡。此刻的阳子也开始觉醒。

阳子和神代开始计划杀人骗保,第一个对象就是这个牛郎。之后因为这样来钱快,又寻找新的对象开始杀人骗保。阳子已完全堕入深渊。此刻的阳子已经开始反抗,合伙刺杀神代,独自杀害亲母,诱杀朋友,偷梁换柱,整个过程冰冷的像一个机器人一样。

阳子本就是一个平庸的不能再平庸的人了,可奈何时代的灰尘落到普通人的身上竟会像一座山一样,压的人痛苦不堪,只得挣扎绝叫。