[翻译]Dropbox Web 服务启用 HTTP/2:经验和观察

Haowei Yuan | 2016年5月11日

最近,为了启用 HTTP/2,我们 Dropbox 的流量团队升级了前端的 Nginx 服务器。本文将分享我们迁移到 HTTP/2 的过程中的体验和新发现。整个过程较为顺利,但还是有发现一些坑,也许对大家有帮助。 继续阅读[翻译]Dropbox Web 服务启用 HTTP/2:经验和观察

[翻译]为什么迁移到 HTTPS 有利于网站统计

2016年06月06日

联邦机构要求将所有联邦网站在 2016 年底前都迁移成只能通过 安全的 HTTPS-only 连接 访问的网站。您也许不知道的是,转换成 HTTPS 后,您网站的引流页面的追踪效果会提升。 继续阅读[翻译]为什么迁移到 HTTPS 有利于网站统计

AngularJS 父子 scope 之间的交流

本文是 《Parent/Child Controller Communication》 的译文。

======译文开始======

我最近经在教很多个朋友 AngularJS,而他们几乎都问了同样一个问题:

如何在 controller 之间传递消息(状态)?

这是个好问题。通常对初学者来说,它不直观。答案比我们想的要复杂(但实现起来很简单)。

有好多方法可以在 controller 之间通信 继续阅读AngularJS 父子 scope 之间的交流

[翻译]修复 Nginx 和 PHP-FPM 之间的超时问题

本文是 《Fixing timeout between Nginx and PHP-FPM》 的译文。

=======译文开始========

若你使用 Nginx 作为 PHP-FPM 的反向代理,且你的 PHP 脚本很复杂或者很慢,需要运行很久,很可能就会看到 504 gateway time-out 错误。这是个很常见的错误,但是大多数情况下人们会找错解决问题的地方,他们不知道怎么找到哪个超时 directive 是正确的、符合他们的情景的。

原文配图:花五小时修复超时程序,不如用一个 directive 立即解决
原文配图:花五小时修复超时程序,不如用一个 directive 立即解决

我看见很多人拼命的试验 proxy_read_timeout, send_timeout, 甚至 client_header_timeout 和client_body_timeout 的 directive,但如果他们瞥一眼 Nginx 的 error_log,会看到一条类似这样的错误:

2013/01/19 11:36:59 [error] 14564#0: *1215 upstream timed out (110: Connection timed out) while reading response header from upstream, client: 123.456.789.123, server: example.com, request: "POST /path/to/some/script.php HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000", host: "example.com", referrer: "http://example.com/"

这条错误清楚的陈述了 Nginx 和 upstream 服务之间的连接超时这件事。在此这个 upstream 服务是 PHP-FPM,但也可以是任何 FastCGI 服务在读响应头时出错。若你据此稍加分析,就不会没找到 fastcgi_read_timeout 这个 directive。浏览文档,看看它是做什么:

设置 upstream 等待 FastCGI 进程发送数据的时长的 directive 。若你有长时间运行、若非结束不输出结果的 FastCGI 进程,修改这个 directive。若你在错误日志中看到 upstream 超时错误,那么增加这个参数到某个更合适的值。

所以,在 http, server 或者 location 的 { 和 } 之间加上这个 directive 并赋予足够高的数值是明智之举,例如:

location ~* .php$ {
include fastcgi_params;
fastcgi_index index.php;
fastcgi_read_timeout 120;
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}

=======译文结束=======

看到这篇文章是因为 www.yymwz.com 国庆期间莫名其妙 504 gateway time-out 了四天,还顺带连累了同一个服务器上的本站一起 504 了。重启服务什么的都不行。搜索了下,叫我用什么 directive 的都有,而且都号称能解决问题,当然总不见效。最后还是按照这篇文章得到解决。修改了 fastcgi_read_timeout 的 directive 以后,mysql 被拖垮了一次,重启后就正常了,昨天那么久只挂了两次,已经好多了。

不过为什么 PHP 脚本会突然超时,博主我依然是百思不得其解的说。待后续吧。

[翻译]简单实现 Angular-UI Bootstrap 的一个 alert service

导语

本文阐述 AngularJS 的 Bootstrap alert service 的简单实现方法,不依赖 jQuery,原文地址 https://coderwall.com/p/r_bvhg本文应该可以看作“一分钟入门 AngularJS Service 开发”,故转载并翻译之。

译文

Angular-UI Bootstrap 提供了不少流行的 Bootstrap 组件的 AngularJS directive(可显著降低代码量)。若您计划在您的 Angular App 中使用任何 Bootstrap 组件,强烈推荐您关注一下。它意味着直接包含 Bootstrap 的组件就能正确运行。 Service 用来在 controllers 之间共享代码。将代码从 controller 移出到 service,alert 是个正面的示例。 The Angular-UI Bootstrap 文档提供了如下例子:

VIEW

<div ng-controller="AlertDemoCtrl">
  <alert ng-repeat="alert in alerts" type="alert.type" close="closeAlert($index)">{{alert.msg}}</alert>
  <button class='btn' ng-click="addAlert()">Add Alert</button>
</div>

CONTROLLER

function AlertDemoCtrl($scope) {
  $scope.alerts = [
    { type: 'error', msg: 'Oh snap! Change a few things up and try submitting again.' }, 
    { type: 'success', msg: 'Well done! You successfully read this important alert message.' }
  ];

  $scope.addAlert = function() {
    $scope.alerts.push({msg: "Another alert!"});
  };

  $scope.closeAlert = function(index) {
    $scope.alerts.splice(index, 1);
  };
}

由于需要在 App 的不同 controller 里创建 alert,而代码在 controllers 之间互相引用又是个不良的编程习惯,所以我们得把它变成一个 service。

alertService

'use strict';

/* services.js */

// don't forget to declare this service module as a dependency in your main app constructor!
var appServices = angular.module('appApp.services', []);

appServices.factory('alertService', function($rootScope) {
    var alertService = {};

    // create an array of alerts available globally
    $rootScope.alerts = [];

    alertService.add = function(type, msg) {
      $rootScope.alerts.push({'type': type, 'msg': msg});
    };

    alertService.closeAlert = function(index) {
      $rootScope.alerts.splice(index, 1);
    };

    return alertService;
  });

View

这些标签也许会在您的 index.html 里,或者从一个头文件被包含过来。

<div>
  <alert ng-repeat="alert in alerts" type="alert.type" close="closeAlert($index)">{{ alert.msg }}</alert>
</div>

最后,我们需要将 alertService 的 closeAlert() 方法绑定到 $globalScope 里。

Controller

function RootCtrl($rootScope, $location, alertService) {
  $rootScope.changeView = function(view) {
    $location.path(view);
  }

  // root binding for alertService
  $rootScope.closeAlert = alertService.closeAlert; 
}
RootCtrl.$inject = ['$scope', '$location', 'alertService'];

我对这个绑定并不完全满意,希望能够直接从 html 标签直接调用这个 service 的 closeAlert 方法,但是还没发现怎么实现。 现在创建一个 alert 只需从任何一个 controller 调用 alertService.add() 即可。

function ArbitraryCtrl($scope, alertService) {
  alertService.add("warning", "This is a warning.");
  alertService.add("error", "This is an error!");
}

任何人有什么改进,请留言。希望此文是篇有用的 Angular.js service 介绍文。

译者:留言里真的有改进和实现方法,译者总结如下:

jwickers:以下代码无须注入到 controller 中就能运行。想从 html 标签中直接调用 closeAlert 方法只需增加一个 close 方法到 alert 对象中。

sur:我也添加了一个 clear 函数到 Alert Service 里面,这样只需调用 AppAlert.clear() 就能一键删掉所有的 alert。

译者:用 $sce 和 ng-bind-html 配合使用,可以使消息支持 html,须包含 AngularJS Router 文件。若不需要可以自行删掉调用了 $sce 的部分,一样可以正常运行。

alertService

.factory('AppAlert', [
      '$rootScope', '$timeout', '$sce', function($rootScope, $timeout, $sce) { 
        var alertService;
        $rootScope.alerts = [];
        return alertService = {
          add: function(type, msg, timeout) {
            $rootScope.alerts.push({
              type: type,
              msg: $sce.trustAsHtml(msg),
              close: function() {
                return alertService.closeAlert(this);
              }
            });

            if (timeout) { 
                $timeout(function(){ 
                    alertService.closeAlert(this); 
                }, timeout); 
            }
          },
          closeAlert: function(alert) {
            return this.closeAlertIdx($rootScope.alerts.indexOf(alert));
          },
          closeAlertIdx: function(index) {
            return $rootScope.alerts.splice(index, 1);
          },
          clear: function(){
            $rootScope.alerts = [];
          }
        };
      }
    ]);

View

<alert ng-repeat="alert in alerts" type="{{alert.type}}" close="alert.close()"><span ng-bind-html="alert.msg"></span></alert>

原文地址

Angular-UI Bootstrap alert service for Angular.js

拓展阅读

Angular.js: service vs provider vs factory?

[翻译]jQuery.isFunction() 和 (typeof variable === “function”) 的区别

通常测试一个 JS 对象是否是函数是这样:
(typeof fn === ‘function’)

然而,它并不总是有效 (IE8):

typeof alert => ‘object’
typeof document.createElement(‘input’).getAttribute => ‘object’

jQuery 1.4 之前也使用 typeof 的方法,但后来的版本修复了这个问题。所以想确定传递的对象确实是函数,使用 $.isFunction :

$.isFunction(function() {}) => true
$.isFunction(alert) => true
$.isFunction(document.createElement(‘input’).getAttribute) => true

附注

angularJS 的 angular.isFunction 用的是 typeof fn === ‘function’ 的方式。

参考

Why jQuery.isFunction?

扩展阅读

Type Checks – JavaScript Style Guide
What’s the difference between (typeof variable === “function”) and jQuery.isFunction()? – Stack Overflow

BAE 2.0 上 wordpress 3.5.2 原版发邮件的方法

注意!!由于 BAE 2.0 已经全面下线,本文内容不再有用!!

本站用的就是最新的原版的 wordpress 3.5.2 。玻璃泉上的 《BAE上原版wordpress发邮件教程》 文章已经说得很清楚了。以下五个步骤是根据此文针对最新 SDK 作出的修改后亲测有效的方法。

1、下载“Bcms.class.php”文件和“lib”文件夹的压缩包,也就是官方的 SDK(来自消息队列的官方文档)。后将它们放入wp-includes目录下。“sample”文件夹不用放进去。

2、接下来,在 wordpress 根目录下的 wp-config.php 文件中加入如下几行(如果已有则不用重复添加):

/* 消息队列 */
define('BCMS_QUEUE','您的消息队列名那一串');
$bcms_host = 'bcms.api.duapp.com';
/* accessKey 和 secretKey 消息队列要用 */
$accessKey = getenv('HTTP_BAE_ENV_AK');
$secretKey = getenv('HTTP_BAE_ENV_SK');

3、然后打开 wp-includes 下的 pluggable.php 文件,查找

if ( !function_exists( 'wp_mail' ) ) :

在它的上一行添加如下代码:

/**
* BAE Send Mail
* BCMS
*/
if ( !function_exists( 'wp_mail' ) ) :
function wp_mail( $to, $subject, $message, $headers = '', $attachments = array() ) {
require_once ABSPATH . WPINC . '/Bcms.class.php';
$bcms = new Bcms ( $accessKey, $secretKey, $bcms_host) ;
$ret = $bcms->mail ( BCMS_QUEUE, $message, array($to), array( Bcms::MAIL_SUBJECT => $subject)) ;
if ( false === $ret ) {
return false;
} else {
return true;
}
}
endif;

4、这样就行了,可以正常发出来自 BCMS 的电子邮件了。发出的邮件不出意料的落在的垃圾邮件文件夹里:

用 BAE BCMS 发出的 wordpress 重设密码邮件用 BAE BCMS 发出的 wordpress 重设密码邮件

5、Bcms 的 class 不能重复定义。BAE 环境中已经内置了一些定义,所以把报重定义 Fatal Error 的 PHP 文件内的内容全部注释掉即可。

最后,距离前文提到的《BAE上原版wordpress发邮件教程》 撰文的 2012-11-15 已经过去了一年半多,可以看到现在本文代码中调用 BCMS 的方法和那时的已经略有不同,需要 $accessKey 和 $secretKey 和指定 $bcms_host。

BCMS 的 SDK 也许将来还会再作修改,到时应该以官方的 SDK 里的 sample.php 的方法为准。

6、BAE 2.0 的 BCMS 服务有配额,配额里发邮件次数用完了就不能再发邮件了。据 BAE 客服回复,BAE 3.0 可以直接发邮件,不需要 mail 服务。有条件的可以往 BAE 3.0 (收费) 迁移,就省去这个麻烦了。

[汉化] Organize Series 中文语言包

Organize Series 是一个 Wrodpress 插件,和它的名字一样,“系列组织者”,其免费版本可以用来将成系列的文章独立于标签和分类,组织起来。Organize Series  可以设置每篇文章的序号。而且,Organize Series  还能自动在连载文章页加上导航链接,加上同一系列连载的文章列表导航,并提供全站通用的连载小工具挂件等。其付费扩展包更提供许多高级的功能。

为了给 www.yymwz.com 做一个全中文的后台,本人决定汉化网站上安装的 Organize Series ,点此下载 .mo 文件,并上传到 Organize Series 插件的 lang 目录下,即可生效。汉化后效果如下图所示。

image

image

 

欢迎协助翻译和帮忙纠错,请点击此链接 http://organizeseries.com/translating-organize-series/

Github上搭建自己的个人博客

1、前提

你需要注册一个github的帐号,并登陆到github.com。这样就到达了你的个人首页。

2、开始创建自己的blog

  1. 然后点New repository创建一个新的repository,命名为:yss.github.com(这里的yss为你在github上的用户名,下面涉及到的用户名也以yss为例)
  2. 进入这个仓库:yss.github.com,点击偏右上角的Admin,进入Admin页面
  3. 找到下面的灰色按钮,名为:Automatic Page Generator
  4. 进入到上面这个页面后,点右下角的continue to Layouts。则进入了模板选择页面。
  5. 然后选择一个模板,点public按钮即可(偏右上角的位置)。
  6. 这样就可以访问你的github博客了~

3、后话

github博客还有很多扩展性的东西,有待后续去了解,去学习。

当然这是最最基本的搭建自己个人的github博客。

后期基于jekyll搭建了自己的博客:yansong.me。算是做了回所谓的用黑客的方式写博客~~

4、扩展性阅读及参考

http://pages.github.com/

https://help.github.com/categories/20/articles