2017年11月

介绍

KSQL 是 Apache Kafka 中的开源的流式 SQL 引擎。它可以让你在 Kafka 主题 topic 上,使用一个简单的并且是交互式的 SQL 接口,很容易地做一些复杂的流处理。在这个短文中,我们将看到如何轻松地配置并运行在一个沙箱中去探索它,并使用大家都喜欢的演示数据库源: Twitter。我们将从推文的原始流中获取,通过使用 KSQL 中的条件去过滤它,来构建一个聚合,如统计每个用户每小时的推文数量。

Confluent

首先, 获取一个 Confluent 平台的副本。我使用的是 RPM 包,但是,如果你需要的话,你也可以使用 tar、 zip 等等 。启动 Confluent 系统:

$ confluent start

(如果你感兴趣,这里有一个 Confluent 命令行的快速教程

我们将使用 Kafka Connect 从 Twitter 上拉取数据。 这个 Twitter 连接器可以在 GitHub 上找到。要安装它,像下面这样操作:

# Clone the git repo
cd /home/rmoff
git clone https://github.com/jcustenborder/kafka-connect-twitter.git
# Compile the code
cd kafka-connect-twitter
mvn clean package

要让 Kafka Connect 去使用我们构建的连接器, 你要去修改配置文件。因为我们使用 Confluent 命令行,真实的配置文件是在 etc/schema-registry/connect-avro-distributed.properties,因此去修改它并增加如下内容:

plugin.path=/home/rmoff/kafka-connect-twitter/target/kafka-connect-twitter-0.2-SNAPSHOT.tar.gz

重启动 Kafka Connect:

confluent stop connect
confluent start connect

一旦你安装好插件,你可以很容易地去配置它。你可以直接使用 Kafka Connect 的 REST API ,或者创建你的配置文件,这就是我要在这里做的。如果你需要全部的方法,请首先访问 Twitter 来获取你的 API 密钥

{
 "name": "twitter_source_json_01",
 "config": {
   "connector.class": "com.github.jcustenborder.kafka.connect.twitter.TwitterSourceConnector",
   "twitter.oauth.accessToken": "xxxx",
   "twitter.oauth.consumerSecret": "xxxxx",
   "twitter.oauth.consumerKey": "xxxx",
   "twitter.oauth.accessTokenSecret": "xxxxx",
   "kafka.delete.topic": "twitter_deletes_json_01",
   "value.converter": "org.apache.kafka.connect.json.JsonConverter",
   "key.converter": "org.apache.kafka.connect.json.JsonConverter",
   "value.converter.schemas.enable": false,
   "key.converter.schemas.enable": false,
   "kafka.status.topic": "twitter_json_01",
   "process.deletes": true,
   "filter.keywords": "rickastley,kafka,ksql,rmoff"
 }
}

假设你写这些到 /home/rmoff/twitter-source.json,你可以现在运行:

$ confluent load twitter_source -d /home/rmoff/twitter-source.json

然后推文就从大家都喜欢的网络明星 [rick] 滚滚而来……

$ kafka-console-consumer --bootstrap-server localhost:9092 --from-beginning --topic twitter_json_01|jq '.Text'
{
  "string": "RT @rickastley: 30 years ago today I said I was Never Gonna Give You Up. I am a man of my word - Rick x https://t.co/VmbMQA6tQB"
}
{
  "string": "RT @mariteg10: @rickastley @Carfestevent Wonderful Rick!!\nDo not forget Chile!!\nWe hope you get back someday!!\nHappy weekend for you!!\n❤…"
}

KSQL

现在我们从 KSQL 开始 ! 马上去下载并构建它:

cd /home/rmoff
git clone https://github.com/confluentinc/ksql.git
cd /home/rmoff/ksql
mvn clean compile install -DskipTests

构建完成后,让我们来运行它:

./bin/ksql-cli local --bootstrap-server localhost:9092
                       ======================================
                       =      _  __ _____  ____  _          =
                       =     | |/ // ____|/ __ \| |         =
                       =     | ' /| (___ | |  | | |         =
                       =     |  <  \___ \| |  | | |         =
                       =     | . \ ____) | |__| | |____     =
                       =     |_|\_\_____/ \___\_\______|    =
                       =                                    =
                       =   Streaming SQL Engine for Kafka   =
Copyright 2017 Confluent Inc.

CLI v0.1, Server v0.1 located at http://localhost:9098

Having trouble? Type 'help' (case-insensitive) for a rundown of how things work!

ksql> 

使用 KSQL, 我们可以让我们的数据保留在 Kafka 主题上并可以查询它。首先,我们需要去告诉 KSQL 主题上的 数据模式 schema 是什么,一个 twitter 消息实际上是一个非常巨大的 JSON 对象, 但是,为了简洁,我们只选出其中几行:

ksql> CREATE STREAM twitter_raw (CreatedAt BIGINT, Id BIGINT, Text VARCHAR) WITH (KAFKA_TOPIC='twitter_json_01', VALUE_FORMAT='JSON');

Message  
----------------
Stream created

在定义的模式中,我们可以查询这些流。要让 KSQL 从该主题的开始展示数据(而不是默认的当前时间点),运行如下命令:

ksql> SET 'auto.offset.reset' = 'earliest';  
Successfully changed local property 'auto.offset.reset' from 'null' to 'earliest'

现在,让我们看看这些数据,我们将使用 LIMIT 从句仅检索一行:

ksql> SELECT text FROM twitter_raw LIMIT 1;  
RT @rickastley: 30 years ago today I said I was Never Gonna Give You Up. I am a man of my word - Rick x https://t.co/VmbMQA6tQB
LIMIT reached for the partition.  
Query terminated
ksql>

现在,让我们使用刚刚定义和可用的推文内容的全部数据重新定义该流:

ksql> DROP stream twitter_raw;
Message
--------------------------------
Source TWITTER_RAW was dropped

ksql> CREATE STREAM twitter_raw (CreatedAt bigint,Id bigint, Text VARCHAR, SOURCE VARCHAR, Truncated VARCHAR, InReplyToStatusId VARCHAR, InReplyToUserId VARCHAR, InReplyToScreenName VARCHAR, GeoLocation VARCHAR, Place VARCHAR, Favorited VARCHAR, Retweeted VARCHAR, FavoriteCount VARCHAR, User VARCHAR, Retweet VARCHAR, Contributors VARCHAR, RetweetCount VARCHAR, RetweetedByMe VARCHAR, CurrentUserRetweetId VARCHAR, PossiblySensitive VARCHAR, Lang VARCHAR, WithheldInCountries VARCHAR, HashtagEntities VARCHAR, UserMentionEntities VARCHAR, MediaEntities VARCHAR, SymbolEntities VARCHAR, URLEntities VARCHAR) WITH (KAFKA_TOPIC='twitter_json_01',VALUE_FORMAT='JSON');
Message
----------------
Stream created

ksql>

现在,我们可以操作和检查更多的最近的数据,使用一般的 SQL 查询:

ksql> SELECT TIMESTAMPTOSTRING(CreatedAt, 'yyyy-MM-dd HH:mm:ss.SSS') AS CreatedAt,\
EXTRACTJSONFIELD(user,'$.ScreenName') as ScreenName,Text \
FROM twitter_raw \
WHERE LCASE(hashtagentities) LIKE '%oow%' OR \
LCASE(hashtagentities) LIKE '%ksql%';  

2017-09-29 13:59:58.000 | rmoff | Looking forward to talking all about @apachekafka & @confluentinc’s #KSQL at #OOW17 on Sunday 13:45 https://t.co/XbM4eIuzeG

注意这里没有 LIMIT 从句,因此,你将在屏幕上看到 “continuous query” 的结果。不像关系型数据表中返回一个确定数量结果的查询,一个持续查询会运行在无限的流式数据上, 因此,它总是可能返回更多的记录。点击 Ctrl-C 去中断然后返回到 KSQL 提示符。在以上的查询中我们做了一些事情:

  • TIMESTAMPTOSTRING 将时间戳从 epoch 格式转换到人类可读格式。(LCTT 译注: epoch 指的是一个特定的时间 1970-01-01 00:00:00 UTC)
  • EXTRACTJSONFIELD 来展示数据源中嵌套的用户域中的一个字段,它看起来像:
{
"CreatedAt": 1506570308000,
"Text": "RT @gwenshap: This is the best thing since partitioned bread :) https://t.co/1wbv3KwRM6",
[...]
"User": {
    "Id": 82564066,
    "Name": "Robin Moffatt \uD83C\uDF7B\uD83C\uDFC3\uD83E\uDD53",
    "ScreenName": "rmoff",
    [...]
  • 应用断言去展示内容,对 #(hashtag)使用模式匹配, 使用 LCASE 去强制小写字母。(LCTT 译注:hashtag 是twitter 中用来标注线索主题的标签)

关于支持的函数列表,请查看 KSQL 文档

我们可以创建一个从这个数据中得到的流:

ksql> CREATE STREAM twitter AS \
SELECT TIMESTAMPTOSTRING(CreatedAt, 'yyyy-MM-dd HH:mm:ss.SSS') AS CreatedAt,\
EXTRACTJSONFIELD(user,'$.Name') AS user_Name,\
EXTRACTJSONFIELD(user,'$.ScreenName') AS user_ScreenName,\
EXTRACTJSONFIELD(user,'$.Location') AS user_Location,\
EXTRACTJSONFIELD(user,'$.Description') AS  user_Description,\
Text,hashtagentities,lang \
FROM twitter_raw ;

Message  
----------------------------  
Stream created and running  

ksql> DESCRIBE twitter;
Field            | Type  
------------------------------------  
ROWTIME          | BIGINT  
ROWKEY           | VARCHAR(STRING)  
CREATEDAT        | VARCHAR(STRING)  
USER_NAME        | VARCHAR(STRING)  
USER_SCREENNAME  | VARCHAR(STRING)  
USER_LOCATION    | VARCHAR(STRING)  
USER_DESCRIPTION | VARCHAR(STRING)  
TEXT             | VARCHAR(STRING)  
HASHTAGENTITIES  | VARCHAR(STRING)  
LANG             | VARCHAR(STRING)  
ksql>

并且查询这个得到的流:

ksql> SELECT CREATEDAT, USER_NAME, TEXT \
FROM TWITTER \
WHERE TEXT LIKE '%KSQL%';  

2017-10-03 23:39:37.000 | Nicola Ferraro | RT @flashdba: Again, I'm really taken with the possibilities opened up by @confluentinc's KSQL engine #Kafka https://t.co/aljnScgvvs

聚合

在我们结束之前,让我们去看一下怎么去做一些聚合。

ksql> SELECT user_screenname, COUNT(*) \
FROM twitter WINDOW TUMBLING (SIZE 1 HOUR) \
GROUP BY user_screenname HAVING COUNT(*) > 1;  

oracleace | 2  
rojulman | 2
smokeinpublic | 2  
ArtFlowMe | 2  
[...]

你将可能得到满屏幕的结果;这是因为 KSQL 在每次给定的时间窗口更新时实际发出聚合值。因为我们设置 KSQL 去读取在主题上的全部消息(SET 'auto.offset.reset' = 'earliest';),它是一次性读取这些所有的消息并计算聚合更新。这里有一个微妙之处值得去深入研究。我们的入站推文流正好就是一个流。但是,现有它不能创建聚合,我们实际上是创建了一个表。一个表是在给定时间点的给定键的值的一个快照。 KSQL 聚合数据基于消息的事件时间,并且如果它更新了,通过简单的相关窗口重申去操作后面到达的数据。困惑了吗? 我希望没有,但是,让我们看一下,如果我们可以用这个例子去说明。 我们将申明我们的聚合作为一个真实的表:

ksql> CREATE TABLE user_tweet_count AS \
SELECT user_screenname, count(*) AS  tweet_count \
FROM twitter WINDOW TUMBLING (SIZE 1 HOUR) \
GROUP BY user_screenname ;

Message  
---------------------------  
Table created and running

看表中的列,这里除了我们要求的外,还有两个隐含列:

ksql> DESCRIBE user_tweet_count;

Field           | Type  
-----------------------------------  
ROWTIME         | BIGINT  
ROWKEY          | VARCHAR(STRING)  
USER_SCREENNAME | VARCHAR(STRING)  
TWEET_COUNT     | BIGINT  
ksql>

我们看一下这些是什么:

ksql> SELECT TIMESTAMPTOSTRING(ROWTIME, 'yyyy-MM-dd HH:mm:ss.SSS') , \
ROWKEY, USER_SCREENNAME, TWEET_COUNT \
FROM user_tweet_count \
WHERE USER_SCREENNAME= 'rmoff';  

2017-09-29 11:00:00.000 | rmoff : Window{start=1506708000000 end=-} | rmoff | 2  
2017-09-29 12:00:00.000 | rmoff : Window{start=1506711600000 end=-} | rmoff | 4  
2017-09-28 22:00:00.000 | rmoff : Window{start=1506661200000 end=-} | rmoff | 2  
2017-09-29 09:00:00.000 | rmoff : Window{start=1506700800000 end=-} | rmoff | 4  
2017-09-29 15:00:00.000 | rmoff : Window{start=1506722400000 end=-} | rmoff | 2  
2017-09-29 13:00:00.000 | rmoff : Window{start=1506715200000 end=-} | rmoff | 6

ROWTIME 是窗口开始时间, ROWKEYGROUP BYUSER_SCREENNAME)加上窗口的组合。因此,我们可以通过创建另外一个衍生的表来整理一下:

ksql> CREATE TABLE USER_TWEET_COUNT_DISPLAY AS \
SELECT TIMESTAMPTOSTRING(ROWTIME, 'yyyy-MM-dd HH:mm:ss.SSS') AS WINDOW_START ,\
USER_SCREENNAME, TWEET_COUNT \
FROM user_tweet_count;

Message  
---------------------------  
Table created and running

现在它更易于查询和查看我们感兴趣的数据:

ksql> SELECT WINDOW_START ,  USER_SCREENNAME, TWEET_COUNT \
FROM USER_TWEET_COUNT_DISPLAY WHERE TWEET_COUNT> 20;  

2017-09-29 12:00:00.000 | VikasAatOracle | 22  
2017-09-28 14:00:00.000 | Throne_ie | 50  
2017-09-28 14:00:00.000 | pikipiki_net | 22  
2017-09-29 09:00:00.000 | johanlouwers | 22  
2017-09-28 09:00:00.000 | yvrk1973 | 24  
2017-09-28 13:00:00.000 | cmosoares | 22  
2017-09-29 11:00:00.000 | ypoirier | 24  
2017-09-28 14:00:00.000 | pikisec | 22  
2017-09-29 07:00:00.000 | Throne_ie | 22  
2017-09-29 09:00:00.000 | ChrisVoyance | 24  
2017-09-28 11:00:00.000 | ChrisVoyance | 28

结论

所以我们有了它! 我们可以从 Kafka 中取得数据, 并且很容易使用 KSQL 去探索它。 而不仅是去浏览和转换数据,我们可以很容易地使用 KSQL 从流和表中建立流处理。

如果你对 KSQL 能够做什么感兴趣,去查看:

记住,KSQL 现在正处于开发者预览阶段。 欢迎在 KSQL 的 GitHub 仓库上提出任何问题, 或者去我们的 community Slack group 的 #KSQL 频道。


via: https://www.confluent.io/blog/using-ksql-to-analyse-query-and-transform-data-in-kafka

作者:Robin Moffatt 译者:qhwdw 校对:wxy

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

运用这些很棒的 Python 爬虫工具来获取你需要的数据。

 title=

在一个理想的世界里,你需要的所有数据都将以公开而文档完备的格式清晰地展现,你可以轻松地下载并在任何你需要的地方使用。

然而,在真实世界里,数据是凌乱的,极少被打包成你需要的样子,要么经常是过期的。

你所需要的信息经常是潜藏在一个网站里。相比一些清晰地、有调理地呈现数据的网站,更多的网站则不是这样的。 爬取数据 crawling 挖掘数据 scraping 、加工数据、整理数据这些是获取整个网站结构来绘制网站拓扑来收集数据所必须的活动,这些可以是以网站的格式储存的或者是储存在一个专有数据库中。

也许在不久的将来,你需要通过爬取和挖掘来获得一些你需要的数据,当然你几乎肯定需要进行一点点的编程来正确的获取。你要怎么做取决于你自己,但是我发现 Python 社区是一个很好的提供者,它提供了工具、框架以及文档来帮助你从网站上获取数据。

在我们进行之前,这里有一个小小的请求:在你做事情之前请思考,以及请耐心。抓取这件事情并不简单。不要把网站爬下来只是复制一遍,并其它人的工作当成是你自己的东西(当然,没有许可)。要注意版权和许可,以及你所爬行的内容应用哪一个标准。尊重 robots.txt 文件。不要频繁的针对一个网站,这将导致真实的访问者会遇到访问困难的问题。

在知晓这些警告之后,这里有一些很棒的 Python 网站爬虫工具,你可以用来获得你需要的数据。

Pyspider

让我们先从 pyspider 开始介绍。这是一个带有 web 界面的网络爬虫,让与使之容易跟踪多个爬虫。其具有扩展性,支持多个后端数据库和消息队列。它还具有一些方便的特性,从优先级到再次访问抓取失败的页面,此外还有通过时间顺序来爬取和其他的一些特性。Pyspider 同时支持 Python 2 和 Python 3。为了实现一个更快的爬取,你可以在分布式的环境下一次使用多个爬虫进行爬取。

Pyspyder 的基本用法都有良好的 文档说明 ,包括简单的代码片段。你能通过查看一个 在线的样例 来体验用户界面。它在 Apache 2 许可证下开源,Pyspyder 仍然在 GitHub 上积极地开发。

MechanicalSoup

MechanicalSoup 是一个基于极其流行而异常多能的 HTML 解析库 Beautiful Soup 建立的爬虫库。如果你的爬虫需要相当的简单,但是又要求检查一些选择框或者输入一些文字,而你又不想为这个任务单独写一个爬虫,那么这会是一个值得考虑的选择。

MechanicalSoup 在 MIT 许可证下开源。查看 GitHub 上该项目的 example.py 样例文件来获得更多的用法。不幸的是,到目前为止,这个项目还没有一个很好的文档。

Scrapy

Scrapy 是一个有着活跃社区支持的抓取框架,在那里你可以建造自己的抓取工具。除了爬取和解析工具,它还能将它收集的数据以 JSON 或者 CSV 之类的格式轻松输出,并存储在一个你选择的后端数据库。它还有许多内置的任务扩展,例如 cookie 处理、代理欺骗、限制爬取深度等等,同时还可以建立你自己附加的 API。

要了解 Scrapy,你可以查看网上的文档或者是访问它诸多的社区资源,包括一个 IRC 频道、Reddit 子版块以及关注他们的 StackOverflow 标签。Scrapy 的代码在 3 句版 BSD 许可证下开源,你可以在 GitHub 上找到它们。

如果你完全不熟悉编程,Portia 提供了一个易用的可视化的界面。scrapinghub.com 则提供一个托管的版本。

其它

  • Cola 自称它是个“高级的分布式爬取框架”,如果你在寻找一个 Python 2 的方案,这也许会符合你的需要,但是注意它已经有超过两年没有更新了。
  • Demiurge 是另一个可以考虑的潜在候选者,它同时支持 Python 2和 Python 3,虽然这个项目的发展较为缓慢。
  • 如果你要解析一些 RSS 和 Atom 数据,Feedparser 或许是一个有用的项目。
  • Lassie 让从网站检索像说明、标题、关键词或者是图片一类的基本内容变得简单。
  • RoboBrowser 是另一个简单的库,它基于 Python 2 或者 Python 3,它具有按钮点击和表格填充的基本功能。虽然它有一段时间没有更新了,但是它仍然是一个不错的选择。

这远不是一个完整的列表,当然,如果你是一个编程专家,你可以选择采取你自己的方法而不是使用这些框架中的一个。或者你发现一个用其他语言编写的替代品。例如 Python 编程者可能更喜欢 Python 附带的 Selenium,它可以在不使用实际浏览器的情况下进行爬取。如果你有喜欢的爬取和挖掘工具,请在下面评论让我们知道。

(题图:You as a Machine. Modified by Rikki Endsley. CC BY-SA 2.0


via: https://opensource.com/resources/python/web-scraper-crawler

作者:Jason Baker 译者:ZH1122 校对:wxy

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

用 iftop、Nethogs 和 vnstat 了解更多关于你的网络连接。

你可以通过这三个 Linux 网络命令,了解有关你网络连接的大量信息。iftop 通过进程号跟踪网络连接,Nethogs 可以快速显示哪个在占用你的带宽,而 vnstat 作为一个很好的轻量级守护进程运行,可以随时随地记录你的使用情况。

iftop

iftop 监听你指定的网络接口,并以 top 的形式展示连接。

这是一个很好的小工具,用于快速识别占用、测量速度,并保持网络流量的总体运行。看到我们使用了多少带宽是非常令人惊讶的,特别是对于我们这些还记得使用电话线、调制解调器、让人尖叫的 Kbit 速度和真实的实时波特率的老年人来说。我们很久以前就放弃了波特率,转而使用比特率。波特率测量信号变化,有时与比特率相同,但大多数情况下不是。

如果你只有一个网络接口,可以不带选项运行 iftopiftop 需要 root 权限:

$ sudo iftop

当你有多个接口时,指定要监控的接口:

$ sudo iftop -i wlan0

就像 top 一样,你可以在运行时更改显示选项。

  • h 切换帮助屏幕。
  • n 切换名称解析。
  • s 切换源主机显示,d 切换目标主机。
  • s 切换端口号。
  • N 切换端口解析。要全看到端口号,请关闭解析。
  • t 切换文本界面。默认显示需要 ncurses。我认为文本显示更易于阅读和更好的组织(图1)。
  • p 暂停显示。
  • q 退出程序。

 title=

图 1:文本显示是可读的和可组织的。

当你切换显示选项时,iftop 会继续测量所有流量。你还可以选择要监控的单个主机。你需要主机的 IP 地址和网络掩码。我很好奇 Pandora 在我那可怜的带宽中占用了多少,所以我先用 dig 找到它们的 IP 地址:

$ dig A pandora.com
[...]
;; ANSWER SECTION:
pandora.com.            267     IN      A       208.85.40.20
pandora.com.            267     IN      A       208.85.40.50

网络掩码是什么? ipcalc 告诉我们:

$ ipcalc -b 208.85.40.20
Address:   208.85.40.20   
Netmask:   255.255.255.0 = 24
Wildcard:  0.0.0.255  
=>
Network:   208.85.40.0/24 

现在将地址和网络掩码提供给 iftop:

$ sudo iftop -F 208.85.40.20/24 -i wlan0

这不是真的吗?我很惊讶地发现,我珍贵的带宽对于 Pandora 很宽裕,每小时使用大约使用 500Kb。而且,像大多数流媒体服务一样,Pandora 的流量也有峰值,其依赖于缓存来缓解阻塞。

你可以使用 -G 选项对 IPv6 地址执行相同操作。请参阅手册页了解 iftop 的其他功能,包括使用自定义配置文件定制默认选项,并应用自定义过滤器(请参阅 PCAP-FILTER 作为过滤器参考)。

Nethogs

当你想要快速了解谁占用了你的带宽时,Nethogs 是快速和容易的。以 root 身份运行,并指定要监听的接口。它显示了空闲的应用程序和进程号,以便如果你愿意的话,你可以杀死它:

$ sudo nethogs wlan0

NetHogs version 0.8.1

PID USER   PROGRAM              DEV    SENT   RECEIVED       
7690 carla /usr/lib/firefox     wlan0 12.494 556.580 KB/sec
5648 carla .../chromium-browser wlan0  0.052   0.038 KB/sec
TOTAL                                 12.546 556.618 KB/sec 

Nethogs 选项很少:在 kb/s、kb、b 和 mb 之间循环;通过接收或发送的数据包进行排序;并调整刷新之间的延迟。请参阅 man nethogs,或者运行 nethogs -h

vnstat

vnstat 是最容易使用的网络数据收集器。它是轻量级的,不需要 root 权限。它作为守护进程运行,并记录你网络统计信息。vnstat 命令显示累计的数据:

$ vnstat -i wlan0
Database updated: Tue Oct 17 08:36:38 2017

   wlan0 since 10/17/2017

          rx:  45.27 MiB      tx:  3.77 MiB      total:  49.04 MiB

   monthly
                     rx      |     tx      |    total    |   avg. rate
     ------------------------+-------------+-------------+---------------
       Oct '17     45.27 MiB |    3.77 MiB |   49.04 MiB |    0.28 kbit/s
     ------------------------+-------------+-------------+---------------
     estimated        85 MiB |       5 MiB |      90 MiB |

   daily
                     rx      |     tx      |    total    |   avg. rate
     ------------------------+-------------+-------------+---------------
         today     45.27 MiB |    3.77 MiB |   49.04 MiB |   12.96 kbit/s
     ------------------------+-------------+-------------+---------------
     estimated       125 MiB |       8 MiB |     133 MiB |

它默认显示所有的网络接口。使用 -i 选项选择单个接口。以这种方式合并多个接口的数据:

$ vnstat -i wlan0+eth0+eth1

你可以通过以下几种方式过滤显示:

  • -h 以小时显示统计数据。
  • -d 以天数显示统计数据。
  • -w-m 按周和月显示统计数据。
  • 使用 -l 选项查看实时更新。

此命令删除 wlan1 的数据库,并停止监控它:

$ vnstat -i wlan1 --delete

此命令为网络接口创建别名。此例使用 Ubuntu 16.04 中的一个奇怪的接口名称:

$ vnstat -u -i enp0s25 --nick eth0

默认情况下,vnstat 监视 eth0。你可以在 /etc/vnstat.conf 中更改此内容,或在主目录中创建自己的个人配置文件。请参见 man vnstat 以获得完整的参考。

你还可以安装 vnstati 创建简单的彩色图(图2):

$ vnstati -s -i wlx7cdd90a0a1c2 -o vnstat.png

 title=

图 2:你可以使用 vnstati 创建简单的彩色图表。

有关完整选项,请参见 man vnstati


via: https://www.linux.com/learn/intro-to-linux/2017/10/3-simple-excellent-linux-network-monitors

作者:CARLA SCHRODER 译者:geekpi 校对:wxy

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

Linux 中国以推广开源技术,传播开源文化为己任,因此,我们广泛地从互联网世界汲取各种有益的资讯,并组织了 LCTT 翻译了数千篇英文文章分享给中国的读者们。再次,这要感谢我们的志愿者们,几年来,勤勉地贡献了多少个人时间,留下的却是一再传播、令人受益的文章。

大家已经知道,我们除了官方主站(https://linux.cn/)之外,我们还有微信公众号、微博认证号、知乎机构号、网易号、今日头条号等等。而据说,互联网世界除了中国国内这些传播渠道之外,居然还有什么脸谱、推她、电报之类平台,因此,我们本着传播知识的初心,决定将内容反倾销到那些不可知、不存在的地方。毕竟,我们是要成为海贼王的男人嘛! :D

言归正传,下面我来列出一下我们目前所有处于积极维护状态的内容输出平台, 请诸君多撷取 说人话:需要粉丝,求关注

平台Web客户端地址或名称备注
官方主站 https://linux.cn/所有“Linux 中国”发布内容的起源地
RSS https://linux.cn/rss.xml比主站内容更新有延迟
微博认证号Linux中国不定时推送主站内容
微信公众号 Linux中国主号,基本上每日同步更新主站内容
Linux精华摘要号,1-2 周更新一次期间的重要文章
Linux开源社区每日一条技术文章
知乎机构号Linux中国不定时推送主站内容
今日头条号Linux技术不定时推送主站内容
Linux中国不定时推送主站内容
网易号Linux不定时推送主站内容
FacebookLinux中国同步推送主站内容
TwitterLinux中国同步推送主站内容
Telegram Linux中国频道, 同步推送主站内容
Linux中国 粉丝群群组, 同步推送主站内容

好了,不要问我怎么样到达那些不可知、不可测的地方,谁知道到底存在不存在呢?

一个获得关于慢查询、意外错误和其它重要日志通知的简单 Go 秘诀。

我的 Slack 机器人提示我一个运行了很长时间 SQL 查询。我应该尽快解决它。

我们不能管理我们无法去测量的东西。每个后台应用程序都需要我们去监视它在数据库上的性能。如果一个特定的查询随着数据量增长变慢,你必须在它变得太慢之前去优化它。

由于 Slack 已经成为我们工作的中心,它也在改变我们监视系统的方式。 虽然我们已经有非常不错的监视工具,如果在系统中任何东西有正在恶化的趋势,让 Slack 机器人告诉我们,也是非常棒的主意。比如,一个太长时间才完成的 SQL 查询,或者,在一个特定的 Go 包中发生一个致命的错误。

在这篇博客文章中,我们将告诉你,通过使用已经支持这些特性的一个简单的日志系统一个已存在的数据库库(database library) 怎么去设置来达到这个目的。

使用记录器

logger 是一个为 Go 库和应用程序使用设计的小型库。在这个例子中我们使用了它的三个重要的特性:

  • 它为测量性能提供了一个简单的定时器。
  • 支持复杂的输出过滤器,因此,你可以从指定的包中选择日志。例如,你可以告诉记录器仅从数据库包中输出,并且仅输出超过 500 ms 的定时器日志。
  • 它有一个 Slack 钩子,因此,你可以过滤并将日志输入到 Slack。

让我们看一下在这个例子中,怎么去使用定时器,稍后我们也将去使用过滤器:

package main

import (
    "github.com/azer/logger"
    "time"
)

var (
  users = logger.New("users")
  database = logger.New("database")
)

func main () {
  users.Info("Hi!")

  timer := database.Timer()
  time.Sleep(time.Millisecond * 250) // sleep 250ms
  timer.End("Connected to database")

  users.Error("Failed to create a new user.", logger.Attrs{
    "e-mail": "[email protected]",
  })

  database.Info("Just a random log.")

  fmt.Println("Bye.")
}

运行这个程序没有输出:

$ go run example-01.go
Bye

记录器是缺省静默的,因此,它可以在库的内部使用。我们简单地通过一个环境变量去查看日志:

例如:

$ LOG=database@timer go run example-01.go
01:08:54.997 database(250.095587ms): Connected to database.
Bye

上面的示例我们使用了 database@timer 过滤器去查看 database 包中输出的定时器日志。你也可以试一下其它的过滤器,比如:

  • LOG=*: 所有日志
  • LOG=users@error,database: 所有来自 users 的错误日志,所有来自 database 的所有日志
  • LOG=*@timer,database@info: 来自所有包的定时器日志和错误日志,以及来自 database 的所有日志
  • LOG=*,users@mute: 除了 users 之外的所有日志

发送日志到 Slack

控制台日志是用于开发环境的,但是我们需要产品提供一个友好的界面。感谢 slack-hook, 我们可以很容易地在上面的示例中,使用 Slack 去整合它:

import (
  "github.com/azer/logger"
  "github.com/azer/logger-slack-hook"
)

func init () {
  logger.Hook(&slackhook.Writer{
    WebHookURL: "https://hooks.slack.com/services/...",
    Channel: "slow-queries",
    Username: "Query Person",
    Filter: func (log *logger.Log) bool {
      return log.Package == "database" && log.Level == "TIMER" && log.Elapsed >= 200
    }
  })
}

我们来解释一下,在上面的示例中我们做了什么:

  • 行 #5: 设置入站 webhook url。这个 URL 链接在这里
  • 行 #6: 选择流日志的入口通道。
  • 行 #7: 显示的发送者的用户名。
  • 行 #11: 使用流过滤器,仅输出时间超过 200 ms 的定时器日志。

希望这个示例能给你提供一个大概的思路。如果你有更多的问题,去看这个 记录器的文档。

一个真实的示例: CRUD

crud 是一个用于 Go 的数据库的 ORM 式的类库,它有一个隐藏特性是内部日志系统使用 logger 。这可以让我们很容易地去监视正在运行的 SQL 查询。

查询

这有一个通过给定的 e-mail 去返回用户名的简单查询:

func GetUserNameByEmail (email string) (string, error) {
  var name string
  if err := DB.Read(&name, "SELECT name FROM user WHERE email=?", email); err != nil {
    return "", err
  }

  return name, nil
}

好吧,这个太短了, 感觉好像缺少了什么,让我们增加全部的上下文:

import (
  "github.com/azer/crud"
  _ "github.com/go-sql-driver/mysql"
  "os"
)

var db *crud.DB

func main () {
  var err error

  DB, err = crud.Connect("mysql", os.Getenv("DATABASE_URL"))
  if err != nil {
    panic(err)
  }

  username, err := GetUserNameByEmail("[email protected]")
  if err != nil {
    panic(err)
  }

  fmt.Println("Your username is: ", username)
}

因此,我们有一个通过环境变量 DATABASE_URL 连接到 MySQL 数据库的 crud 实例。如果我们运行这个程序,将看到有一行输出:

$ DATABASE_URL=root:123456@/testdb go run example.go
Your username is: azer

正如我前面提到的,日志是 缺省静默的。让我们看一下 crud 的内部日志:

$ LOG=crud go run example.go
22:56:29.691 crud(0): SQL Query Executed: SELECT username FROM user WHERE email='[email protected]'
Your username is: azer

这很简单,并且足够我们去查看在我们的开发环境中查询是怎么执行的。

CRUD 和 Slack 整合

记录器是为配置管理应用程序级的“内部日志系统”而设计的。这意味着,你可以通过在你的应用程序级配置记录器,让 crud 的日志流入 Slack :

import (
  "github.com/azer/logger"
  "github.com/azer/logger-slack-hook"
)

func init () {
  logger.Hook(&slackhook.Writer{
    WebHookURL: "https://hooks.slack.com/services/...",
    Channel: "slow-queries",
    Username: "Query Person",
    Filter: func (log *logger.Log) bool {
      return log.Package == "mysql" && log.Level == "TIMER" && log.Elapsed >= 250
    }
  })
}

在上面的代码中:

  • 我们导入了 loggerlogger-slack-hook 库。
  • 我们配置记录器日志流入 Slack。这个配置覆盖了代码库中 记录器 所有的用法, 包括第三方依赖。
  • 我们使用了流过滤器,仅输出 MySQL 包中超过 250 ms 的定时器日志。

这种使用方法可以被扩展,而不仅是慢查询报告。我个人使用它去跟踪指定包中的重要错误, 也用于统计一些类似新用户登入或生成支付的日志。

在这篇文章中提到的包

告诉我们 如果你有任何的问题或建议。


via: http://azer.bike/journal/monitoring-slow-sql-queries-via-slack/

作者:Azer Koçulu 译者:qhwdw 校对:wxy

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

到目前为止,糟糕的文档是 Linux 用户最头痛的问题。这里还有一些其他常见的问题。

正如我在 2016 年开源年鉴的“故障排除提示:5 个最常见的 Linux 问题”中所讨论的,对大多数用户而言 Linux 能安装并按照预期运行,但有些不可避免地会遇到问题。过去一年在这方面有什么变化?又一次,我将问题提交给 LinuxQuestions.org 和社交媒体,并分析了 LQ 回复情况。以下是更新后的结果。

1、 文档

文档及其不足是今年最大的痛点之一。尽管开源的方式产生了优秀的代码,但是制作高质量文档的重要性在最近才走到了前列。随着越来越多的非技术用户采用 Linux 和开源软件,文档的质量和数量将变得至关重要。如果你想为开源项目做出贡献,但不觉得你有足够的技术来提供代码,那么改进文档是参与的好方法。许多项目甚至将文档保存在其仓库中,因此你可以使用你的贡献来适应版本控制的工作流。

2、 软件/库版本不兼容

我对此感到惊讶,但软件/库版本不兼容性屡被提及。如果你没有运行某个主流发行版,这个问题似乎更加严重。我个人许多年来没有遇到这个问题,但是越来越多的诸如 AppImageFlatpak 和 Snaps 等解决方案的采用让我相信可能确实存在这些情况。我有兴趣听到更多关于这个问题的信息。如果你最近遇到过,请在评论中告诉我。

3、 UEFI 和安全启动

尽管随着更多支持的硬件部署,这个问题在继续得到改善,但许多用户表示仍然存在 UEFI 和/或 安全启动 secure boot 问题。使用开箱即用完全支持 UEFI/安全启动的发行版是最好的解决方案。

4、 弃用 32 位

许多用户对他们最喜欢的发行版和软件项目中的 32 位支持感到失望。尽管如果 32 位支持是必须的,你仍然有很多选择,但可能会继续支持市场份额和心理份额不断下降的平台的项目越来越少。幸运的是,我们谈论的是开源,所以只要有人关心这个平台,你可能至少有几个选择。

5、 X 转发的支持和测试恶化

尽管 Linux 的许多长期和资深的用户经常使用 X 转发 X-forwarding ,并将其视为关键功能,但随着 Linux 变得越来越主流,它看起来很少得到测试和支持,特别是对较新的应用程序。随着 Wayland 网络透明转发的不断发展,情况可能会进一步恶化。

对比去年的遗留和改进

视频(特别是视频加速器、最新的显卡、专有驱动程序、高效的电源管理)、蓝牙支持、特定 WiFi 芯片和打印机以及电源管理以及挂起/恢复,对许多用户来说仍然是麻烦的。更积极的一点的是,安装、HiDPI 和音频问题比一年前显著降低。

Linux 继续取得巨大的进步,而持续的、几乎必然的改进周期将会确保持续数年。然而,与任何复杂的软件一样,总会有问题。

那么说,你在 2017 年发现 Linux 最常见的技术问题是什么?让我在评论中知道它们。


via: https://opensource.com/article/17/10/top-5-linux-painpoints

作者:Jeremy Garcia 译者:geekpi 校对:wxy

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