Google Code Review Guide

  1. 原则:给出技术上的建议,而不是个人偏好
  2. 写一个好的 commit:
    1. 第一行,改动的简短摘要
    2. 空行
    3. 详细提交信息
  3. 小修改,多提交
    1. 方便 review/merge/roll back
    2. 利于好的代码设计,减少 bug
  4. Code review 看什么?
    1. 设计
    2. 功能实现是否正确,以及复杂度
    3. 测试
    4. 命名,注释,代码风格,文档等
  5. 尽早 review,尽快 review
  6. 好的 code review comment
    1. Be kind
    2. 只指出问题,让开发人员自己决定怎么修改
    3. Encourage developers to simplify code

如何写出优雅的 Golang 代码

原文是一篇非常赞的工程总结,推荐。这里记录一些笔记

  1. 代码规范,gofmt, goimports, golangci-lint 等,配合 CI 自动化
  2. 目录结构 Standard Go Project Layout
    1. /pkg 可以被外部使用包模块
    2. /internal 私有模块,不可被外部使用
    3. 不要有 /src 目录
    4. /cmd 生成可执行文件
    5. /api 对外提供的 API 模块
    6. 不要有 model/controller 这样的模块,按照职责拆分,面向接口开发
  3. 不要在 init 做资源初始化,比如 rpc/DB/Redis 等,因为 init 会被隐式执行,会默默初始化资源连接
  4. 推荐的做法是 Client + NewClient,显式初始化连接
  5. init 阶段适合做一些简单、轻量的前置条件判断,比如 flag 设置
  6. 使用 GoMock/sqlmock/httpmock/monkey 做 mock + 测试

Simple techniques to optimise Go programs 介绍了一些简单却非常高效的性能提升方法:

  • Avoid using structures containing pointers as map keys for large maps, use ints or bytes
  • Use strings.Builder to build up strings
  • Use strconv instead of fmt.Sprintf

Power of g in Vim

:[range]g[!]/pattern/cmd

! means do not match pattern, cmd list:

  • d: delete
  • m: move
  • t: copy, or co
  • s: replace

for more info:

动态添加/删除 Hadoop DataNode

添加节点

  1. NameNode 添加节点 etc/hadoop/slaves
  2. 同步 etc/hadoop 配置
  3. 在新节点 ./sbin/hadoop-daemon.sh start datanode

删除节点

  1. etc/hadoop/excludes 写入要删掉的节点地址
  2. 修改 etc/hadoop/ hdfs-site.xml:
  <property>
    <name>dfs.hosts.exclude</name>
    <value>/home/web/hadoop/etc/hadoop/excludes</value>
  </property>
  1. 修改 etc/hadoop/mapred-site.xml, 这个是下线 nodemanager
  <property>
    <name>mapred.hosts.exclude</name>
    <value>/home/web/hadoop/etc/hadoop/excludes</value>
    <final>true</final>
  </property>
  1. 修改 etc/hadoop/slaves,去掉要删除的节点
  2. 同步 etc/hadoop/excludesetc/hadoop/slaves 到所有 NameNode
  3. 在 NameNode 执行 ./bin/hadoop dfsadmin -refreshNodes
  4. ./bin/hadoop dfsadmin -report 查看要删除的节点状态变化 Normal -> Decommission in progress -> Decommissioned
  5. 在要删除的节点 ./sbin/hadoop-daemon.sh stop datanode,等待 Admin State 变更为 Dead

Using special SSH key for Git

In ~/.ssh/config:

host github.com
    HostName github.com
    IdentityFile ~/.ssh/id_rsa_github
    User git

don’t forget chmod 600 ~/.ssh/config

Or, use GIT_SSH_COMMAND environment variable:

export GIT_SSH_COMMAND="ssh -i ~/.ssh/id_rsa_example -F /dev/null"

Regex Unicode Scripts

  1. \p{Han} 匹配中文、日语文字,支持简繁体。
  2. \p{Common} 匹配符号
  3. \p{Latin} 匹配拉丁语系
  4. 需要 grep perl 支持,即 grep -P "\p{Han}",或者 rg/ag.
echo '中文/繁體/片仮名/かたかな/カタカナ/katakana' | rg "\p{Han}"   > 中文 繁體 片仮名
echo '中文@mail.com' | rg "\p{Common}"                                > @ .
echo '中文@mail.com' | rg "\p{Latin}"                                 > mail com

Unicode Scripts for more.

Octotree for Safari

brew install [email protected]
export PATH="/usr/local/opt/[email protected]/bin:$PATH"
# make sure node and npm is v10, cause octotree used gulp 3, which is not working with node 12.

git clone https://github.com/ovity/octotree.git ~/src/octotree
cd ~/src/octotree
git checkout master

npm i
npm install [email protected]
npm run dist
# extension locate in ~/src/octotree/tmp/safari/octotree.safariextension/

cd ~/Library/Safari/Extensions
mv ~/src/octotree/tmp/safari/octotree.safariextension .
  1. Enable Developer menu in Safari
  2. Developer - Show Extension Builder
  3. Add octotree.safariextension and Run

MySQL Prefix Index

CREATE TABLE `t1` (
  `bundle` varchar(300) DEFAULT '' COMMENT 'pkg name',
  `domain` varchar(200) DEFAULT '',
  UNIQUE KEY `idx_bundle_domain` (`bundle`(100),`domain`(100))
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4;

关键部分 bundle(100) 来解决组合索引可能会出现的 Specified key was too long; max key length is 767 bytes 错误。

Deployment with git

#!/bin/sh

set -uex

PATH=$PATH:$HOME/bin
export PATH

DIR=/home/serv/project
cd ${DIR}

REV1=$(git rev-parse --verify HEAD)
git pull origin master
REV2=$(git rev-parse --verify HEAD)
test ${REV1} = ${REV2} && echo "Already updated" && exit

make
test $? -ne 0 && echo "make error" && exit

kill -HUP $(cat logs/run.pid)

主要是通过 git rev-parse --verify HEAD 来获取当前 rev hash,前后对比是否一致,以此来决定是否继续。

logrotate

logrotate - rotates, compresses, and mails system logs

# 0 0 * * * /usr/sbin/logrotate --state=/home/serv/logrotate.state /home/serv/logrotate.log.conf
/home/serv/logs/dev.log
/home/serv/logs/access.log {
    rotate 10
    daily
    compress
    create
    copytruncate
    missingok
    dateext
    dateformat -%Y-%m-%d
    dateyesterday

    sharedscripts
    postrotate
        kill -USR1 `cat /var/run/nginx.pid`
    endscript
}
  1. 要么保存到 /etc 配置,由系统调度。也可以自己通过 crontab 调度控制,这种情况要注意加 --state 来保存状态
  2. 像 nginx 可以通过 kill -USR1 来重新打开日志文件,如果服务不支持可以用 copytruncate,先拷贝再清空