2018年3月

了解如何在 Linux 中创建登录导语,来向要登录或登录后的用户显示不同的警告或消息。

无论何时登录公司的某些生产系统,你都会看到一些登录消息、警告或关于你将登录或已登录的服务器的信息,如下所示。这些是 登录导语 login banner

Login welcome messages in Linux

在本文中,我们将引导你配置它们。

你可以配置两种类型的导语。

  1. 用户登录前显示的导语信息(在你选择的文件中配置,例如 /etc/login.warn
  2. 用户成功登录后显示的导语信息(在 /etc/motd 中配置)

如何在用户登录前连接系统时显示消息

当用户连接到服务器并且在登录之前,这个消息将被显示给他。意味着当他输入用户名时,该消息将在密码提示之前显示。

你可以使用任何文件名并在其中输入信息。在这里我们使用 /etc/login.warn 并且把我们的消息放在里面。

# cat /etc/login.warn
        !!!! Welcome to KernelTalks test server !!!!
This server is meant for testing Linux commands and tools. If you are
not associated with kerneltalks.com and not authorized please dis-connect
immediately.

现在,需要将此文件和路径告诉 sshd 守护进程,以便它可以为每个用户登录请求获取此标语。对于此,打开 /etc/sshd/sshd_config 文件并搜索 #Banner none

这里你需要编辑该配置文件,并写下你的文件名并删除注释标记(#)。它应该看起来像:Banner /etc/login.warn

保存文件并重启 sshd 守护进程。为避免断开现有的连接用户,请使用 HUP 信号重启 sshd。

root@kerneltalks # ps -ef | grep -i sshd
root     14255     1  0 18:42 ?        00:00:00 /usr/sbin/sshd -D
root     19074 14255  0 18:46 ?        00:00:00 sshd: ec2-user [priv]
root     19177 19127  0 18:54 pts/0    00:00:00 grep -i sshd

root@kerneltalks # kill -HUP 14255

就是这样了!打开新的会话并尝试登录。你将看待你在上述步骤中配置的消息。

Login banner in Linux

你可以在用户输入密码登录系统之前看到此消息。

如何在用户登录后显示消息

消息用户在成功登录系统后看到的 当天消息 Message Of The Day (MOTD)由 /etc/motd 控制。编辑这个文件并输入当成功登录后欢迎用户的消息。

root@kerneltalks # cat /etc/motd
           W E L C O M E
Welcome to the testing environment of kerneltalks.
Feel free to use this system for testing your Linux
skills. In case of any issues reach out to admin at
[email protected]. Thank you.

你不需要重启 sshd 守护进程来使更改生效。只要保存该文件,sshd 守护进程就会下一次登录请求时读取和显示。

motd in linux

你可以在上面的截图中看到:黄色框是由 /etc/motd 控制的 MOTD,绿色框就是我们之前看到的登录导语。

你可以使用 cowsaybannerfigletlolcat 等工具创建出色的引人注目的登录消息。此方法适用于几乎所有 Linux 发行版,如 RedHat、CentOs、Ubuntu、Fedora 等。


via: https://kerneltalks.com/tips-tricks/how-to-configure-login-banners-in-linux/

作者:kerneltalks 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

面试可能会有压力,但 58% 的公司告诉 Dice 和 Linux 基金会,他们需要在未来几个月内聘请开源人才。学习如何提出正确的问题。

Dice 和 Linux 基金会的年度开源工作报告揭示了开源专业人士的前景以及未来一年的招聘活动。在今年的报告中,86% 的科技专业人士表示,了解开源推动了他们的职业生涯。然而,当在他们自己的组织内推进或在别处申请新职位的时候,有这些经历会发生什么呢?

面试新工作绝非易事。除了在准备新职位时还要应付复杂的工作,当面试官问“你有什么问题要问吗?”时,适当的回答更增添了压力。

在 Dice,我们从事职业、建议,并将技术专家与雇主连接起来。但是我们也在公司里雇佣技术人才来开发开源项目。实际上,Dice 平台基于许多 Linux 发行版,我们利用开源数据库作为我们搜索功能的基础。总之,如果没有开源软件,我们就无法运行 Dice,因此聘请了解和热爱开源软件的专业人士至关重要。

多年来,我在面试中了解到提出好问题的重要性。这是一个了解你的潜在新雇主的机会,以及更好地了解他们是否与你的技能相匹配。

这里有三个要问的重要问题,以及其重要的原因:

1、 公司对员工在空闲时间致力于开源项目或编写代码的立场是什么?

这个问题的答案会告诉正在面试的公司的很多信息。一般来说,只要它与你在该公司所从事的工作没有冲突,公司会希望技术专家为网站或项目做出贡献。在公司之外允许这种情况,也会在技术组织中培养出一种创业精神,并教授技术技能,否则在正常的日常工作中你可能无法获得这些技能。

2、 项目如何区分优先级?

由于所有的公司都成为了科技公司,所以在创新的客户面对技术项目与改进平台本身之间往往存在着分歧。你会努力保持现有的平台最新么?或者致力于公众开发新产品?根据你的兴趣,答案可以决定公司是否适合你。

3、 谁主要决定新产品,开发者在决策过程中有多少投入?

这个问题是了解谁负责公司创新(以及与他/她有多少联系),还有一个是了解你在公司的职业道路。在开发新产品之前,一个好的公司会和开发人员和开源人才交流。这看起来不用多想,但有时会错过这步,意味着在新产品发布之前协作环境的不同或者混乱的过程。

面试可能会有压力,但是 58% 的公司告诉 Dice 和 Linux 基金会他们需要在未来几个月内聘用开源人才,所以记住高需求会让像你这样的专业人士成为雇员。以你想要的方向引导你的事业。

现在下载完整的 2017 年开源工作报告。


via: https://www.linux.com/blog/os-jobs/2017/12/3-essential-questions-ask-your-next-tech-interview

作者:Brian Hostetter 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

如果你的数据中心全是 Linux 服务器,而你就是系统管理员。那么你的其中一项工作内容就是查看服务器的日志文件。但是,如果你在大量的机器上去查看日志文件,那么意味着你需要挨个去登入到机器中来阅读日志文件。如果你管理的机器很多,仅这项工作就可以花费你一天的时间。

另外的选择是,你可以配置一台单独的 Linux 机器去收集这些日志。这将使你的每日工作更加高效。要实现这个目的,有很多的不同系统可供你选择,而 syslog-ng 就是其中之一。

syslog-ng 的不足是文档并不容易梳理。但是,我已经解决了这个问题,我可以通过这种方法马上进行安装和配置 syslog-ng。下面我将在 Ubuntu Server 16.04 上示范这两种方法:

  • UBUNTUSERVERVM 的 IP 地址是 192.168.1.118 ,将配置为日志收集器
  • UBUNTUSERVERVM2 将配置为一个客户端,发送日志文件到收集器

现在我们来开始安装和配置。

安装

安装很简单。为了尽可能容易,我将从标准仓库安装。打开一个终端窗口,运行如下命令:

sudo apt install syslog-ng

你必须在收集器和客户端的机器上都要运行上面的命令。安装完成之后,你将开始配置。

配置收集器

现在,我们开始日志收集器的配置。它的配置文件是 /etc/syslog-ng/syslog-ng.conf。syslog-ng 安装完成时就已经包含了一个配置文件。我们不使用这个默认的配置文件,可以使用 mv /etc/syslog-ng/syslog-ng.conf /etc/syslog-ng/syslog-ng.conf.BAK 将这个自带的默认配置文件重命名。现在使用 sudo nano /etc/syslog/syslog-ng.conf 命令创建一个新的配置文件。在这个文件中添加如下的行:

@version: 3.5
@include "scl.conf"
@include "`scl-root`/system/tty10.conf"
    options {
        time-reap(30);
        mark-freq(10);
        keep-hostname(yes);
        };
    source s_local { system(); internal(); };
    source s_network {
        syslog(transport(tcp) port(514));
        };
    destination d_local {
    file("/var/log/syslog-ng/messages_${HOST}"); };
    destination d_logs {
        file(
            "/var/log/syslog-ng/logs.txt"
            owner("root")
            group("root")
            perm(0777)
            ); };
    log { source(s_local); source(s_network); destination(d_logs); };

需要注意的是,syslog-ng 使用 514 端口,你需要确保在你的网络上它可以被访问。

保存并关闭这个文件。上面的配置将转存期望的日志文件(由 system()internal() 指出)到 /var/log/syslog-ng/logs.txt 中。因此,你需要使用如下的命令去创建所需的目录和文件:

sudo mkdir /var/log/syslog-ng
sudo touch /var/log/syslog-ng/logs.txt

使用如下的命令启动和启用 syslog-ng:

sudo systemctl start syslog-ng
sudo systemctl enable syslog-ng

配置客户端

我们将在客户端上做同样的事情(移动默认配置文件并创建新配置文件)。拷贝下列文本到新的客户端配置文件中:

@version: 3.5
@include "scl.conf"
@include "`scl-root`/system/tty10.conf"
source s_local { system(); internal(); };
destination d_syslog_tcp {
              syslog("192.168.1.118" transport("tcp") port(514)); };
log { source(s_local);destination(d_syslog_tcp); };

请注意:请将 IP 地址修改为收集器的 IP 地址。

保存和关闭这个文件。与在配置为收集器的机器上一样的方法启动和启用 syslog-ng。

查看日志文件

回到你的配置为收集器的服务器上,运行这个命令 sudo tail -f /var/log/syslog-ng/logs.txt。你将看到包含了收集器和客户端的日志条目的输出(图 A)。

图 A

恭喜你!syslog-ng 已经正常工作了。你现在可以登入到你的收集器上查看本地机器和远程客户端的日志了。如果你的数据中心有很多 Linux 服务器,在每台服务器上都安装上 syslog-ng 并配置它们作为客户端发送日志到收集器,这样你就不需要登入到每个机器去查看它们的日志了。


via: https://www.techrepublic.com/article/how-to-use-syslog-ng-to-collect-logs-from-remote-linux-machines/

作者:Jack Wallen 译者:qhwdw 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

区块链之所以被称之为一种“颠覆性”的新兴技术,因为尽管其成名于比特币,但未来区块链的用武之地将远远超过加密货币。区块链的分布式共享账本这一技术本质能够在商业网络中使更多的参与方得以更加广泛的参与,并为商业网络或行业业务带来更低的沟通或整合成本,以及更高的业务效率。可以预见,区块链作为一个独立的技术板块,会在商业领域得到广泛应用。

1、区块链的 2.0 时代:商用区块链

自 2009 年比特币在交易领域迅速崛起以来,这种加密币受到了广泛关注,但也颇受争议。不过比特币的底层技术——区块链,由于能够快速改进银行、供应链以及其他的交易网络,在降低与业务运营相关的成本和风险的同时,创造新的创新和增长机会,是比较无争议的新兴技术模式,得到了商业世界的鼎力支持。

传统的商业业务模式存在很难在一个互信的网络中监视跨机构的交易执行的问题:每个参与方都有自己的账本,在交易发生时各自更改;协同各方导致的额外工作及中介等附加成本;由于业务条件,“合同”重复分散在各个参与方造成整体业务流程的不有效性;整个业务网络依赖于一个或几个中心系统,整个商业网络十分脆弱。

而区块链提供了共享的、复制的、授权的账本这样一个解决方案。区块链架构带来以下改变:区块链架构使每一个商业网络的参与方都具有一个共享的账本,当交易发生时,通过点对点的复制更改所有账本;使用密码算法确保网络上的参与者仅仅可以看到和他们相关的账本内容,交易是安全的、授权的和验证的;区块链也将资产转移交易相关的合同条款嵌入交易数据库以做到满足商务条件下交易才发生;网络参与者基于共识机制或类似的机制来保证交易时共同验证的,商业网络满足政府监管、合规及审计。总体而言,区块链在提高业务效率和简化流程上确实具有优势。

当前国内外区块链产业生态发展迅猛,产业链层次逐渐清晰,无论从底层基础架构和平台,还是细分产业板块的区块链应用,以及风险资本投资都已初具规模。综合来看,全球区块链在商业行业发展具有三大趋势:

1)从比特币向更丰富的应用场景发展。区块链 2.0 把之前“区块链就是比特币”的意义向前推进了一大步,区块链也不再是比特币的专有技术和代名词,而且在更加广泛的应用场景中,成为资产流转的价值表述。区块链当下不再依赖数字货币或资产这一类的单一场景,而是发展到支付汇兑、电子商务、移动社交、众筹、慈善、互助保险等面向终端用户的应用,以及数字资产、IP版权和交易、金融清算和结算、商品溯源等企业级应用领域。

2)全球区块链生态日益丰富,参与方开始出现明显的产业分工。从全球的视角来看,随着参与者越来越多,区块链形成了不同技术平台、行业以及发展路径的产业生态。对全球的区块链从业者来说,更看重区块链作为未来 金融科技 FinTech 的一个领域而提前布局,大胆尝试实践区块链在金融及其他行业中的各类业务场景。同时,高科技龙头企业也希望在区块链技术框架的建立上尽早发力,通过支持全球开源社区建立更扎实的底层区块链平台和更广泛的应用场景。区块链的热潮带动了更多创业者的热情,众多初创公司如雨后春笋般的应运而生。从行业角度来看,区块链初创公司覆盖了银行和保险服务、供应链、医疗、物联网、外贸等众多行业背景,可谓是百花齐放。

3)全球投资正在快速注入,重点关注企业级应用落地。区块链项目融资正呈现井喷式增长,从 2012 年到 2015 年,区块链领域吸引的风险投资从 200 万美元增长到 4.69 亿美元,增长超过了 200 倍,累计投资已达 10 亿美元左右。2016 年仅在金融领域,区块链技术投资额就占整体投资的七成以上。从全球的投资情况来看,由于越来越多的行业已经开始实践区块链,使得更多的投资人开始关注在行业内的区块链应用场景,投资上趋于理性,但更注重利用投资者自身资源帮助投资标的进行深度的行业孵化。

总之,市场,行业,投资等多方对于商用区块链的发展诉求十分强烈,作为“颠覆性创新”技术的区块链前景光明。

2、超级账本:商用区块链的“第五元素”

企业级区块链四大平台要素包括:共享账簿,共识,隐私和保密,智能合约。此外,还有第五要素,即商业网络。企业级的区块链一定是围绕业务场景展开的,因此在第五元素商业网络当中需要包含市场参与者的对等架构以及伙伴间的一个共识协议。

目前,以比特币为代表的公有链有一些加密货币之外的新型应用,但是却无法克服自身固有的一些问题,例如交易效率低,区块没有 最终确定性 finality 等,而且是由极客主导的,不符合商业主流趋势。为了克服上述不足,满足大多数商业应用的要求,设计开发适合商用的区块链平台迫在眉睫。

Linux 基金会于 2015 年 12 月启动了名为“超级账本”(Hyperledger)的开源项目应运而生。该项目旨在推动各方协作,共同打造基于区块链的企业级分布式账本底层技术,用于构建支撑业务的行业应用和平台,以便支持各种各样的商业应用场景。超级账本是代码数量最大社区参与度最高的区块链开源项目。

企业级商用区块链网络比较适合使用联盟链和许可制。这样在一个限定的范围内,只有授权的节点和用户才能参与到交易和智能合约的执行中来,而任何的匿名节点或非授权用户均被拒绝服务。从团体联盟的角度增加了区块链网络的安全可靠。当前,欧美主流的区块链应用大部分是行业链或者是联盟链,也就是某一个行业的上下游,或者是核心企业大家联合起来,一起来构建的半公开化的区块链。从这个角度讲,超级账本具备成为未来最主要的商用区块链技术平台的潜力,值得技术开发人员花时间和精力进行学习研究。

由于超级账本有个重要的设计原则就是按照 “用例驱动” use case driven 的方式来实现的,所有功能都应该有对应的用例需求,因此学习研究的过程并不一定十分辛苦。此外,鉴于超级账本是个通用型框架,无法预先确定将来所有的应用场景,因此,定义出部分典型的用例,可使超级账本先满足这部分代表性的区块链应用需求,然后再用可替换模块满足其他需求。

3、区块链的商业应用场景

区块链的商业应用才刚刚起步,一般都将金融业应用作为切入口,很多其他领域的应用还在探索或试水阶段。最重要的是,不能为了技术而技术,为了区块链而区块链。商用区块链技术要解决企业的痛点,为客户创造新的价值。可喜的是,在金融和金融以外的各个细分领域,区块链都在加速落地。以下为一些应用实例和构想。

1)金融领域。21 世纪是金融的“大航海时代”,区块链在银行、保险、清算、股权登记交易、信用评级、公证等领域,既需要绝对的可信任,也需要隐私保密,特别适合区块链应用。举例来说,金融行业关心的资产分布式管存,可以把资产(如证券等)数据存放在区块链网络后,资产的利益相关人可以直接访问资产数据,而无需经过传统的中间人,可大幅提高效率和节约成本。区块链股权登记和交易平台脱胎于加密币交易所,也是比较合适、比较容易实现的应用。

2)产业互联网领域。供应链溯源和共享经济可以应用区块链。在供应链中,所有的参与者都通过区块链记录、追踪和共享各种数据,这些数据记录在区块链里面并贯穿货物的生产、运输和销售等环节,从而提供深度回溯查询等核心功能,实现信息公开透明,出了问题可以用来追责。附加值较高的食品、药品和疫苗、零部件生产检测结果等都可以使用区块链。

例如,现在市场上号称是北大荒地区生产的大米,特别是五常大米,是当地实际产量的很多倍,造成良莠不齐。消费者希望花比较高的价钱购买真正的北大荒大米,却苦于根本无法分辨哪些大米是真的。此处可以提现区块链在供应链溯源上的价值,就是利用区块链的数据记录的真实性或者是有效性。如果通过在原产地和各个流通环节中设置的传感设备在区块链上签名盖戳,一旦进入到区块链里面,每个人的签名就不能抵赖了。含有被区块链标记的时间戳、地理戳、品质戳的放心粮从源头上杜绝各个环节作弊的动机,市场上才能销售与当地产量相匹配的大米。

1)传统行业的转型创新。区块链的应用绝不仅局限于金融和互联网等前沿领域,还可以与能源,零售,电商、房地产等传统领域接轨,因此区块链不是个摆设。例如,高盛公司就提出,对于资产所有权需经过谨慎识别的房地产交易,如果能够利用区块链技术建立安全、共享的所有权数据库,那么房产交易纠纷和交易成本将大大缩小。

2)FinTech 2.0 的三驾马车:区块链、认知物联网和人工智能。未来,世界将进入人工智能、认知物联网和区块链三足鼎立的时期,如果能将三者有机结合将创造巨大的价值。例如,如果将闲置或未充分利用的资产(汽车、仓库、医疗设备等)接入物联网,那么区块链技术则可以帮助互不相识的这些资产的所有者进行资产使用的交易谈判。在共享经济的模式下,最需要解决的就是陌生人之间的信任问题,即资源的提供方和资源的租用者,如何在缺乏信任的基础上安全地完成交易。分布式区块链将是全新的一种去信任的方式,不使用任何中间平台,达到各方参与者的可靠交易的目的。这有点类似于分时用车和分时用房,将引爆以前隐藏在深处的过剩资产容量。

——本文摘自《深度探索区块链:Hyperledger 技术与应用》


想学习区块链知识的同学可以参加由 华章书院、智链 ChainNova 主办,Linux 中国协办的第3届《洞见区块链·深度探索区块链》技术沙龙

时间: 2018 年 3 月 18 日 13:00 ~ 17:30 。

地点:北京市海淀区海淀西大街36号昊海写字楼3楼(清华经管创业者加速器)

限额 200 人

点此报名,或扫描二维码报名。

所有人都在讨论云。尽管市面上有很多为我们提供云存储和其他云服务的主要服务商,但是我们还是可以为自己搭建一个私有云。

在本教程中,我们将讨论如何利用 OwnCloud 搭建私有云。OwnCloud 是一个可以安装在我们 Linux 设备上的 web 应用程序,能够存储和用我们的数据提供服务。OwnCloud 可以分享日历、联系人和书签,共享音/视频流等等。

本教程中,我们使用的是 CentOS 7 系统,但是本教程同样适用于其他 Linux 发行版中安装 OwnCloud。让我们开始安装 OwnCloud 并且做一些准备工作,

预备

$ sudo yum install php-mysql php-json php-xml php-mbstring php-zip php-gd curl php-curl php-pdo

安装

安装 OwnCloud,我们现在需要在服务器上下载 OwnCloud 安装包。使用下面的命令从官方网站下载最新的安装包(10.0.4-1):

$ wget https://download.owncloud.org/community/owncloud-10.0.4.tar.bz2

使用下面的命令解压:

$ tar -xvf owncloud-10.0.4.tar.bz2

现在,将所有解压后的文件移动至 /var/www/html

$ mv owncloud/* /var/www/html

下一步,我们需要在 Apache 的配置文件 httpd.conf 上做些修改:

$ sudo vim /etc/httpd/conf/httpd.conf

更改下面的选项:

AllowOverride All

保存该文件,并修改 OwnCloud 文件夹的文件权限:

$ sudo chown -R apache:apache /var/www/html/
$ sudo chmod 777 /var/www/html/config/

然后重启 Apache 服务器执行修改:

$ sudo systemctl restart httpd

现在,我们需要在 MariaDB 上创建一个数据库,保存来自 OwnCloud 的数据。使用下面的命令创建数据库和数据库用户:

$ mysql -u root -p
MariaDB [(none)] > create database owncloud;
MariaDB [(none)] > GRANT ALL ON owncloud.* TO ocuser@localhost IDENTIFIED BY 'owncloud';
MariaDB [(none)] > flush privileges;
MariaDB [(none)] > exit

服务器配置部分完成后,现在我们可以在网页浏览器上访问 OwnCloud。打开浏览器,输入您的服务器 IP 地址,我这边的服务器是 10.20.30.100:

安装 owncloud

一旦 URL 加载完毕,我们将呈现上述页面。这里,我们将创建管理员用户同时提供数据库信息。当所有信息提供完毕,点击“Finish setup”。

我们将被重定向到登录页面,在这里,我们需要输入先前创建的凭据:

安装 owncloud

认证成功之后,我们将进入 OwnCloud 面板:

安装 owncloud

我们可以使用手机应用程序,同样也可以使用网页界面更新我们的数据。现在,我们已经有自己的私有云了,同时,关于如何安装 OwnCloud 创建私有云的教程也进入尾声。请在评论区留下自己的问题或建议。


via: http://linuxtechlab.com/create-personal-cloud-install-owncloud/

作者:SHUSAIN 译者:CYLeft 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

这是我写的并发网络服务器系列文章的第五部分。在前四部分中我们讨论了并发服务器的结构,这篇文章我们将去研究一个在生产系统中大量使用的服务器的案例—— Redis

Redis logo

Redis 是一个非常有魅力的项目,我关注它很久了。它最让我着迷的一点就是它的 C 源代码非常清晰。它也是一个高性能、大并发的内存数据库服务器的非常好的例子,它是研究网络并发服务器的一个非常好的案例,因此,我们不能错过这个好机会。

我们来看看前四部分讨论的概念在真实世界中的应用程序。

本系列的所有文章有:

事件处理库

Redis 最初发布于 2009 年,它最牛逼的一件事情大概就是它的速度 —— 它能够处理大量的并发客户端连接。需要特别指出的是,它是用一个单线程来完成的,而且还不对保存在内存中的数据使用任何复杂的锁或者同步机制。

Redis 之所以如此牛逼是因为,它在给定的系统上使用了其可用的最快的事件循环,并将它们封装成由它实现的事件循环库(在 Linux 上是 epoll,在 BSD 上是 kqueue,等等)。这个库的名字叫做 ae。ae 使得编写一个快速服务器变得很容易,只要在它内部没有阻塞即可,而 Redis 则保证 注1 了这一点。

在这里,我们的兴趣点主要是它对文件事件的支持 —— 当文件描述符(如网络套接字)有一些有趣的未决事情时将调用注册的回调函数。与 libuv 类似,ae 支持多路事件循环(参阅本系列的第三节第四节)和不应该感到意外的 aeCreateFileEvent 信号:

int aeCreateFileEvent(aeEventLoop *eventLoop, int fd, int mask,
                      aeFileProc *proc, void *clientData);

它在 fd 上使用一个给定的事件循环,为新的文件事件注册一个回调(proc)函数。当使用的是 epoll 时,它将调用 epoll_ctl 在文件描述符上添加一个事件(可能是 EPOLLINEPOLLOUT、也或许两者都有,取决于 mask 参数)。ae 的 aeProcessEvents 功能是 “运行事件循环和发送回调函数”,它在底层调用了 epoll_wait

处理客户端请求

我们通过跟踪 Redis 服务器代码来看一下,ae 如何为客户端事件注册回调函数的。initServer 启动时,通过注册一个回调函数来读取正在监听的套接字上的事件,通过使用回调函数 acceptTcpHandler 来调用 aeCreateFileEvent。当新的连接可用时,这个回调函数被调用。它调用 accept 注2 ,接下来是 acceptCommonHandler,它转而去调用 createClient 以初始化新客户端连接所需要的数据结构。

createClient 的工作是去监听来自客户端的入站数据。它将套接字设置为非阻塞模式(一个异步事件循环中的关键因素)并使用 aeCreateFileEvent 去注册另外一个文件事件回调函数以读取事件 —— readQueryFromClient。每当客户端发送数据,这个函数将被事件循环调用。

readQueryFromClient 就让我们期望的那样 —— 解析客户端命令和动作,并通过查询和/或操作数据来回复。因为客户端套接字是非阻塞的,所以这个函数必须能够处理 EAGAIN,以及部分数据;从客户端中读取的数据是累积在客户端专用的缓冲区中,而完整的查询可能被分割在回调函数的多个调用当中。

将数据发送回客户端

在前面的内容中,我说到了 readQueryFromClient 结束了发送给客户端的回复。这在逻辑上是正确的,因为 readQueryFromClient 准备要发送回复,但它不真正去做实质的发送 —— 因为这里并不能保证客户端套接字已经准备好写入/发送数据。我们必须为此使用事件循环机制。

Redis 是这样做的,它注册一个 beforeSleep 函数,每次事件循环即将进入休眠时,调用它去等待套接字变得可以读取/写入。beforeSleep 做的其中一件事情就是调用 handleClientsWithPendingWrites。它的作用是通过调用 writeToClient 去尝试立即发送所有可用的回复;如果一些套接字不可用时,那么套接字可用时,它将注册一个事件循环去调用 sendReplyToClient。这可以被看作为一种优化 —— 如果套接字可用于立即发送数据(一般是 TCP 套接字),这时并不需要注册事件 ——直接发送数据。因为套接字是非阻塞的,它从不会去阻塞循环。

为什么 Redis 要实现它自己的事件库?

第四节 中我们讨论了使用 libuv 来构建一个异步并发服务器。需要注意的是,Redis 并没有使用 libuv,或者任何类似的事件库,而是它去实现自己的事件库 —— ae,用 ae 来封装 epoll、kqueue 和 select。事实上,Antirez(Redis 的创建者)恰好在 2011 年的一篇文章 中回答了这个问题。他的回答的要点是:ae 只有大约 770 行他理解的非常透彻的代码;而 libuv 代码量非常巨大,也没有提供 Redis 所需的额外功能。

现在,ae 的代码大约增长到 1300 多行,比起 libuv 的 26000 行(这是在没有 Windows、测试、示例、文档的情况下的数据)来说那是小巫见大巫了。libuv 是一个非常综合的库,这使它更复杂,并且很难去适应其它项目的特殊需求;另一方面,ae 是专门为 Redis 设计的,与 Redis 共同演进,只包含 Redis 所需要的东西。

这是我 前些年在一篇文章中 提到的软件项目依赖关系的另一个很好的示例:

依赖的优势与在软件项目上花费的工作量成反比。

在某种程度上,Antirez 在他的文章中也提到了这一点。他提到,提供大量附加价值(在我的文章中的“基础” 依赖)的依赖比像 libuv 这样的依赖更有意义(它的例子是 jemalloc 和 Lua),对于 Redis 特定需求,其功能的实现相当容易。

Redis 中的多线程

在 Redis 的绝大多数历史中,它都是一个不折不扣的单线程的东西。一些人觉得这太不可思议了,有这种想法完全可以理解。Redis 本质上是受网络束缚的 —— 只要数据库大小合理,对于任何给定的客户端请求,其大部分延时都是浪费在网络等待上,而不是在 Redis 的数据结构上。

然而,现在事情已经不再那么简单了。Redis 现在有几个新功能都用到了线程:

  1. “惰性” 内存释放
  2. 在后台线程中使用 fsync 调用写一个 持久化日志
  3. 运行需要执行一个长周期运行的操作的用户定义模块。

对于前两个特性,Redis 使用它自己的一个简单的 bio(它是 “Background I/O" 的首字母缩写)库。这个库是根据 Redis 的需要进行了硬编码,它不能用到其它的地方 —— 它运行预设数量的线程,每个 Redis 后台作业类型需要一个线程。

而对于第三个特性,Redis 模块 可以定义新的 Redis 命令,并且遵循与普通 Redis 命令相同的标准,包括不阻塞主线程。如果在模块中自定义的一个 Redis 命令,希望去执行一个长周期运行的操作,这将创建一个线程在后台去运行它。在 Redis 源码树中的 src/modules/helloblock.c 提供了这样的一个示例。

有了这些特性,Redis 使用线程将一个事件循环结合起来,在一般的案例中,Redis 具有了更快的速度和弹性,这有点类似于在本系统文章中 第四节 讨论的工作队列。

  • 注1: Redis 的一个核心部分是:它是一个 内存中 数据库;因此,查询从不会运行太长的时间。当然了,这将会带来各种各样的其它问题。在使用分区的情况下,服务器可能最终路由一个请求到另一个实例上;在这种情况下,将使用异步 I/O 来避免阻塞其它客户端。
  • 注2: 使用 anetAcceptanet 是 Redis 对 TCP 套接字代码的封装。

via: https://eli.thegreenplace.net/2017/concurrent-servers-part-5-redis-case-study/

作者:Eli Bendersky 译者:qhwdw 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出