RPCX: 一个用Go实现的类似Dubbo的分布式RPC框架

rpcx是一个类似阿里巴巴 Dubbo 和微博 Motan 的分布式的RPC服务框架,基于Golang net/rpc实现。

谈起分布式的RPC框架,比较出名的是阿里巴巴的dubbo,包括由当当网维护的dubbox。
不知道dubbo在阿里的内部竞争中败给了HSF,还是阿里有意将其闭源了,官方的代码使用的spring还停留在2.5.6.SEC03的版本,dubbox的spring也只升级到3.2.9.RELEASE。
不管怎样,dubbo还是在电商企业得到广泛的应用,京东也有部分在使用dubbo开发。

DUBBO是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,是阿里巴巴SOA服务化治理方案的核心框架,每天为2,000+个服务提供3,000,000,000+次访问量支持,并被广泛应用于阿里巴巴集团的各成员站点。
微博的RPC框架 Motan 也正式开源了,如张雷所说:

2013 年微博 RPC 框架 Motan 在前辈大师们(福林、fishermen、小麦、王喆等)的精心设计和辛勤工作中诞生,向各位大师们致敬,也得到了微博各个技术团队的鼎力支持及不断完善,如今 Motan 在微博平台中已经广泛应用,每天为数百个服务完成近千亿次的调用。

这两个个优秀的框架都是使用Java开发的,国外的互联网企业也有非常出名的的RPC框架如thriftfinagle

本项目rpcx的目标就是实现一个Go生态圈的Dubbo,为Go生态圈提供一个分布式的、多插件的、带有服务治理功能的产品级的RPC框架。

Go生态圈已经有一些RPC库,如官方的net/rpcgrpc-gogorilla-rpc等,为什么还要开发rpcx呢?

原因在于尽管这些框架都是为Go实现的RPC库,但是它们的功能比较单一,只是实现了点对点(End-to-End)的通讯框架。缺乏服务治理的功能,比如服务注册和发现、
负载均衡、容灾、服务监控等功能。因此我基于Go net/rpc框架实现了一个类似Dubbo的分布式框架。

和rpcx比较类似的Go RPC框架是go-micro,但是rpcx提供了更丰富的功能,基于TCP的通讯协议性能更好。

阅读全文

[译]Scala DSL教程: 实现一个web框架路由器

原文: Scala DSL tutorial - writing a web framework router, 作者: Tymon Tobolski

译者按:
Scala非常适合实现DSL(Domain-specific language)。我在使用Scala的过程中印象深刻的是scalatestspray-routing,

比如scalatest的测试代码的编写:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import collection.mutable.Stack
import org.scalatest._
class ExampleSpec extends FlatSpec with Matchers {
"A Stack" should "pop values in last-in-first-out order" in {
val stack = new Stack[Int]
stack.push(1)
stack.push(2)
stack.pop() should be (2)
stack.pop() should be (1)
}
it should "throw NoSuchElementException if an empty stack is popped" in {
val emptyStack = new Stack[Int]
a [NoSuchElementException] should be thrownBy {
emptyStack.pop()
}
}
}

或者 akka-http的路由(route)的配置 (akka-http可以看作是spray 2.0的版本,因为作者现在在lightbend,也就是原先的typesafe公司开发akka-http):

1
2
3
4
5
6
7
8
9
10
11
12
val route =
get {
pathSingleSlash {
complete(HttpEntity(ContentTypes.`text/html(UTF-8)`,"<html><body>Hello world!</body></html>"))
} ~
path("ping") {
complete("PONG!")
} ~
path("crash") {
sys.error("BOOM!")
}
}

可以看到,使用Scala实现的DSL非常简洁,也符合人类便于阅读的方式。但是我们如何实现自己的DSL呢?文末有几篇参考文档,介绍了使用Scala实现DSL的技术,但是本文翻译的这篇文章,使用Scala实现了一个鸡蛋的web路由DSL,步骤详细,代码简单,所以我特意翻译了一下。以下内容(除了参考文档)是对原文的翻译。

阅读全文

更好的Scala I/O: better-files

对于使用Scala的程序员来说, I/O操作如文件的读写通常使用scala.io.Source来实现。但是这个类功能还是欠缺的,而且功能混乱,因此在Scala类库的增强提案(Scala IO fix-up/overhaul)中如何改进它争论相当的大,甚至有些开发者提议将这个库废掉,让社区实现的第三方来完成这方面的工作,或者引导开发者使用java.nio来实现I/O操作。

当然,作为一个使用Scala的公司来说,可能会自己实现了辅助的I/O操作的方法, 比如类似FileUtils等名称的一些类。Java程序员可能已经熟悉了使用java.nio.file.FilesGuavaApache common-iojodd FileUtil等开源I/O库,但是如果使用Scala进行I/O操作时,虽然还是可以使用这些Java I/O库,但是毕竟还是不是那么纯粹,因此,我们可以关注一下Scala实现的I/O库,比如sbt ioAmmonite-Opsbetter-files等。

本文为你推荐better-files

阅读全文

使用WinMerge作为git的Merge工具

我比较喜欢使用免费的WinMerge作为diff和merge工具,虽然TortoiseGit也自己带了TortoiseGitMerge工具,但是使用起来总觉得不是那么方便。

虽然WinMerge项目看起来没人维护了,最后一个发布打分版本在2013-02-02,但是这个工具使用起来还是相当方便的。我在重装机器的时候,或者更新Windows的时候,如果需要配置TortoiseGit,总是需要到网上查找如何配置WinMerge,因为长长的命令参数总是记不起来。所以在本文中记录下来。

阅读全文

更新Maven POM文件中依赖库的版本

维护一个Maven管理的Java项目的时候,有的时候需要更新项目依赖的第三方的库,比如将Spring 3.2.16升级成Spring 4.2.5。我们可以通过Maven versions插件自动化的实现。

这个插件定义了非常多的goal:

  • versions:compare-dependencies compares the dependency versions of the current project to the dependency management section of a remote project.
  • versions:display-dependency-updates scans a project's dependencies and produces a report of those dependencies which have newer versions available.
  • versions:display-plugin-updates scans a project's plugins and produces a report of those plugins which have newer versions available.
  • versions:display-property-updates scans a projectand produces a report of those properties which are used to control artifact versions and which properies have newer versions available.
  • versions:update-parent updates the parent section of a project so that it references the newest available version. For example, if you use a corporate root POM, this goal can be helpful if you need to ensure you are using the latest version of the corporate root POM.
  • versions:update-properties updates properties defined in a project so that they correspond to the latest available version of specific dependencies. This can be useful if a suite of dependencies must all be locked to one version.
  • versions:update-property Sets a property to the latest version in a given range of associated artifacts.
  • versions:update-child-modules updates the parent section of the child modules of a project so the version matches the version of the current project. For example, if you have an aggregator pom that is also the parent for the projects that it aggregates and the children and parent versions get out of sync, this mojo can help fix the versions of the child modules. (Note you may need to invoke Maven with the -N option in order to run this goal if your project is broken so badly that it cannot build because of the version mis-match).
  • versions:lock-snapshots searches the pom for all -SNAPSHOT versions and replaces them with the current timestamp version of that -SNAPSHOT, e.g. -20090327.172306-4
  • versions:unlock-snapshots searches the pom for all timestamp locked snapshot versions and replaces them with -SNAPSHOT.
  • versions:resolve-ranges finds dependencies using version ranges and resolves the range to the specific version being used.
  • versions:set can be used to set the project version from the command line.
  • versions:use-releases searches the pom for all -SNAPSHOT versions which have been released and replaces them with the corresponding release version.
  • versions:use-next-releases searches the pom for all non-SNAPSHOT versions which have been a newer release and replaces them with the next release version.
  • versions:use-latest-releases searches the pom for all non-SNAPSHOT versions which have been a newer release and replaces them with the latest release version.
  • versions:use-next-snapshots searches the pom for all non-SNAPSHOT versions which have been a newer -SNAPSHOT version and replaces them with the next -SNAPSHOT version.
  • versions:use-latest-snapshots searches the pom for all non-SNAPSHOT versions which have been a newer -SNAPSHOT version and replaces them with the latest -SNAPSHOT version.
  • versions:use-next-versions searches the pom for all versions which have been a newer version and replaces them with the next version.
  • versions:use-latest-versions searches the pom for all versions which have been a newer version and replaces them with the latest version.
  • versions:commit removes the pom.xml.versionsBackup files. Forms one half of the built-in "Poor Man's SCM".
  • versions:revert restores the pom.xml files from the pom.xml.versionsBackup files. Forms one half of the built-in "Poor Man's SCM".

也提供了三个reporting goal:

  • versions:dependency-updates-report produces a report of those project dependencies which have newer versions available.
  • versions:plugin-updates-report produces a report of those plugins which have newer versions available.
  • versions:property-updates-report produces a report of those properties which are used to control artifact versions and which properies have newer versions available.

如果你的项目中artifact的版本都是通过属性定义的,那么mvn versions:display-property-updates可以在命令行中显示可以更新的依赖的信息。

你可以手工更改这些依赖的版本,也可以通过mvn versions:update-properties自动更新定义版本的属性。

上面的命令会为你原始的pom.xml产生一个备份文件,如果没有更新问题,你可以通过 mvn versions:commit移除这个备份文件。

在Go web服务器中实现prefork和affinity

Apache服务器可是使用prefork技术,启动多个独立的进程,每个进程独立的处理http请求,不需要担心线程安全的问题。

This Multi-Processing Module (MPM) implements a non-threaded, pre-forking web server that handles requests in a manner similar to Apache 1.3. It is appropriate for sites that need to avoid threading for compatibility with non-thread-safe libraries. It is also the best MPM for isolating each request, so that a problem with a single request will not affect any other.

尽管prefork在处理高并发的情况下并不高效,但是作为一个技术,倒是有启发我们的地方。我最近在调研Go服务器的性能看到一段代码,很优雅的实现了prefork和affinity的的功能,特地抄写在本文中,看看他是怎么实现的。

阅读全文