爬虫的终极形态:nightmare

nightmare 是一个基于 electron 的自动化库(意思是说它自带浏览器),用于实现爬虫或自动化测试。相较于传统的爬虫框架(scrapy/pyspider),或者dom操作库(cheerio/jsdom),或者基于浏览器的自动化框架(selenium/phantomjs),他的优势在于提供了一个简洁有效 的编程模型。

来看官网给出的一个对比场景:

同样是实现一个向yahoo自动提交关键词并搜索的功能

1. PhantomJS实现

2. nightmare实现
[crayon-5beaff5836[……]

阅读全文

实现一个Node.js版本的Consul SDK

Consul

Consul 是一个开源软件,用于实现分布式系统的服务发现与配置,内置如下功能:

  • 服务的注册和发现
  • 键值对存储
  • 健康检查
  • 多数据中心支持

Node-Consul

目前实现最为完备的 Consul 客户端是 node-consul,看看它的功能点:

  • ACL: 访问控制
  • Agent: 检查/服务注册
  • Health: 健康信息获取
  • Catalog: 目录列表
  • KV: 键值对存取
  • Event: 发送事件与列表
  • Query: 查询服务信息
  • Status: Raft一致性的状态信息

Too much,超出了需求范[……]

阅读全文

漫谈元编程

咬文嚼字

meta-programming(a.k.a.元编程) 中的这个 meta-词前缀源自希腊词,本意为“在…后,变换,以上”。经过几千年的演进,这个词前缀有了一种全新的意义:关于事物自身的事物。比如 meta-knowledge 就是“关于知识本身的知识”,meta-data 就是“关于数据的数据”,meta-language 就是“关于语言的语言”,而 meta-programming 也是由此而来,是“关于编程的编程”。

元编程

元编程算不上什么新鲜的概念,各种语言里早已有之:

  • C和Lisp系语言里的宏
  • C++里的模板
  • Java的注解
  • C#的属性和反射
  • [……]

阅读全文

Akka Streams: Using TCP

引子

准确来说,IO API 不算是 Akka Streams的内容,但它却是 Streaming IO (TCP) 的基础。

IO API 编程的第一步,是获取一个管理对象的引用。比如我们想针对TCP编程,可以这么获取 TCP Manager:

manager 是一个 actor 对象,用于处理底层 I/O资源和操作(诸如channels/selectors,或是workers的初始化),同时对于上层提供基于actor 模型的抽象

IO TCP

IO TCP 编程也是 CS 模型的,好处是不需要写繁琐的 S[……]

阅读全文

Akka Streams: Integrating with Actors

引子

Akka Streams 为异步编程提供了管道和流式接口,但如果我们希望结合 actor 模型的消息机制呢?Akka Streams提供了如下解决方案:

  • Sink.actorRef 产生 ActorRef,做为下游结点接收管道里的流数据
  • Source.actorRef 产生ActorRef,能被下游结点消费
  • Source.ActorPublisher 产生ActorRef,用于实现Reactive Streams中的Publisher
  • Sink.ActorSubscriber 产生ActorRef,用于实现Reactive Streams中的Subscriber[……]

阅读全文

Akka Streams: GraphStage

Stages

Stage 是 Akka Streams 里的核心概念,它代表了在Graph里的单位,是如何定义输入端口(Inlet)  / 输出端口(Outlet) 的;常用的基础形态有:

compose_shapes1

  • Source: 只有一个Outlet
  • Sink: 只有一个Inlet
  • Flow: 只有一个Outlet和一个Inlet
  • Fan-In: 多个Inlet一个Outlet
  • Fan-Out: 一个Inlet多个Outlet
  • BidiFlow: 双向通道,一对Inlet一对Outlet

有了这些基础件,我们可以按需组合出各种拓扑的图来:
runnable_graph1

自定义流处理

之前介绍过[……]

阅读全文

Akka Streams: pipelines

Reactive Streams

reactive streams 是一个异步流标准,Akka项目是这个标准最早的实现者之一。

标准定义了两个通道:

  • publisher为上游生产者通道
  • subscriber为下游消费者通道

reactive_stream标准要求这两个通道间的通信是异步非阻塞的,并且是基于反压模式(back pressure)的——数据是从publisher流向subscriber的,但数据一次发送多少个elements是由subscriber通过request(n)来告诉上游的,这使得流可控。同时,这也使得流在处理过程中的合并与拆分成为可能:

split_and_merge_streams

akka-stream[……]

阅读全文

Akka in action: Let it crash

Akka 在容错方面有如下特点:

  • 分区容错(local & remote),错误隔离
  • Actors 基于策略进行监督和恢复
  • 在错误解决前,失效的Actor 可被挂起,转由系统代收消息(Dead Letter),并在恢复时继续之前的消息处理

Akka 对于错误的观点值得称道:没有银弹,还是着眼于如何进行灾后重建吧 🙂

Let it crash

与传统应用将 业务逻辑和 try {} catch{}错误处理 绞在一起不同,Akka 的容错恢复是独立于业务逻辑的:Actors专注于自己的消息处理逻辑,而错误处理和策略设定,则由层 级结构里,它的监督者(父级Acto[……]

阅读全文

Akka in action: actor model

引子

最近在学习 Akka,因为Scala的新版本已将Actors迁移到Akka [1](教材就是那本烂到一定程度的 Akka in action,排版字体代码示例一如既往的Manning式的糟糕)——至于为什么要学习Actors,大概是因为 红宝书 里提出了一些对异步编程组合子的设计要求。

Akka

官方定义:

Akka is a toolkit and runtime for building highly concurrent, distributed, and resilient message-driven applications on the JVM.

做为一个消息驱[……]

阅读全文

RingBuffer in scala

是什么?

ring_bufferRingBuffer (环形缓冲区),是一种用于表示一个固定尺寸、头尾相连的缓冲区的数据结构,适合缓存数据流(用来实现轮转功能的日志也很合适)。

它亦是一个队列,先进先出(FIFO)。这意味着,入队永远是在环的尾部(tail),出队永远是在环的头部(head)。这个环的容量是一开始就确定的,那么不停变换的,是头尾两个指针:入队驱动tail,出队驱动head,在环上单向轮转。

性能优势

我们可以将RingBuffer实现为一个不停覆盖尾部的版本, 以提供一种高性能的有限无锁队列:

  • 它使用数组,比链表要快,且基于一个可预测的访问模式(数组内元素的内存地址 具有连续性[……]

阅读全文