交叉编译是现代语言非常有用的特性,本地平台编译目标平台所需的可执行文件或者动态链接库,在没有目标平台编译环境的情况下,依然可以发布我们的程序。正如Golang,Rust也支持交叉编译,不过使用起来比Golang麻烦点。

1、首先介绍下本地编译与交叉编译的概念:

  • 本地编译可以理解为,在当前编译平台下,编译出来的程序只能放到当前平台下运行:比如,我们在Mac Darwin平台上,编写程序并编译成可执行程序。这种方式下,我们使用 Darwin平台上的工具,开发针对Darwin平台本身的可执行程序,这个编译过程称为本地编译;
  • 交叉编译可以理解为,在当前编译平台下,编译出来的程序能运行在体系结构不同的另一种目标平台上,但是编译平台本身却不能运行该程序:比如,我们在Darwin平台上,编写程序并编译成能运行在Linux平台的程序,编译得到的程序在Darwin平台上是不能运行的,必须放到Linux平台上才能运行。

2、下面以Mac上编译Linux程序为例,介绍Rust交叉编译步骤:
(1)安装musl-cross 工具
musl-cross 是用来专门编译到 linux 的工具链

brew install FiloSottile/musl-cross/musl-cross 

(2)查看Rust支持平台

rustup target list

支持的平台非常多

powerpc64le-unknown-linux-gnu
s390x-unknown-linux-gnu
sparc64-unknown-linux-gnu
thumbv7neon-linux-androideabi
thumbv7neon-unknown-linux-gnueabihf
x86_64-linux-android
x86_64-unknown-linux-gnu
x86_64-unknown-linux-gnux32
x86_64-unknown-linux-musl (installed)
...

我们选择x86_64-unknown-linux-musl,后面会用到这个tag。

(3)~/.cargo/config配置参数

[target.x86_64-unknown-linux-musl]
linker = "x86_64-linux-musl-gcc"

(4)安装第三条在config配置的target.x86_64-unknown-linux-musl工具

rustup target add x86_64-unknown-linux-musl

(5)准备源代码进行交叉编译

cargo build --target=x86_64-unknown-linux-musl

编译到其他平台同理!

任务调度是后端重要的组成部分,用于的场景非常广泛,比如生产系统中跑一些定时任务,涉及到上千台机器管理就很困难;Web应用中用户触发的操作比较耗时,这部分可以放到异步任务中处理;离线数据处理多个任务,并且任务间直接有依赖关系...

分布式任务调度通常有以下几类实现方式,一类是基于机器调度的方式,如CT(Contab Task),百度内部是这种方式,定时执行指定机器上的具体指令,通常需要先把任务脚本发布到具体机器,提供给机器调度(worker);第二类如Gearman/Celery,Client将任务发送给Job Server,Server根据后端负载情况,将任务投递到Worker;还有一类是编程框架层面提供的Schedule,功能相对局限,比如只能当前这台机器执行,当前机器挂了,任务也就挂了。

目前自己工作内容涉及到不少离线数据计算,这类任务是基于Python实现,公司内部现用调度系统对非Java支持不完善,而离线任务较多,其中任务间还有依赖关系,使用系统自带的Contab,不管从任务稳定性,还是任务间依赖关系的处理都不完善,最终选择部署Celery集群作为离线任务调度框架。Celery是一个专注于实时处理的任务队列,同时也支持任务调度,配套的任务监控也很完善,可以使用Flower作为可视化监控工具。

- 阅读剩余部分 -

程序性能分析是一个非常庞大的话题,自下而上涉及底层CPU、网络、I/O,上层的业务逻辑复杂度、算法性能等。同时性能分析也是容易被大家忽略的点,往往线上出现问题、服务超时才会着手排查。工欲善其事,必先利其器,本文介绍两种Golang性能分析工具:pprof和torch。

1、pprof
pprof是Golang官方自带的程序性能分析包,可以在net/http/pprofruntime/pprof这两个地方引用,net/http/pprof实际也调用了runtime/pprof,并在http端口上暴露。
(1)服务程序
引入方式如下:

import _ "net/http/pprof"

demo代码如下

package main

import "net/http"
import _ "net/http/pprof"

func main() {
    http.ListenAndServe(":8080", http.DefaultServeMux)
}

然后访问该链接 http://127.0.0.1:8080/debug/pprof/
可以看到当前web服务的状态,包括CPU占用情况和内存使用情况

(2)应用程序
这种场景下需要引入runtime/pprof包,对CPU运行信息进行采样存储,比如

package main

import "runtime/pprof"
import "os"
import "log"

func main() {
    f, err := os.Create("cpu.prof")
    if err != nil {
        log.Fatal(err)
    }
    pprof.StartCPUProfile(f)
    defer pprof.StopCPUProfile()
}

下一步需要使用pprof文件做出性能分析图

go tool pprof test.exe cpu.prof

然后输入web命令生成svg文件,svg用浏览器打开可以看到调用链。如果提示"profile is empty"是由于程序使用了很少的内存,无法进行采样导致,可以修改runtime.MemProfileRate降低采样率,运行前加上环境变量GODEBUG="memprofilerate=1"

- 阅读剩余部分 -

GraphQL是一种用于API的查询语言也是一个满足你数据查询的运行时,GraphQL对你的API中的数据提供了一套易于理解的完整描述,使得客户端能够准确地获得它需要的数据,查询总是返回可预测的结果。

1、REST VS GraphQL
GraphQL目前被认为是革命性的API工具,因为它可以让客户端在请求中指定希望得到的数据,而不像传统的REST那样只能呆板地在服务端进行预定义。下面通过一个例子对比两种API:
(1)REST的核心思想就是资源,每个资源都能用一个URL来表示,你能通过一个GET请求访问该URL从而获取该资源。根据当今大多数API的定义,你很有可能会得到一份JSON格式的数据响应,整个过程大概是这样:

GET /books/1
{
  "title": "Black Hole Blues",
  "author": { 
    "firstName": "Janna",
    "lastName": "Levin"
  }
  // ... more fields here
}

在REST中,一个资源的种类与你获取它的方式是耦合的,比如上面这个例子中的API就可以称之为“book端点”(book endpoint)。

- 阅读剩余部分 -

通常使用Golangencoding/json标准库可以方便的编码/解析JSON数据,但是前提需要定义struct数据结构。特别是解析未知结构的JSON数据时,原有方法很难满足需求了,本文主要介绍动态解析JSON格式。

1、传统方法
比如User数据结构如下:

type User struct {
    Name string `json:"name"`
    Age int     `json:"age"`
}

在定义struct字段的时候,可以在字段后面添加tag,来控制encode/decode的过程:是否要 decode/encode 某个字段,JSON 中的字段名称是什么。字段名首字母控制字段的可见性,若要输出到JSON,首字母需要大写。
三种tag:
-:不要解析这个字段
omitempty:当字段为空(默认值)时,不要解析这个字段。比如 false、0、nil、长度为 0 的 array,map,slice,string
FieldName:当解析 json 的时候,使用这个名字

举例来说吧:

// 解析的时候忽略该字段。默认情况下会解析这个字段,因为它是大写字母开头的
Field int   `json:"-"`
// 解析(encode/decode) 的时候,使用 `other_name`,而不是 `Field`
Field int   `json:"other_name"`
// 解析的时候使用 `other_name`,如果struct 中这个值为空,就忽略它
Field int   `json:"other_name,omitempty"`

- 阅读剩余部分 -