通过 git clone 命令默认拉取的是 git repo master 分支代码。

git clone git@git.kangkai.art:xxx/xxx.git

如果需要拉取非 master 分支则需要如下操作。

Solution

  1. 查看远程分支
git branch -r
  1. 查看所有分支
git branch -a 

* master
  henry-dev
  transform_face_attr
  remotes/origin/henry-dev
  remotes/origin/master
  remotes/origin/transform_face_attr
  1. 切换并拉取 henry-dev 分支
git checkout origin/henry-dev
  1. Done!

Classic Solution

传统的方法则是创建一个新的本地分支并指向远程分支,或者想要修改正在跟踪的上游分支。

  1. 我们首先需要在本地先建立一个分支,建议名称和远程的想要同步的分支名称一样
git branch henry-dev
  1. 切换到新建的本地分支
git checkout henry-dev
# Switched to branch 'henry-dev'
  1. 接下来需要建立上游分支的关联
git branch --set-upstream-to=origin/henry-dev henry-dev
# Branch henry-dev set up to track remote branch henry-dev from origin.
  1. 拉取该远端分支的最新代码
git pull
  1. Done!

四种常见的 POST 提交数据方式

HTTP/1.1 协议规定的 HTTP 请求方法有 OPTIONS、GET、HEAD、POST、PUT、DELETE、TRACE、CONNECT 这几种。其中 POST 一般用来向服务端提交数据,本文主要讨论 POST 提交数据的几种方式。

我们知道,HTTP 协议是以 ASCII 码传输,建立在 TCP/IP 协议之上的应用层规范。规范把 HTTP 请求分为三个部分:状态行、请求头、消息主体。类似于下面这样:

<method> <request-URL> <version>
<headers>

<entity-body>

协议规定 POST 提交的数据必须放在消息主体(entity-body)中,但协议并没有规定数据必须使用什么编码方式。实际上,开发者完全可以自己决定消息主体的格式,只要最后发送的 HTTP 请求满足上面的格式就可以。

但是,数据发送出去,还要服务端解析成功才有意义。一般服务端语言如 php、python 等,以及它们的 framework,都内置了自动解析常见数据格式的功能。服务端通常是根据请求头(headers)中的 Content-Type 字段来获知请求中的消息主体是用何种方式编码,再对主体进行解析。所以说到 POST 提交数据方案,包含了 Content-Type 和消息主体编码方式两部分。下面就正式开始介绍它们。
Continue reading

小时候家里管得严不让我过早接触网络和计算机,所以我第一次接触编码还是那句熟悉的九宫格手机键盘口令*#220807#,在我的印象中那是一个比 symbian 更加广阔的天地,极弱的算力和有限的内存却支撑起了众多优秀的应用程序。

最近在做一个非常 hacker 的一个项目,通过采集区域监控摄像视频流,通过 CV 算法分析获取结构化数据,然后上报到服务端进行比对和分析,最终实现区域监控无人值守高效运转,其上可以包装的产品还有很多,想想就觉得很兴奋。

Full-time 写各类软件代码已经一年多,这次又可以接触到硬件并去攻略他,唤醒了我血液中流淌着的 Hacker 基因。

0x00 Architecture

一个完整的智能监控网络需要包括 ‘Edge – Server – Frontend’ 这三块组件。

  1. Edge:边缘设备,包括 cam,nvr 及其他智能采集及分析设备;
  2. Server: 宏观上包含各类 S3对象存储,kafka消息队列,MQTT长连接等服务端云产品和 CDN 内容分发网络等第三方服务;
  3. Frontend: 前端大屏,后端系统稳定性和数据完整性展现的重要载体,一般还需要配合产品设计实现数据展示及各类不同场景下的视频流播放。

Continue reading

我带的实习生要开始搞 fpm 的落地和实现了,为了更加优雅的完成这个工具,整个 rpmbuild – Test – Beta – Production 生命周期充斥着各类异步场景。

0x00 Promise in Node.js

这段时间写大屏用 Node.js 积累了一些网络和文件操作上使用异步编程的经验,一般简单场景使用回调方式就能很好的解决问题,但当遇到比较复杂的逻辑时,为了避免 Callback Hell 的问题的,异步接口更好的处理办法就是使用 Promise 接口。

let promisify = (fn, receiver) => {
  return (...args) => {
    return new Promise((resolve, reject) => {
      fn.apply(receiver, [...args, (err, res) => {
        return err ? reject(err) : resolve(res);
      }]);
    });
  };
};

var fs = require("fs");
var readFilePromise = promisify(fs.readFile, fs); // Encapsulate Promise interface

readFilePromise("foo.json", "utf8").then(function(content){
    // normal
}).catch(function(err){
    // abnormal
})

题外话,JavaScript 从 ES8 开始支持基于 Promise 的 Async/Await 语法糖, 实现类似 Golang 协程采用同步方式写异步代码。

Continue reading

最近听了 IoT 长连接 Erlang 研发同学的技术分享,部分分享内容涉及到到了 HTTP/2,刚好在草稿箱里翻到了两年前攒的这篇文章,趁这个机会补充一下把他放出来吧。

HTTP/2 不叫 HTTP/2.0,是因为标准委员会不打算再发布子版本了,下一个新版本将是 HTTP/3。

0x00 HTTP Frames

HTTP/1.1 版的头信息肯定是文本(ASCII编码),数据体可以是文本,也可以是二进制。HTTP/2 则是一个彻底的二进制协议,头信息和数据体都是二进制,并且统称为”帧”(frame):头信息帧和数据帧。

HTTP/2 相较于 HTTP/1.* 的不同点在于,HTTP/2 将 HTTP 协议通信分解为二进制编码Frame的交换,这些Frame对应着特定Stream中的Message。所有这些都在一个 TCP 连接内复用。这是 HTTP/2 协议所有其他功能和性能优化的基础。

二进制协议的一个好处是,可以定义额外的帧。HTTP/2 定义了近十种帧,为将来的高级应用打好了基础。如果使用文本实现这种功能,解析数据将会变得非常麻烦,二进制解析则方便得多。

Frame 的基础结构由五部分组成:

  • Length: 表示 Frame Payload 的大小,是一个 24-bit 的整型,表明 Frame Payload 的大小不应该超过 2^24 – 1 byte,但其实 payload 默认的大小是不超过 2^14 byte,可以通过 SETTING Frame 来设置 SETTINGS_MAX_FRAME_SIZE 修改允许的 Payload 大小;
  • Type: 表示 Frame 的类型,目前定义了 0-9 共 10 种类型;
  • Flags: 为一些特定类型的 Frame 预留的标志位,比如 Header, Data, Setting, Ping 等,都会用到;
  • R: 1-bit 的保留位,目前没用,值必须为 0;
  • Stream Identifier: Steam 的 id 标识,表明 id 的范围只能为 0 到 2^31 – 1 之间,其中 0 用来传输控制信息,比如 Setting, Ping;客户端发起的 Stream id 必须为奇数,服务端发起的 Stream id 必须为偶数;并且每次建立新 Stream 的时候,id 必须比上一次的建立的 Stream 的 id 大;当在一个连接里,如果无限建立 Stream,最后 id 大于 2^31 时,必须从新建立 TCP 连接,来发送请求。如果是服务端的 Stream id 超过上限,需要对客户端发送一个 GOWAY 的 Frame 来强制客户端重新发起连接。

Continue reading

昨晚快下班的时候,蓝色港湾那家影院的客服小哥给我打电话说我们预定的那个包场被取消了,心态有点炸。今早到公司重新规划了路线,终于把周五 Building 的全套行程都确定下来了,明天消费升级改道去国贸。

中午有小姐姐来找我说他们新员工培训抽到了‘持续创新’的主题,打算把我做 AI 沟通助手的过程拍成一部 VCR,于是我们很愉快的聊了下研发细节,话说上次涉足演艺圈事业已经是快一年前的事了,明少当时约了一票好友一起造了一晚上,记得那时候坐我左手边的姑娘气质特别好,唱霉霉的歌也特有感觉。


转眼间接口开放平台野蛮生长了很长一段时间了,一直没有一个很正式的测试环境,每次做新需求都是从 git 上把代码拉下来重新起套新环境,这里面存在很多坑,比如 Python3 版本升级之后 virtualenv 中的 mysql 依赖就装不上了

ModuleNotFoundError: No module named 'ConfigParser'

查阅相关文档之后发现在 Python3 版本升级后,ConfigParser.py 已经更名为 configparser.py 了,可以同前版本的处理办法一样,通过重命名解决问题,但是路子太野会给之后上量扩容满坑,所以得找找其他办法。

https://github.com/PyMySQL/PyMySQL

于是我找到了 mysql 的替代模块 PyMySQL,

pip3 install PyMySQL

如果还有报错,那么:

# Ubuntu
sudo apt-get install libmysqlclient-dev

# CentOS
sudo yum install python-dev mariadb-devel

PyMySQL 的玩儿法也更加优雅,特别对于多条数据的处理逻辑也更加线性易于理解。Continue reading

在做大屏可视化展示的时候,需要把大数据收敛聚合接口提供的数据以三个 Pie 图的形式展示在屏幕下方正中。

Burst of Celestial Fireworks

Screen Preview

下面就是我使用 Node 完成样式构造的 demo:

const StyledDivAllinline = styled.div`
text-align:center;
margin:0 auto;
padding:0;
clear:both;
`
// `inline-block` effect
const StyledSubdivAllinline = styled.div`
margin:0;
padding:0;
display:inline-block;
_display:inline;
*display:inline;
zoom:1;
`
// render
<StyledDivAllinline>
  <StyledSubdivAllinline>
    Hello, world
  </StyledSubdivAllinline>
  <StyledSubdivAllinline>
    HELLO, World
  </StyledSubdivAllinline>
  <StyledSubdivAllinline>
    Hail, Hydra
  </StyledSubdivAllinline>
</StyledDivAllinline>

Burst of Celestial Fireworks

Burst of Celestial Fireworks

你永远无法识别由潜意识制造的假象。

我们的视野中本该有一块无法避免的黑斑,

对应视网膜上视神经的位置,

大脑却像裱糊一样将它均匀填补了。

到底哪里是假的呢?

–MorningRocks

SpaceX's Falcon 9 Rocket / NASA

SpaceX’s Falcon 9 Rocket / NASA

We live in a time when information is readily accessible in the palm of ours hands.

So do YOURSELF a favor – Never stop learning. Something small or something big. Doesn’t matter. Just never Stop.

— Wykrhm