QCon全球软件开发大会8折优惠倒计时,购票立减¥1760!了解详情 >>> 了解详情
写点什么

借助 JArchitect 探究 Cassandra CLI 内部机制

2014 年 2 月 10 日

关系型数据库管理系统(RDBMS)是存储和使用数据最常用的系统,但对于超大量数据,这些数据库的扩展性不是很好。

近年来,由于对关系型数据库替代产品的需求日益增长, NoSQL 的概念已经受到广泛的欢迎。NoSQL 背后的最大动机是可扩展性。NoSQL 数据库解决方案提供了一种存储和使用超大量数据的方法,而且开销更小,工作量更少,性能更好,停机时间更短。

Apache Cassandra 是一个基于列的 NoSQL 数据库。它是 Facebook 为推动其收件箱搜索功能而开发的,后来成为 Apache 的开源项目。 Twitter Digg 、Reddit 及其他许多组织都已经开始使用它。

Cassandra 本身提供了一个非常基础的交互式命令行接口(CLI)。开发人员可以使用 CLI 连接到集群中的远程节点,创建或更新模式以及设置和检索记录。

对于 Cassandra 管理员而言,CLI 是一个有用的工具。即使只提供了基础的命令,它也是一个很好的例子,从中可以知道如何实现 Cassandra 客户端。要开发自定义的 Cassandra 客户端甚至是扩展 CLI 工具,必须得了解 CLI 的内部工作原理。

本文将使用 JArchitect 工具和 CQLinq 语言分析 CLI 的代码库,以探究 CLI 的架构模型。JArchitect 工具用来分析代码结构,并指定设计原则,以获得更好的代码质量。借助 JArchitect,软件质量可以用代码度量进行测量,用“图(graph)”和“树图(treemap)”进行可视化,并用标准和自定义的规则来执行。

下面是分析得出的依赖关系图:

Cassandra 使用了若干大家熟知的 jar 包,如 antlr、log4j、slf4j、commons-lang,也使用了若干大家不怎么知道的 jar 包,比如下面这些:

  • Libthrift :它是一个跨多种编程语言和用例的 API,其目标是尽可能高效和无缝地实现跨语言通信和数据序列化的可靠性和高性能。
  • Snakeyaml :YAML 是一个为人工可读性和与脚本语言交互而设计的数据序列化格式。Cassandra 的配置文件用了这一格式。
  • Jackson :一个高性能 JSON processor。
  • Snappy :它是一个用 C++ 编写的快速压缩 / 解压缩程序,最初由 Google 开发,snappy-java 是其 Java 版本。
  • High-scale-lib :它是一个并发和高扩展性实用程序的集合,其目的是为了直接取代包 java.util.* 或者 java.util.concurrent.* 中的集合类,而当许多 CPU 并发使用集合时性能更好。

下图的矩阵图是对这些 JAR 文件之间依赖权重的更为详细的说明。

Cassandra**** 命令行接口

包 org.apache.cassandra.cli 实现了命令行接口逻辑,入口是 CliMain 类。

使用下面的 CQLinq 查询查找 main 方法调用的方法:

复制代码
from m in Methods where m.IsUsedBy
("org.apache.cassandra.cli.CliMain.main(String[])")
select new { m, m.NbBCInstructions }

Main 方法用了 JLine ,这是一个处理控制台输入的 Java 库。通过它,开发人员不需要太费力就可以写出很棒的 CLI 应用程序。它对命令历史、Tab 键自动补全、行编辑、自定义键绑定以及字符屏蔽提供了开箱即用的支持。

以下是 main 方法用到的两个有趣的方法:

  • connect:该方法用于连接 Cassandra 数据库服务器。
  • processStatetementInteractive:该方法用于执行来自用户的命令。

CLI**** 与 Cassandra 服务器之间的通信

在与 Cassandra 服务器进行交互之前,客户端必须使用 connect 方法连接到服务器。

下面的查询查找 connect 方法直接或间接使用的所有方法:

复制代码
from m in Methods
let depth0 = m.DepthOfIsUsedBy("org.apache.cassandra.cli.CliMain.connect
(String,int)")
where depth0 >= 0 orderby depth0
select new { m, depth0 }

CLI 使用 Thrift 库与服务器进行通信,Thrift 允许开发人员用一个简单的定义文件定义数据类型和服务接口。将这个文件作为输入,编译器会生成代码,开发人员可以用这些代码轻松地构建 RPC 客户端和服务器,从而实现跨编程语言的无缝通信。无需编写大量的样板代码来序列化和传输对象以及调用远程代码,开发人员就可以马上开始处理业务。

下面是 Thrift 服务器实现的一个简单例子:

Thrift 服务器实现了 org.apache.thrift.server.TServer 接口,其构造函数接收一个 processor 和一个服务器传输规范类的实例作为参数。Processor 需要一个 handler 来处理传入的请求。

让我们在 Cassandra 服务器中找出所有的这些组成部分。为了做到这一点,我们可以从找出所有继承了 TServer 类的类开始。

复制代码
public class Server {
public static class SomethingHandler implements Something.Iface {
public SomethingHandler() {}
public int ping() {
return 1;
}
}
public static void main(String [] args) {
SomethingHandler handler = new SomethingHandler();
Something.Processor processor = new Something.Processor(handler);
TServerTransport serverTransport = new TServerSocket(9090);
TServer server = new TSimpleServer(processor, serverTransport);
// 下面的语句适用于多线程服务器
// server = new TThreadPoolServer(processor, serverTransport)
server.serve();
}
}

Thrift 服务器实现了 org.apache.thrift.server.TServer 接口,其构造函数接收一个 processor 和一个服务器传输规范类的实例作为参数。Processor 需要一个 handler 来处理传入的请求。

让我们在 Cassandra 服务器中找出所有的这些组成部分。为了做到这一点,我们可以从找出所有继承了 TServer 类的类开始。

复制代码
from t in Types
let depth0 = t.DepthOfDeriveFrom("org.apache.thrift.server.TServer")
where depth0 >= 0 orderby depth0
select new { t, depth0 }

Cassandra 定义了如下类:

CustomTThreadPoolServer:它是 Apache Thrift 类 TThreadPoolServer 的一个稍作修改的版本。TThreadPoolServer 类会使用一个线程池为传入的请求提供服务。

CustomerTHsHaServer:该服务器的目的是避免 IO 粘在一个 CPU 上。为了获得更大的吞吐量,它将 IO 任务分配给多个线程。Selector 线程的数目可以与可用的 CPU 数目相同。

CustomTNonBlockingServer:它使用一个非阻塞的套接字传输方式。

以下是 ThriftServer 启动时所做的工作:

该过程会使用工厂类创建一个 TServer,并创建一个 CassandraServer handler 来处理传入的请求,后者实现了 Cassandra.Iface 接口,其中包含了 Cassandra 支持的所有命令。下图展示了该接口的部分方法:

正如前面的 Thrift 服务器示例所示,需要用 processor 处理传入的请求;所有这些 processor 都继承了 ProcessFunction 类。

下面是部分 Cassandra processor:

在找出 Cassandra Thrift 服务器的组成部分之后,让我们回到客户端,找出 main 方法调用 connect 方法时发生了什么。

org.apache.thrift.TServiceClient用于客户端和服务器之间的通信,它调用 sendBase 方法向 Thrift 服务器发送消息。

在服务器上,login processor 接收这一请求,并调用 login 方法。

下面的依赖关系图展示了 login 方法调用的部分方法。

下面会通过添加一个新方法 MyMethod 进入到扩展 CLI 的步骤。

在查明 CLI 的内部工作原理之后,我们可以很容易地给它添加新方法,下面是所需的主要步骤:

I- 扩展服务器:

  • Cassandra.Iface接口中添加方法
  • CassandraServer类中添加该方法的实现
  • 新建一个继承ProcessFunction的类Cassandra.Processor.MyMethod
  • Cassandra.Processor.getProcessMap方法返回的 Map 中添加上一步中新建的 processor 的一个实例。

II- 扩展客户端:

  • 新增一个开关项,并在CliOptions.processArgs方法中对其进行处理。
  • Cassandra.Client类中添加一个方法,并使用TServiceClient.sendBase方法向服务器发送请求。

结论

学习如何实现 Cassandra 客户端,命令行接口是一个很好的例子,而且从现实项目中学习要好过只是在网上搜索例子。因此,要开发 Cassandra 客户端的话,就要毫不犹豫地仔细阅读它的源代码,并享受其中的乐趣。

关于作者

Dane Dennis是 JArchitect 产品经理。他为 CoderGears 工作,这是一家为开发人员和架构师开发工具的公司。

查看英文原文:**** Cassandra CLI Internals Using JArchitect

2014 年 2 月 10 日 07:331562
用户头像

发布了 256 篇内容, 共 69.0 次阅读, 收获喜欢 6 次。

关注

评论

发布
暂无评论
发现更多内容

TRTC代码示例文档集合完毕!哪里不会点哪里!

腾讯云音视频

腾讯云 API sdk 实时音视频 音视频开发

企业安全运维重点是什么?如何做?

行云管家

数据库 运维 企业管理 企业运维 安全运维

面试官:你了解JVM的锁优化吗?

百度开发者中心

Java 最佳实践 方法论 语言 & 开发

2021Java大厂面试集合,java多线程

策划Java工程师

Java 程序员 后端

2021年五面蚂蚁,从单体到分布式,必须解决的四个问题

策划Java工程师

Java 程序员 后端

啃书一年多的我,推荐Python初学者不要在乱看书了,有这三本就妥妥的

冇先生

编译脚本:编写CMakeFile(一)

正向成长

CMakeFile

从河南暴雨、疫情反弹看区块链“灾疫”治理

CECBC区块链专委会

基于 Apache APISIX,新浪微博API网关的定制化开发之路

Apache APISIX 中国社区

Apache 网关 APISIX 微博

双非本化学跨专业,投岗阿里/滴滴后端三面,最终拿下offer

编程菌

Java 编程 程序员 面试 计算机

2021最新Java面试真题解析!1

策划Java工程师

Java 程序员 后端

Linux 网络管理技术 OSI 七层模型和 TCP/IP 四层模型

学神来啦

Linux 运维 IP

ironSource 在 2021 ChinaJoy 举办多场活动赋能中国开发者

Geek_459987

Python代码阅读(第2篇):数字转化成列表

Felix

Python 编程 Code Programing 阅读代码

【最不佳实践】Serverless应用优化四则

刘宇

Serverless 优化

频繁出现的分布式拒绝服务 (DDoS) 攻击​,有什么办法可以抵御吗?

九河云安全

下一个颠覆的领域:区块链如何影响审计行业?(下)

CECBC区块链专委会

防火墙 Keepalived 异常双活恢复后部分外网访问中断问题分析

Qunar技术沙龙

运维 防火墙 网络 故障诊断 keep-alive

2021Java笔试题总结!Java个人学习之旅(第十天)

策划Java工程师

Java 程序员 后端

2021Java面经:Android屏幕适配-重点盘点

策划Java工程师

Java 程序员 后端

FastApi-04-请求体-1

Python测试和开发

FastApi 8月日更

2021年Java开发实战!仿微信的网络聊天室项目开发【完整源码讲解

策划Java工程师

Java 程序员 后端

API网关在API安全性中的作用

互联网架构师小马

gitlab无法通过ssh拉代码

阿呆

#GitLab

关于Spring注解开发教程,打包全送你

华为云开发者社区

Java spring 容器 注解 组件

Hologres揭秘:深度解析高效率分布式查询引擎

阿里云大数据AI技术

2021Java春招面试真题详解,Git-如何优雅地回退代码

策划Java工程师

Java 程序员 后端

2021年Java知识体系总结,部门老大:redis-分布式锁再这么用

策划Java工程师

Java 程序员 后端

当企业遭遇分布式拒绝服务 (DDoS) 攻击时,第一时间该如何进行操作?

九河云安全

Java代码中,如何监控Mysql的binlog?

互联网架构师小马

区块链技术如何有效应对气候变化

CECBC区块链专委会

移动应用开发的下一站

移动应用开发的下一站

借助JArchitect探究Cassandra CLI内部机制-InfoQ