致我所深爱着的世界

使用 Nginx 反代并缓存动态内容

因为着实没想到一个皮肤站竟然会有这么大的并发(好吧其实也不大,QPS 大概 50 左右),所以我之前 开发/部署 Blessing Skin Server 的时候是完全没考虑到缓存优化的。直到后来出现了 神秘的高并发(QPS 上 200)导致皮肤站宕机我才意识到缓存的重要性。

我到现在也还是搞不懂那到底是正常流量还是 CC 攻击。。难道正常用户会每秒请求 20+ 次 Json Profile 吗?又不是天天退/进游戏玩 emotion

虽然当时我就花了一点时间给 Json Profile 和皮肤预览之类的地方 加上了缓存,但是由于这些缓存方案都是在 Laravel 层之上的,所以框架的性能依旧是硬伤。试了下 Stone
之类的优化措施也没什么卵效果,再加上我学业也忙了起来,这个问题就被搁置了。

正好最近国庆放假(虽然只有四天),我就抽了点时间出来研究了一下如何给我的皮肤站套一层缓存 ( ・_ゝ・)

> READ MORE...

String.prototype.endsWith() 的浏览器兼容性问题

String.prototype.endsWith() 这个方法是 ECMA6 新加入的,而我当初随手 Google 了一下,也没怎么看就直接用上去了,直到我今天在一台破手机上测试的时候发现有个用到这个方法的值神秘地变成了 undefined ( ´_ゝ`)

我记得上次好像也是这样随手搜索导致使用了不兼容的函数 ( -д-) 论面向搜索引擎编程的坏处

不过我们还是可以通过扩展 String 的原型来实现在不支持的浏览器上使用这个方法:

/**
 * 代码来自 MDN
 * 
 * @link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith
 */

if (!String.prototype.endsWith) {
  String.prototype.endsWith = function(searchString, position) {
      var subjectString = this.toString();
      if (typeof position !== 'number' || !isFinite(position) || Math.floor(position) !== position || position > subjectString.length) {
        position = subjectString.length;
      }
      position -= searchString.length;
      var lastIndex = subjectString.lastIndexOf(searchString, position);
      return lastIndex !== -1 && lastIndex === position;
  };
}

使用 Laravel 的 RedirectResponse 重定向至任意 URL

Laravel 允许我们在控制器中返回一个 Illuminate\Http\RedirectResponse 的实例来执行重定向。根据文档,我们可以通过 redirect() 帮助函数或者 Redirect Facade 来生成实例,并且可以方便得重定向至命名路由、控制器行为等。

但如果我们想要重定向至自定义 URL 呢?

对于这样的需求,Laravel 官方的文档是完全没有提及的(至少到目前 5.3 是这样),所以估计很多人都是自己实现了一个使用 header() 或者 <meta http-equiv='Refresh' content=''> 的重定向函数(包括以前的我)。

> READ MORE...

使用 Certbot 自动签发 Let's Encrypt 证书

今晚一回来就看到 Google Search Console 给我发了封邮件说我站点上的 SSL 证书过期了。我上去一看还真是,这张我从 Andy 手里买来的通配符证书已经在昨天失效了。

唉,时间也是过得忒快啊,转眼间一年就过去了,我也成为了苦逼的高三党,真是惨得不行 ( ・_ゝ・)

不过正好,我从 之前就一直在关注 Let’s Encrypt 这个项目了,这次正好试试看它好不好用。

> READ MORE...

Sublime Text 3 主题推荐 —— Boxy

BOXY

用了好久的 Predawn,打算换个 Theme 和 Color Scheme 试试。在网上逛了一段时间后,我找到了一个很不错的 ST3 主题,这里分享一下:

Boxy Theme

The most hackable theme for Sublime Text 3

这个主题在 Package Control 上的页面在这里,这是一个非常强大的主题,你可以去看看它的介绍视频。

Boxy 提供了很多自定义选项,因此你甚至可以把 Sublime 打扮成 Atom、VS Code,甚至是同为 ST 主题的 Predawn/Material 的样式,简直碉堡了好吗:

Screenshot

> READ MORE...

又是一种用于 JavaScript 的前端国际化方案

现在 Blessing Skin Server 的 HTML 模板是使用 Laravel 自带的本地化来实现多语言支持的,并且使用了 devitek/yaml-translation 这个包把 Laravel 语言文件从默认的 PHP 数组形式改为 YAML 格式的文件。

不得不说数组形式的语言文件简直反人类好吗,一大堆 => 看的眼晕。。YAML 大法好!(ゝ∀・)

回到正题。虽然 HTML 模板里的国际化是解决了,但是整个应用中需要国际化的地方可不止 HTML 模板,同时还有 JavaScript。但是静态的脚本文件中总不能内嵌 PHP 吧,所以我们得搞个单独的解决方案。

虽然说网上现成的 JS 国际化的库很多,但我总觉得有些看不上眼(可能是我没找到好的),就准备自己实现一下。

> READ MORE...

自定义 Laravel Validator 所返回的响应

不得不说 Laravel 的 Validation 是极好的,非常易于使用,麻麻再也不用担心我要写一大堆验证啦 ~( ^ω^)

但是这个 Validator 有一个神秘的地方 ( -д-),正如官方文档所说,它会自动判断当前请求是否为 Ajax 发送的,如果是,则在验证失败的时候返回一个 JsonResponse 响应而不是 RedirectResponse 响应。

但是,这个 JSON 响应的状态码,是 422。

WTF!坑爹呢这是!要知道 422 这个状态码是通不过 jQuery.ajax.success 的啊!

在网上找了一圈,愣是没找着什么好一点的解决方法(全是叫你在 $.ajax.failed 里处理错误的)。

> READ MORE...

使用 Laravel 的 监听者模式实现缓存机制的松散耦合

唔,我也不知道我接下来要讲的东西是不是配得上这个题目,总之就是分享一下我在搞 Blessing Skin Server 的缓存与插件机制时的一些经验(大佬们就请忽略吧)

既然要实现松散耦合的缓存机制,那就是要做到有没有缓存都没事。有缓存的话就走缓存,然后那边的模块内部实现一个包括过期时间呀啥啥的缓存机制,没有收到缓存模块的响应的时候就继续走原来的应用逻辑,一样可以正常响应。

因为我们是要实现应用逻辑与缓存逻辑的解耦,所以正常应用逻辑内是不能有对那些缓存的依赖的。那么我们要通过什么来和缓存模块通信呢?巧的是,Laravel 正好提供了基于 Event 和 Listener 的观察者模式,我们就可以用这种设计模式来解耦缓存模块。

> READ MORE...

使用 Laravel 的服务容器来优化读写数据库中的 options

这篇文章应该算是心得体会一类的吧,因为并没有什么卵用(笑

就像前两篇文章说的一样,在我把项目框架改为 Laravel 后,自然要最大限度地利用 Laravel 的特性来提升我们应用的性能(虽然使用 Laravel 本身就是在降低性能了),并且让我们的代码看起来更优雅 装逼

其中我们可以最方便地利用的一个特性就是 Laravel 的服务容器了。在这里我不多赘述 Service Container 是个啥,想了解的可以自行搜索。不想了解的就只要大致知道它是个可以 绑定/取出 实例的东西就好了(当然服务容器可不止这么点功能)。

相信很多 Web 应用都会在数据库建立一个 options 表来储存一些用户的配置信息,而为了方便,我们通常会封装一个 Option 类来方便地进行数据的 getset 操作。而通常的做法是把这些操作做成类内静态方法来调用。

但是这样的弊端就是每一次的操作都要去查询数据库,这对于性能还是有挺大影响的,尤其是在一次响应中要使用很多 options 的情况下。

> READ MORE...