Monday, September 26, 2016

第二届区块链峰会随记

上周(9.19-9.24)在上海参加了第二届区块链全球峰会。
整体感觉,整个产业已经上升到一个新的阶段了,开始有一些落地的项目,不再只是呼吁概念。

天下大势,三分已成

币圈和链圈渐行渐远,而目前区块链领域从技术实现上已经逐渐划分为三大阵营:以太坊、超级账本和其它。
以太坊(Ethereum):开源阵营。由 VB 同学带领的以太坊团队牵头开发。草根出身,自然受到很多个人开发者的喜爱,相关的客户端、环境支持也比较完善。不少欧洲的创业项目(Consensus 投资了不少)都是基于以太坊的平台来搭建,但普遍规模较小。
超级账本(HyperLedger):开源阵营 + 企业支持。由 Linux 基金会组织团队开发。科技界和金融界的巨头们牵头支持,自然受到各大企业的青睐。不少机构给的对区块链平台的需求和设计,基本可以理解为对超级账本白皮书的解读,包括隐私保护、可审计、安全、插件化的共识等都是超级账本的基本特性。SWIFT 也刚跳出来支持超级账本阵营。更多信息可以查看 这里
其它方案:包括各种开源、非开源的方案。以创业团队居多。百花齐放百家争鸣是好事情,但是可惜自己真的从头做的很少,这也挺正常,毕竟区块链领域相关技术门槛确实比较高。少数几个号称从头做、有底层技术的又不开源,这在如今是一件挺可惜的事情。
个人感觉,区块链产业要想做大,至少在基础设施这一层需要尽快的成熟和规范,这对大家都有好处。Linux、Web Server 这样的开源方案出来被大家认可后,才有了整个互联网的繁荣。

通用平台 vs 专用平台

除了对通用平台的讨论,开始有人意识到专用平台的重要性。
之前不少人喜欢用传统数据库的需求来质疑区块链。实际上区块链技术跟数据库完全是两个领域的事情,解决的不同的问题。如果某个业务场景真的需要特定的功能,则应该结合业务层从一开始就设计支持,而不是所有需求都堆到底下。
大胆预测,未来可能出现专门面向各个领域的专用区块链平台:金融区块链、物联网区块链、众筹区块链……,类似不同的 Linux 发行版。
只有这样,才能真的说区块链落地了。

应用场景

应用场景仍然是五花八门,开始有一些关注到具体实际的问题。
比如解决个人的资产登记问题、跨境资金、分布式电商平台,大部分也都是之前就耳熟能详的。但有些推出了新一代的解决方案,还是有不少亮点的。
对应用来说,技术层面反而要弱化,好的商业模式、对市场的把握、对当地政策的解读往往都是决定性的因素。
从目前来看,明后两年将会出现应用的大爆发,特别是国内市场。

BaaS 将成为短期内热点

随着 IBM、微软、Google 等宣布退出 BaaS 业务,将有更多的云服务商会追随这一趋势。
目前来看,基于 HyperLedger 的 BaaS 有相对成熟的解决方案。

Friday, August 12, 2016

ProtoBuf 与 gRPC 你需要知道的知识

ProtoBuf 是一套接口描述语言(IDL)和相关工具集(主要是 protoc,基于 C++ 实现),类似 Apache 的 Thrift)。用户写好 .proto 描述文件,之后使用 protoc 可以很容易编译成众多计算机语言(C++、Java、Python、C#、Golang 等)的接口代码。这些代码可以支持 gRPC,也可以不支持。
gRPC 是 Google 开源的 RPC 框架和库,已支持主流计算机语言。底层通信采用 gRPC 协议,比较适合互联网场景。gRPC 在设计上考虑了跟 ProtoBuf 的配合使用。
两者分别解决的不同问题,可以配合使用,也可以分开。
典型的配合使用场景是,写好 .proto 描述文件定义 RPC 的接口,然后用 protoc(带 gRPC 插件)基于 .proto 模板自动生成客户端和服务端的接口代码。

ProtoBuf

需要工具主要包括:
  • 编译器:protoc,以及一些官方没有带的语言插件;
  • 运行环境:各种语言的 protobuf 库,不同语言有不同的安装来源;
语法类似 C++ 语言,可以参考 语言规范
比较核心的,message 是代表数据结构(里面可以包括不同类型的成员变量,包括字符串、数字、数组、字典……),service代表 RPC 接口。变量后面的数字是代表进行二进制编码时候的提示信息,1~15 表示热变量,会用较少的字节来编码。另外,支持导入。
默认所有变量都是可选的(optional),repeated 则表示数组。主要 service rpc 接口只能接受单个 message 参数,返回单个 message;
syntax = "proto3";
package hello;

message HelloRequest {
  string greeting = 1;
}

message HelloResponse {
  string reply = 1;
  repeated int32 number=4;
}

service HelloService {
  rpc SayHello(HelloRequest) returns (HelloResponse){}
}
编译最关键参数是指定输出语言格式,例如,python 为 --python_out=OUT_DIR
一些还没有官方支持的语言,可以通过安装 protoc 对应的 plugin 来支持。例如,对于 go 语言,可以安装
$ go get -u github.com/golang/protobuf/{protoc-gen-go,proto} // 前者是 plugin;后者是 go 的依赖库
之后,正常使用 protoc --go_out=./ hello.proto 来生成 hello.pb.go,会自动调用 protoc-gen-go 插件。
ProtoBuf 提供了 Marshal/Unmarshal 方法来将数据结构进行序列化操作。所生成的二进制文件在存储效率上比 XML 高 3~10 倍,并且处理性能高 1~2 个数量级。

gRPC

工具主要包括:
  • 运行时库:各种不同语言有不同的 安装方法,主流语言的包管理器都已支持。
  • protoc,以及 grpc 插件和其它插件:采用 ProtoBuf 作为 IDL 时,对 .proto 文件进行编译处理。
官方文档 写的挺全面了。
类似其它 RPC 框架,gRPC 的库在服务端提供一个 gRPC Server,客户端的库是 gRPC Stub。典型的场景是客户端发送请求,同步或异步调用服务端的接口。客户端和服务端之间的通信协议是基于 HTTP2 的 gRPC 协议,支持双工的流式保序消息,性能比较好,同时也很轻。
采用 ProtoBuf 作为 IDL,则需要定义 service 类型。生成客户端和服务端代码。用户自行实现服务端代码中的调用接口,并且利用客户端代码来发起请求到服务端。一个完整的例子可以参考 这里
以上面 proto 文件为例,需要执行时添加 grpc 的 plugin:
$ protoc --go_out=plugins=grpc:. hello.proto

生成服务端代码

服务端相关代码如下,主要定义了 HelloServiceServer 接口,用户可以自行编写实现代码。
type HelloServiceServer interface {
        SayHello(context.Context, *HelloRequest) (*HelloResponse, error)
}

func RegisterHelloServiceServer(s *grpc.Server, srv HelloServiceServer) {
        s.RegisterService(&_HelloService_serviceDesc, srv)
}
用户需要自行实现服务端接口,代码如下。
比较重要的,创建并启动一个 gRPC 服务的过程:
  • 创建监听套接字:lis, err := net.Listen("tcp", port)
  • 创建服务端:grpc.NewServer()
  • 注册服务:pb.RegisterHelloServiceServer()
  • 启动服务端:s.Serve(lis)
type server struct{}

// 这里实现服务端接口中的方法。
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
    return &pb.HelloReply{Message: "Hello " + in.Name}, nil
}

// 创建并启动一个 gRPC 服务的过程:创建监听套接字、创建服务端、注册服务、启动服务端。
func main() {
    lis, err := net.Listen("tcp", port)
    if err != nil {
        log.Fatalf("failed to listen: %v", err)
    }
    s := grpc.NewServer()
    pb.RegisterHelloServiceServer(s, &server{})
    s.Serve(lis)
}
编译并启动服务端。

生成客户端代码

生成的 go 文件中客户端相关代码如下,主要和实现了 HelloServiceClient 接口。用户可以通过 gRPC 来直接调用这个接口。
type HelloServiceClient interface {
        SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloResponse, error)
}

type helloServiceClient struct {
        cc *grpc.ClientConn
}

func NewHelloServiceClient(cc *grpc.ClientConn) HelloServiceClient {
        return &helloServiceClient{cc}
}

func (c *helloServiceClient) SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloResponse, error) {
        out := new(HelloResponse)
        err := grpc.Invoke(ctx, "/hello.HelloService/SayHello", in, out, c.cc, opts...)
        if err != nil {
                return nil, err
        }
        return out, nil
}
用户直接调用接口方法:创建连接、创建客户端、调用接口。
func main() {
    // Set up a connection to the server.
    conn, err := grpc.Dial(address, grpc.WithInsecure())
    if err != nil {
        log.Fatalf("did not connect: %v", err)
    }
    defer conn.Close()
    c := pb.NewHelloServiceClient(conn)

    // Contact the server and print out its response.
    name := defaultName
    if len(os.Args) > 1 {
        name = os.Args[1]
    }
    r, err := c.SayHello(context.Background(), &pb.HelloRequest{Name: name})
    if err != nil {
        log.Fatalf("could not greet: %v", err)
    }
    log.Printf("Greeting: %s", r.Message)
}
编译并启动客户端,查看到服务端返回的消息。

Docker 1.12 Swarm 模式剖析

Docker 1.12 在 2016 年 7 月 28 日正式 GA,除了大量的在使用上的改进和 bug 修复外,最引人瞩目的是原生支持了 Swarm 模式。
熟悉 Docker 的读者都知道 Docker Swarm 是官方三剑客之一,提供了轻量级容器云的支持,以性能卓越出名,跟 K8s 面向应用的较为复杂的容器云方案一时瑜亮,各有千秋。
本次 Swarm 模式特性的发布可谓重要变革,不仅仅是减低使用门槛那么简单,还引入了不少新的围绕应用的特性,从中可以一探 Docker 团队对于容器云的理念。

基本概念

Swarm 定义为一组合作在一起的 Docker 主机集群,由节点组成,每个节点都是一个独立的 Docker 主机。
集群中包括两种节点:管理节点和工作节点。参考 k8s 的结构,也是如此。
  • 管理节点:负责对任务进行调度和其它管理任务,多个管理节点通过 Raft 协议组成集群;
  • 工作节点:负责运行具体的任务,管理节点可以同时作为工作节点。
如果把所有节点配成管理+工作,那就是绝对的对等了,实际上从性能角度考虑,管理节点数量不宜过多,并且相互之间的互联网络要保证好的质量。
此外,还引入了服务的概念。服务也包括两种类型:
  • 复制服务(replicated services):类似 k8s 中复制集的概念,保持一定数量的相同任务在集群中运行;
  • 全局服务(global services):类似 k8s 中 daemon 的概念,每个工作节点上运行一个。
一个服务由多个任务组成,一个任务即一个运行的容器。

主要特性

负载均衡和服务地址管理

k8s 中让人印象深刻的是它的服务自带了负载均衡和服务地址功能,Swarm 也通过 ingress load balancing (基于 ipvs 的四层代理)来实现,为每一个服务提供一个 DNS 地址,维护一个公共的端口。这点上跟 k8s 默认方式略有不同,但效果是一致的,都保证了无论容器如何变化,任意节点对应用的访问保持不变。

跨主机网络

这点还是基于 overlay 网络来实现。

监控管理

基于服务的概念,对运行状态进行管控,自动保持服务的运行状态。

支持命令

目前围绕对集群和服务进行管理,命令都很容易理解。
  • swarm init
  • swarm join
  • service create
  • service inspect
  • service ls
  • service rm
  • service scale
  • service ps
  • service update

Swarm2k

很有意思的项目,就是基于最新的 Swarm 模式来在全球范围内构建一个超过 2000 个节点,1 M 个容器的大集群。
目前已经达到预定目标,具体可以关注 [这里](https://github.com/swarm2k/swarm2k/blob/master/PROPOSAL.md)。
这个项目的成功,也再次证明官方的 Swarm 方案,在性能上确实首屈一指!

小结

跟 Docker 技术自身的火爆不同,Docker 团队一直以来就面临着未来发展的困境,几乎所有人都希望他们只安心做好容器引擎。但作为一个商业化公司来说,这样下去毫无疑问是自掘深坑。于是,他们积极的在基于容器的各种平台和工具上进行构建。包括三件套、包括容器云,都是很好的尝试。
从 Swarm 的特性来看,Docker 团队在应用为中心这点上是认同了 K8s 的理念的,但是自身又同时保持了一定的独立性。这对于 Docker 来说自然是利好。但是目前来看,并没有完全解决团队发展的困境。

Saturday, June 25, 2016

区块链的七年之痒

关于区块链的探讨和争论从未停息。
或许从计算技术的演变历史中能得到一些启发意义。


上图是笔者在某次交流会中提出的。
以云计算为代表的现代计算技术,发展历史上有若干重要的时间点和事件:
  • 1969 - ARPANet(Advanced Research Projects Agency Network):现代互联网的前身,被美国高级研究计划署(Advanced Research Project Agency)提出,其使用 NCP 协议,核心缺陷之一是无法做到和个别计算机网络交流;
  • 1973 - TCP/IP:Vinton.Cerf(文特•瑟夫)与Bob Karn(鲍勃•卡恩)共同开发出 TCP 模型,解决了 NCP 的缺陷;
  • 1982 - Internet:TCP/IP 正式成为规范,并被大规模应用,现代互联网诞生;
  • 1989 - WWW:早期互联网的应用主要包括 telnet、ftp、email 等,蒂姆·伯纳斯-李(Tim Berners-Lee)设计的 WWW 协议成为互联网的杀手级应用,引爆了现代互联网,从那开始,互联网业务快速扩张;
  • 1999 - salesforge:互联网出现后,一度只能进行通信应用,但 salesforge 开始以云的理念提供基于互联网的企业级服务;
  • 2006 - aws ec2:AWS EC2 奠定了云计算的业界标杆,直到今天,竞争者们仍然在试图追赶 AWS 的脚步;
  • 2013 - cognitive:以 IBM Watson 为代表的认知计算开始进入商业领域,计算开始变得智能,进入“后云计算时代”。
从这个历史中能看出哪些端倪呢?
一个是 技术领域也存在着周期律。 这个周期目前看是 7 年左右。或许正如人有“七年之痒”,技术也存在着七年这道坎,到了这道坎,要么自身突破迈过去,要么往往就被新的技术所取代。如果从比特币网络上线(2009 年 1 月)算起,到今年正是在坎上。因此,现在正是相关技术进行突破的好时机。
为何恰好是七年?七年按照产品周期来看基本是 2-3 个产品周期,所谓事不过三,经过 2-3 个产品周期也差不多该有个结论了。
另外,先出现的未必是先驱,也可能是先烈。 创新固然很好,但过早播撒的种子,没有合适的土壤,往往也难长大。技术创新与科研创新很不同的一点便是,技术创新必须立足于需求,过早过晚都会错失良机。科研创新则要越早越好,最好像二十世纪那批物理巨匠们一样,让后人吃了一百多年的老本。
最后,事物的发展往往是延续的、长期的。 新生事物大都不是凭空蹦出来的,往往是解决了前辈未能解决的问题,或是出现了之前未曾出现过的场景。而且很多时候,新生事物会在历史的舞台下面进行长期的演化,只要是往提高生产力的正确方向,迟早会有出现在舞台上的一天。

Thursday, June 02, 2016

区块链需要关注的应用场景

区块链最近几年炒得很热,国内已有大量与之相关的企业,有些企业已经结合已有业务摸索出了自己的应用场景,但仍有不少企业处于不断试探和反复迷惑状态。
从技术角度讲,区块链涉及到的领域比较杂,包括分布式、存储、密码学、心理学、博弈论、网络协议等,要一下子完全理解确实不太容易。
甚至有人简单将区块链技术归结到分布式数据库的范畴,误导了对其的正确理解。
实际上,要找到合适的应用场景,还是要从区块链自身的特性出发进行分析。
从技术特点上,区块链具有:
  • 分布式容错性:网络极其鲁棒,容错 1/3 左右节点的异常状态。
  • 不可篡改性:一致提交后的数据会一直存在,不可被销毁或修改。
  • 隐私保护性:密码学保证了未经授权者能访问到数据,但无法解析。
随之带来的业务特性包括:
  • 交易成本:设计恰当的区块链应用可以控制每笔交易的成本更低,不需要第三方中介机构。
  • 维护成本:跟传统技术相比,区块链网络维护成本更低,适用环境更多。
  • 安全隐私:直接为终端用户提供一定程度的安全保障和隐私保护。
区块链并非凭空诞生的新技术,更像是技术演化到一定程度突破应用阈值后的产物,因此,其应用场景也跟促生其出现的环境息息相关。
未来几年内,可能深入应用区块链的场景将包括:
  • 征信管理:这是大型社交平台和保险公司都梦寐以求的,目前还缺乏足够的数据来源、可靠的平台支持和有效的数据分析和管理。该领域创业的门槛极高,需要自上而下的推动。
  • 社区资源共享:airbnb 为代表的公司将欢迎这类应用,极大降低管理成本。这个领域创业门槛低,主题集中,会受到投资热捧。
  • 金融交易:主要是降低交易成本,减少跨组织交易风险等。该领域的区块链应用将最快成熟起来,银行和金融交易机构将是主力推动者。
  • 投资管理:无论公募还是私募基金,都可以应用区块链技术降低管理成本和管控风险。虽然有 DAO 这样的试水,谨慎认为该领域的需求还未成熟。
  • 物联网:物联网是很适合的一个领域,短期内会有大量应用出现,特别是租赁、物流等特定场景。但物联网自身的发展局限将导致短期内较难出现规模应用。