Half

Half 查看完整档案

深圳编辑  |  填写毕业院校  |  填写所在公司/组织 github.com/nemolpsky 编辑
编辑

The Long Way Round.

个人动态

Half 赞了文章 · 7月25日

从 Wireshark 看一次请求的过程

从大学有网络课程起就知道有三次握手这回事,但对其中到底发生了什么一直懵懵懂懂,今天打算借助 Wireshark 这一著名的网络数据包分析软件重现一下握手过程。

TCP 头部格式释义

字段对应关系及释义:

TCP头部格式

三次握手

关于 Wireshark

Wireshark

在 Wireshark 中左边实线(图中21 - 28、133 - 134、427 - 428)连起来的一段可以视为为同一次会话内发生的各个阶段,不过图中的是简单顺利的一次会话过程,没有失败重传、分片传输等其他情况。

另外:

  • 每一条中的中括号的为 ACK 为通信控制位,后面的 ACK确认号 表示接收方当前接收到的字节数;
  • SYN、FIN 控制位会占用一个确认号。

文中7001为服务器所在端口号。

三次握手之一

第21个网络包:客户端发送第一个网络包,在头部写入发送方、接收方端口号(用来找到目标套接字),设置客户端初始序号为0, SYN 控制位为1,等待服务器确认,由于此时客户端还未接收过网络包,所以 ACK 控制位为0。

三次握手之二

第22个网络包:服务器收到网络包,同样返回一个响应包,在TCP头部写入发送方、接收方端口号(此时对服务器来说是发送方)、服务端初始序号0, SYN 控制位1,另外还要设置 ACK 控制位为1,表示已收到有效网络包;除此之外可以注意到 ACK号 也被置为1了,就是上文提到的 SYN 控制位占用的一个确认号。

三次握手之三

第23个网络包:客户端收到网络包,发现 SYN 控制位为1,表示连接成功,同时发送一个 ACK 控制位设置为1的网络包给服务器,告知服务器刚才的响应包已收到,这里可以发现序号变为1,那是因为服务器返回的响应包中确认了客户端发送的 SYN 控制位为1,所以序号需要 +1;在服务器收到后三次握手就全部完成了,后面就可以开始收发数据了。

三次握手示意图

后面的[TCP Window Update]是用来窗口更新的,这里不做阐述。

收发数据

客户端发起请求

第25个网络包:客户端发起了一个 HTTP 页面请求,TCP详细信息如下:

No.25

可以看到这个网络包已经不单单是控制信息的传输,开始包含数据,并且数据占用621字节,同时 Wireshark 已经机智在计算下一个客户端发送的包序号了, 621…...

服务器发送确认包

然后服务器告知客户端已收到该请求,响应第26个网络包:

No.26

ACK号 = 前一次的 ACK号 + 本次收到的数据字节数 = 1 + 620 = 621;

序号保持不变,因为本次只是发送控制信息,并没有发送数据。

Tips:在 WireShark 选中某个网络包,如上图No.26,结果No.25前面出现了一个对勾,可以看作是No.26对No.25的消息确认。

服务器发送内容响应请求

在第27个网络包中,服务器针对HTTP请求返回页面内容:

No.27

可以看到这个网络包的数据大小为4152字节,这之后理论上在客户端应该会返回一个 ACK号 为4153的确认包。

客户端发送确认包

No.28

在第28个网络包中,序号就如前面 Wireshark 计算的等于621,ACK号的计算和第26个网络包相似,不再赘述。

关闭连接

在结束最后一个网络包的传输后,再过一段时间(上图中大概5秒),如没有数据往来Web服务器就会关闭连接,至于为什么要延时,大概是为了短时间内如果有后续数据交换,可以减少重新创建套接字建立连接的开销吧。

关闭连接握手之一

服务器生成包含断连控制信息 FIN 的TCP头部发送给客户端。

关闭连接握手之二

客户端告知服务器已收到断连信号 FIN , 因为收到的 FIN 占用一个确认号,所以回复的 ACK号 = 4153 + 1 = 4154。

关闭连接握手之三

客户端在读取所有缓冲区的数据后,也会向服务器发送一个 FIN 为1的网络包。

关闭连接握手之四

服务器同理返回 ACK号 确认收到 FIN 控制信息。

这就是断连操作的四次握手。

关闭连接示意图

附测试数据

测试数据下载链接,过滤规则 tcp.port == 7001

该文章首发于我的个人站点

查看原文

赞 3 收藏 3 评论 2

Half 发布了文章 · 6月27日

systemctl命令介绍和使用

Systemd程序

Systemd其实是Linux系统用来管理系统的一个程序,用来代替原来的init进程(用来管理启动系统其它的服务进程),现在很多Linux发行版都已经自带Systemd程序了。


systemctl命令

1. Unit

systemctl命令是Systemd中最重要的一个命令,用于对服务进行启动,停止等操作,在Systemd中有Unit的概念,每个进程都是一个Unit,总共有十二种Unit类型。

  • Service unit,系统服务
  • Target unit,多个 Unit 构成的一个组
  • Device Unit,硬件设备
  • Mount Unit,文件系统的挂载点
  • Automount Unit,自动挂载点
  • Path Unit,文件或路径
  • Scope Unit,不是由 Systemd 启动的外部进程
  • Slice Unit,进程组
  • Snapshot Unit,Systemd 快照,可以切回某个快照
  • Socket Unit,进程间通信的 socket
  • Swap Unit,swap 文件
  • Timer Unit,定时器

2. 常用命令

# 列出正在运行的Unit
systemctl list-units,可以直接使用systemctl

# 列出所有Unit,包括没有找到配置文件的或者启动失败的
systemctl list-units --all

# 列出所有没有运行的 Unit
systemctl list-units --all --state=inactive

# 列出所有加载失败的 Unit
systemctl list-units --failed

# 列出所有正在运行的、类型为service的Unit
systemctl list-units --type=service

# 显示某个 Unit 是否正在运行
systemctl is-active application.service

# 显示某个 Unit 是否处于启动失败状态
systemctl is-failed application.service

# 显示某个 Unit 服务是否建立了启动链接
systemctl is-enabled application.service

# 立即启动一个服务
sudo systemctl start apache.service

# 立即停止一个服务
sudo systemctl stop apache.service

# 重启一个服务
sudo systemctl restart apache.service

# 重新加载一个服务的配置文件
sudo systemctl reload apache.service

# 重载所有修改过的配置文件
sudo systemctl daemon-reload

systemctl中Unit的配置文件

上面说了每个服务都是一个Unit,那每个Unit都会有它的配置文件,这样启动的时候才知道要按照什么方式去启动。Systemd默认从目录/etc/systemd/system/读取配置文件。但是里面存放的大部分文件都是符号链接,指向目录/usr/lib/systemd/system/,真正的配置文件存放在那个目录。

1. 查看Unit的配置文件

可以使用```systemctl cat```命令来查看服务的配置文件,下面是Mysql的配置文件,很多软件已经支持Systemd程序了,安装的时候会自动配置它的Unit配置文件,例如Mysql和Nginx等等。

```
[root@VM_0_11_centos ~]# systemctl cat mysqld
# /usr/lib/systemd/system/mysqld.service

[Unit]
Description=MySQL Server
Documentation=man:mysqld(8)
Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target

[Install]
WantedBy=multi-user.target

[Service]
User=mysql
Group=mysql
Type=forking
PIDFile=/var/run/mysqld/mysqld.pid
# Disable service start and stop timeout logic of systemd for mysqld service.
TimeoutSec=0
# Execute pre and post scripts as root
PermissionsStartOnly=true
# Needed to create system tables
ExecStartPre=/usr/bin/mysqld_pre_systemd
# Start main service
ExecStart=/usr/sbin/mysqld --daemonize --pid-file=/var/run/mysqld/mysqld.pid $MYSQLD_OPTS
# Use this to switch malloc implementation
EnvironmentFile=-/etc/sysconfig/mysql
# Sets open_files_limit
LimitNOFILE = 5000
Restart=on-failure
RestartPreventExitStatus=1
PrivateTmp=false

```

2. Unit配置文件的含义


可以看到Unit配置文件有很多标签,不同的标签都代表了不同的意思,这里只列出部分介绍,可以去官网查看Unit配置文件文档介绍,https://www.freedesktop.org/software/systemd/man/systemd.unit.html。

- Unit
   - Description,服务的描述
   - Documentation,文档介绍
   - After,该服务要在什么服务启动之后启动,比如Mysql需要在network和syslog启动之后再启动
- Install
   - WantedBy,值是一个或多个Target,当前Unit激活时(enable)符号链接会放入/etc/systemd/system目录下面以Target名+.wants后缀构成的子目录中
   - RequiredBy,它的值是一个或多个Target,当前Unit激活(enable)时,符号链接会放入/etc/systemd/system目录下面以Target名+.required后缀构成的子目录中
   - Alias,当前Unit可用于启动的别名
   - Also,当前Unit激活(enable)时,会被同时激活的其他Unit
- Service
   - Type,定义启动时的进程行为。它有以下几种值。
   - Type=simple,默认值,执行ExecStart指定的命令,启动主进程
   - Type=forking,以 fork 方式从父进程创建子进程,创建后父进程会立即退出
   - Type=oneshot,一次性进程,Systemd 会等当前服务退出,再继续往下执行
   - Type=dbus,当前服务通过D-Bus启动
   - Type=notify,当前服务启动完毕,会通知Systemd,再继续往下执行
   - Type=idle,若有其他任务执行完毕,当前服务才会运行
   - ExecStart,启动当前服务的命令
   - ExecStartPre,启动当前服务之前执行的命令
   - ExecStartPost,启动当前服务之后执行的命令
   - ExecReload,重启当前服务时执行的命令
   - ExecStop,停止当前服务时执行的命令
   - ExecStopPost,停止当其服务之后执行的命令
   - RestartSec,自动重启当前服务间隔的秒数
   - Restart,定义何种情况 Systemd 会自动重启当前服务,可能的值包括always(总是重启)、on-success、on-failure、on-abnormal、on-abort、on-watchdog
   - TimeoutSec,定义 Systemd 停止当前服务之前等待的秒数
   - Environment,指定环境变量

自定义服务启动

既然Systemd的作用就是控制服务的启动,那么就可以把自己的服务添加进去,就可以直接使用systemctl命令来控制服务的启动,或者是设置开机自动启动等等。

1. 创建Unit配置文件

在```/usr/lib/systemd/system```目录中创建自己的配置文件,一般都是```.service```结尾,例如这里创建了一个```test-sh.service```配置文件,这个Unit是为了启动我们自己的一个shell脚本。

```
# /usr/lib/systemd/system/test-sh.service
[Unit]
Description= test sh log

[Service]
ExecStart=/opt/dev/shell/test.sh
Type=forking
KillMode=process
Restart=on-failure
RestartSec=30s

[Install]
WantedBy=multi-user.target

```

2. 创建脚本


在上面配置文件指定的启动路径```/opt/dev/shell/```下创建shell脚本,这里只是每秒打印当前时间,并输出到一个文本中。
```
#!/bin/bash
while true
do
sleep 1
 date=`date -d today +"%Y-%m-%d %T"`
 echo ${date} >> /opt/dev/shell/test.txt
done
```

3. 载入配置文件并启动

使用```systemctl daemon-reload```命令来载入新添加的配置文件,然后使用```systemctl start test-sh.service```命令启动,再使用```systemctl status test-sh.service```命令来查看状态,可以看到已经启动,```/opt/dev/shell/test.txt```也确实在不停的写入内容,最后使用```systemctl stop test-sh.service```命令停止服务,可以看到状态也是停止了。

注意的是修改配置文件后一定要使用```systemctl daemon-reload```命令来载入新添加的配置文件,然后再启动服务。

```
[root@VM_0_11_centos ~]# systemctl start test-sh.service
^C
[root@VM_0_11_centos ~]# systemctl status test-sh.service
● test-sh.service - test sh log
   Loaded: loaded (/usr/lib/systemd/system/test-sh.service; enabled; vendor preset: disabled)
   Active: activating (start) since Fri 2020-06-26 05:46:45 CST; 11s ago
   Control: 9295 (test.sh)
   CGroup: /system.slice/test-sh.service
       ├─9295 /bin/bash /opt/dev/shell/test.sh
       └─9343 sleep 1

Jun 26 05:46:45 VM_0_11_centos systemd[1]: Starting test sh log...
[root@VM_0_11_centos ~]# systemctl stop test-sh.service
[root@VM_0_11_centos ~]# systemctl status test-sh.service
● test-sh.service - test sh log
   Loaded: loaded (/usr/lib/systemd/system/test-sh.service; enabled; vendor preset: disabled)
   Active: inactive (dead) since Fri 2020-06-26 05:47:52 CST; 2s ago
  Process: 9295 ExecStart=/opt/dev/shell/test.sh (code=killed, signal=TERM)

Jun 26 05:46:45 VM_0_11_centos systemd[1]: Starting test sh log...
Jun 26 05:47:52 VM_0_11_centos systemd[1]: Stopped test sh log.
```

查看Unit启动日志

Systemd统一管理了所有Unit的启动日志,因此只需要使用journalctl命令就可以查看到服务的日志

# 查看所有日志(默认情况下 ,只保存本次启动的日志)
journalctl

# 查看指定时间的日志
journalctl --since="2012-10-30 18:17:16"
journalctl --since "20 min ago"
journalctl --since yesterday
journalctl --since "2015-01-10" --until "2015-01-11 03:00"
journalctl --since 09:00 --until "1 hour ago"

# 显示尾部的最新10行日志
journalctl -n

# 显示尾部指定行数的日志
journalctl -n 20

# 实时滚动显示最新日志
journalctl -f

# 查看指定服务的日志
journalctl /usr/lib/systemd/systemd

# 查看指定进程的日志
journalctl _PID=1

# 查看某个路径的脚本的日志
journalctl /usr/bin/bash

# 查看指定用户的日志
journalctl _UID=33 --since today

# 查看某个 Unit 的日志
journalctl -u nginx.service
journalctl -u nginx.service --since today

# 实时滚动显示某个 Unit 的最新日志
journalctl -u nginx.service -f

# 合并显示多个 Unit 的日志
$ journalctl -u nginx.service -u php-fpm.service --since today
查看原文

赞 0 收藏 0 评论 0

Half 提出了问题 · 6月5日

大量调用微信更新会员信息接口如何提高速度

问题描述

https://developers.weixin.qq....
需要调用微信的一个更新会员信息的接口,目的是为了修改微信那边会员卡的一个字段,大约有260万的会员,也就是要请求260万次,测试发现是调用一次大概要0.5秒左右,这样的话速度就会特别慢。

问题出现的环境背景及自己尝试过哪些方法

1.目前想到的是使用Http保持长连接来减少每次请求倒要建立请求和断开请求的耗时,但是时间还是一样的长。
2.另一个就是多线程并发跑。

相关代码

下面是使用Hutool工具,开启了keepAlive字段来保持长连接,但是没有效果,不知道是不是因为用法错误还是什么原因。

        String accessToken = service.getAccessToken();
        logger.info(accessToken);
        String url = "https://api.weixin.qq.com/card/membercard/updateuser?access_token=" + accessToken;
        String json = "{\"code\":\"WMMBC0436000000106879\",\"card_id\":\"pqBpd1J0cyIrRwaSvJoFjKoHSLuw\",\"custom_field_value1\":\"¥2\"}";
        logger.info(url);
        for (int i = 0; i < 10; i++) {
            Stopwatch started = Stopwatch.createStarted();
            String result = HttpRequest
                    .post(url)
                    .header("Content-Type", "application/json")
                    .keepAlive(true)
                    .body(json)
                    .execute()
                    .body();
            logger.info("updateMemberInfo2: [{}]", started.elapsed(TimeUnit.MILLISECONDS));
            logger.info("result:", result);
         }

疑问

现在想知道这种大量的请求,怎么才能提高速度,期望值实在2-4个小时之内能够完成260万的提交。
此外就是想知道Http长连接这种方法为什么没效果,应该怎么样使用才有效果呢?

关注 3 回答 2

Half 收藏了文章 · 6月1日

linux 安装PostgreSQL

  1. 把最新的rpm包添加到系统库
    PostgreSQL会为所有的Linux平台发布rpm包, 而且会比其他的的库更新的更快.
    地址:postresSQL linux
    rpm -Uvh https://download.postgresql.org/pub/repos/yum/11/redhat/rhel-7-x86_64/pgdg-centos11-11-2.noarch.rpm
  2. 列出可用安装包
    yum list postgres*
  3. 安装PostgreSQL
    yum install -y postgresql11-server.x86_64
  4. 初始化数据库
    /usr/pgsql-11/bin/postgresql-11-setup initdb 仅需执行一次
  5. 启动PostgreSQL
    systemctl start postgresql-11
  6. 设置自启动
    systemctl enable postgresql-11
  7. 查看运行状态
    systemctl status postgresql-11

    clipboard.png

  8. 开机启动
    chkconfig postgresql-11 on
  9. 重置密码
    1) sudo -u postgres psql
    2) ALTER USER postgres WITH PASSWORD 'postgres';
    3) 退出 \q
  10. 开启远程访问
    vi /var/lib/pgsql/11/data/postgresql.conf
    修改#listen_addresses = 'localhost' 为 listen_addresses='*',建议只监听内网IP
  11. 修改客户端认证配置文件pg_hba.conf
    vi /var/lib/pgsql/11/data/pg_hba.conf
    将IPv4区下的127.0.0.1/32修改为0.0.0.0/0; 将ident修改为md5
  12. 重启服务
    service postgresql-11 restart
  13. 开放端口
    firewall-cmd --zone=public --add-port=5432/tcp --permanent
  14. 重载防火墙
    firewall-cmd --reload
查看原文

Half 赞了文章 · 6月1日

linux 安装PostgreSQL

  1. 把最新的rpm包添加到系统库
    PostgreSQL会为所有的Linux平台发布rpm包, 而且会比其他的的库更新的更快.
    地址:postresSQL linux
    rpm -Uvh https://download.postgresql.org/pub/repos/yum/11/redhat/rhel-7-x86_64/pgdg-centos11-11-2.noarch.rpm
  2. 列出可用安装包
    yum list postgres*
  3. 安装PostgreSQL
    yum install -y postgresql11-server.x86_64
  4. 初始化数据库
    /usr/pgsql-11/bin/postgresql-11-setup initdb 仅需执行一次
  5. 启动PostgreSQL
    systemctl start postgresql-11
  6. 设置自启动
    systemctl enable postgresql-11
  7. 查看运行状态
    systemctl status postgresql-11

    clipboard.png

  8. 开机启动
    chkconfig postgresql-11 on
  9. 重置密码
    1) sudo -u postgres psql
    2) ALTER USER postgres WITH PASSWORD 'postgres';
    3) 退出 \q
  10. 开启远程访问
    vi /var/lib/pgsql/11/data/postgresql.conf
    修改#listen_addresses = 'localhost' 为 listen_addresses='*',建议只监听内网IP
  11. 修改客户端认证配置文件pg_hba.conf
    vi /var/lib/pgsql/11/data/pg_hba.conf
    将IPv4区下的127.0.0.1/32修改为0.0.0.0/0; 将ident修改为md5
  12. 重启服务
    service postgresql-11 restart
  13. 开放端口
    firewall-cmd --zone=public --add-port=5432/tcp --permanent
  14. 重载防火墙
    firewall-cmd --reload
查看原文

赞 2 收藏 2 评论 0

Half 提出了问题 · 5月26日

两个不同系统拉取数据如何最大限度提高实时性

项目背景

目前有一个订单系统对外提供了一个查询订单的接口,然后另一个管理系统根据时间和订单id等参数去查询,是直接使用http请求来获取数据的,目前是每5分钟拉取一次数据,因为数据量不大,5分钟估计也就几十单,但是现在需求是想尽量压缩,甚至说是要求实时。

疑问

请问以现有的条件来看有办法实现吗?个人认为除非是对方推送数据过来才有可能实现实时,不可能说把定时请求的频率压缩到很短,比如几秒一次,这样性能很糟糕,而且从请求到订单系统再返回响应给管理系统,然后再处理数据入库也需要时间,个人感觉以现有情况肯定无法实现实时,请问还有别的思路吗?### 问题描述

关注 1 回答 0

Half 回答了问题 · 5月23日

解决Python 3.8 import records报错

自己解决了,解决方法是把所有使用pip下载的库都删光了,然后又重新下载了,这次下载是使用的pip3命令,不知道有没有关系,但是已经不报错了。

关注 2 回答 2

Half 赞了回答 · 5月21日

RedisTemplate如何检查一个key是否存在?

方法:

public Boolean hasKey(K key)

关注 2 回答 1

Half 收藏了文章 · 5月18日

扎心!天天写代码,方向真的对吗?

简介: 每个人的时间都是有限的,在有限的时间里选择一项值得投入的技术会变得尤为重要。

“每个人的时间都是有限的,在有限的时间里选择一项值得投入的技术会变得尤为重要。”

笔者从 2008 年开始工作到现在也有 12 个年头了,一路走来都在和数据打交道,做过很多大数据底层框架内核的开发(Hadoop,Pig,Hive,Tez,Spark),也做过多年上层数据计算框架(Livy, Zeppelin)以及数据应用开发,包括数据处理,数据分析以及机器学习。现在是 Apache Member 以及多个 Apache 项目的 PMC 。2018 年加入阿里巴巴实时计算团队专注在 Flink 的研发。

今天我想结合自己过去的职业经历来聊聊如何评估一项技术是否值得学习。我一直在大数据这个圈子,从最初的 Hadoop 到后来的 Hadoop 生态项目 Pig,Hive,Tez,然后又到新一代的计算引擎 Spark ,再到最近在做的 Flink ,大数据计算引擎贯穿我的整个职业生涯。我个人来说是比较幸运的,在每个阶段都在做比较火的技术,当时更多的是凭着自己的兴趣和直觉在选择技术类型。现在回过头来看我觉得需要从下面 3 个大的纬度来评估一项技术是否值得学习。

1、技术深度
2、生态广度
3、进化能力

2 640.png

01 技术深度

技术深度是指这项技术的根基是否扎实,护城河是否够宽够深,是否很容易被其他技术所替代。通俗的来说就是这项技术是否解决了其他技术所不能解决的有重要价值的问题。这里有两个要点:

1、这个问题没有人能解,是这项技术首先解决了这个问题。
2、解决这个问题能够带来重大价值。

拿我职业生涯开始阶段学习的 Hadoop 为例。当时 Hadoop 刚出来的时候是一项革命性的技术,因为当时除了 Google 宣称自己内部有一套 GFS 和 MapReduce 系统外,业界其他公司都没有一套完整的海量数据解决方案。而随着互联网技术的发展,数据量与日俱增,处理海量数据的能力迫在眉睫。Hadoop 的诞生正好解决了这一燃眉之急。

随着技术的发展, Hadoop 的处理海量数据能力的优势慢慢被人习惯,相反 Hadoop 存在的缺陷被人不断诟病(性能差,MapReduce 编写复杂等等)。而这时候Spark应运而生,解决了 Hadoop MapReduce 计算引擎的顽疾。Spark 远超过 Hadoop 的计算性能以及极其优雅简单的 API 迎合了当时用户的需求,受到了广大大数据工程师的热捧。

现在我在阿里巴巴从事的是关于 Flink 的研发工作,主要原因是我看到了工业界对实时性的需求以及 Flink 在实时计算这个领域的霸主地位。之前大数据遇到的最大挑战在于数据规模大(所以大家会称之为“大数据”),经过工业界多年的努力和实践,规模大这个问题基本已经解决了。接下来几年,更大的挑战在于速度,也就是实时性。而大数据的实时性并不是指简单的传输数据或者处理数据的实时性,而是从端到端的实时,任何一个步骤速度慢了,就影响整个大数据系统的实时性。

在 Flink 看来, Everything is stream 。Flink 的以 Stream 为核心的架构是业界独一无二的,由此而产生的性能优越,高扩展性,端到端 Exactly Once 等特性,更是使得 Flink 在流计算领域是当之无愧的王者。

目前主流的流计算引擎有 3 个:Flink、Storm 和 SparkStreaming 。

3 640.png

注:Spark Streaming 只能选择搜索字词,理论上这样的对比是不严谨的。但作为趋势,我们更关注的是其变化曲线,实际影响应该不大。

从上面的 Google trends 曲线可以看出,Flink 处在一个快速增长期, Storm 的热度在逐年下降,而 Spark Streaming 几乎进入了平台期。这就证明了 Flink 在流计算领域的根基之深,目前来看还没有谁可以超越 Flink 在流计算领域的霸主地位。

02 生态广度

一项技术只有技术深度是不够的,因为一项技术只能专注于做好一件事情,如果要解决实际生活中的复杂问题,必定要和其他技术整合联动,这就要求这项技术具有足够宽的生态广度。生态的广度有 2 个纬度可以衡量:

1、上下游生态。上下游生态指从数据流的角度来说的数据上下游。
2、垂直领域生态。垂直领域生态是指某个细分领域或者应用场景的整合。

4 640.png

当 Hadoop 刚出来的时候只有 2 个基本的组件:HDFS 和 MapReduce ,分别解决了海量存储和分布式计算的问题。但随着发展,需要解决的问题越来越复杂,HDFS 和 MapReduce 已经不能很方便的解决一些复杂问题,这时候 Hadoop 的其他生态项目应运而生,比如 Pig,Hive,HBase 等等从垂直领域生态这个角度解决了 Hadoop 不容易或者不能解决的问题。

Spark 亦是如此,一开始的 Spark 是要替换原来的 MapReduce 计算引擎,后来 Spark 发展了各种语言接口,各种上层框架,比如 Spark SQL,Spark Structured Streaming,MLlib,GraphX 等等,大大丰富了 Spark 的使用场景,扩展了Spark的垂直领域生态。Spark 对各种 Data Source 的支持,更是让 Spark 这个计算引擎和存储结成了联盟,建立了强大的上下游生态系统,为端到端的解决方案奠定了基础。

我现在做的 Flink 项目的生态仍然处于起步阶段,当时我加入阿里巴巴正不仅仅是看到了 Flink 作为流计算引擎的霸主地位,更是因为看到了 Flink 生态的机会。大家如果从我的职业生涯来看,会发现些许变化,我在从一开始专注于大数据的核心框架层慢慢在往周边生态项目发展。一个主要的原因是我对整个大数据行业的判断:大数据上半场战斗集中在底层框架,目前已经接近尾声,未来的底层大数据生态圈中将不再有那么多的新的技术和框架,每个细分领域都将优胜劣汰,走向成熟,更加集中化。下半场战斗的重点讲从底层走向上层,走向生态。之前的大数据创新更偏向于 IAAS 和 PAAS ,未来你将看到更多 SAAS 类型的大数据产品和创新。

5 640.png

每次谈到大数据的生态,我都拿出上面这张图。这张图基本上把你日常需要处理的大数据场景都包括进来。从最左边的数据生产者,到数据收集,数据处理,然后再到数据应用(BI + AI)。你会发现 Flink 可以应用在每一个步骤。不仅涉及到大数据,也涉及到 AI ,但是 Flink 的强项在于流计算处理,在其他领域的生态仍在起步阶段,我个人正在做的工作就是完善 Flink 在上面这张图上端到端的能力。

03 进化能力

一项技术如果技术深度和生态广度都没有问题,那么至少说明这项技术在当下是值得学习的。但是投资一项技术还需要从时间这个纬度上考量。你肯定不希望自己学习的技术很快就被淘汰,每年都要去学习一项新技术。所以一项值得投资学习的技术必定需要具有持久的进化能力。

我最初学的 Hadoop 到现在已经 10 多年了,现在仍然被广泛使用着。虽然现在有很多公有云厂商在抢占 Hadoop 的市场,但你不得不承认如果一家公司要成立一个大数据部门,第一件事恐怕就是建一个 Hadoop 集群吧。当我们现在谈论 Hadoop 的时候,他已经不是当初的 Hadoop 了,他更多的是 Hadoop 生态圈的统称。大家有空可以看看 Cloudera CPO Arun 的这篇文章【1】,我对其中的观点非常认同。

【1】:
https://medium.com/@acmurthy/hadoop-is-dead-long-live-hadoop-f22069b264ac

Spark 项目就更不用多说了。Spark 经过 14,15 年爆发,现在已经进入平稳期。但是 Spark 仍在进化,仍在拥抱变化。Spark on K8s 就是 Spark 拥抱云原生的最好佐证。现在 Spark 社区炙手可热的Delta,MLFlow 更是 Spark 的强大的进化能力的佐证。现在的 Spark 也不仅仅是当年要取代 MapReduce 的那个 Spark ,更多是一个适用于多种场景的通用计算引擎。

我从 18 年加入阿里巴巴到现在差不多 1 年半时间,在这一年半的时间了,我正好见证了 Flink 的进化能力。

首先 Flink 经过几个大版本的发布,融入了 Blink 的大部分功能,将 Flink SQL 的能力提升了一大截。

其次 Flink 对 K8s 的支持,对 Python 的支持,对 AI 的支持都在向人们证明这Flink自身强大的进化能力。

小 Tips

除了以上的 3 大维度,在这里我还想分享下我在评估一项新技术时候的一些小技巧。

1、利用 Google trends 。Google trends 能很好的反映一项技术的发展势头,上面提到的趋势图很好的比较了 3 大流计算引擎 Flink , Spark Streaming 和 Storm ,我们不难得出结论:Flink 是流计算领域的王者。

2、查看 GitHub 上的awesome。一项技术受欢迎的一个指标是 GitHub 上的 awesome list,你可以看看这个 awesome list 的 GitHub star 数。此外你可以抽一个周末的时间看看这个 awesome list 上的内容,因为上面基本上是关于这项技术的精华内容,通过这些内容你大致可以判断出这项技术的价值。

3、看看技术网站上是否有一些技术布道者为这项技术背书(我个人经常会看medium.com)。技术圈里通常有这样一群人,他们对技术很执着,也很有品位。如果一项技术真的很好,那么就会有技术布道者无偿的为这项技术背书,分享如何这项技术的使用心得。

04 总结

每个人的时间都是有限的,在有限的时间里选择一项值得投入的技术会变得尤为重要。

以上是我对如何评估一项技术是否值得学习的一些思考,也算是对我自己事业生涯在技术选型方面的一个小小的总结和回顾,希望我的这些思考能对大家的职业生涯有所帮助。

作者介绍:

章剑锋(简锋),开源界老兵,Github ID:@zjffdu,Apache Member,曾就职于 Hortonworks,目前在阿里巴巴计算平台事业部任高级技术专家,并同时担任 Apache Tez、Livy 、Zeppelin 三个开源项目的 PMC ,以及 Apache Pig 的 Committer。有幸很早就接触了大数据和开源,希望可以在开源领域为大数据和数据科学做点贡献。

查看原文

Half 提出了问题 · 5月17日

解决Python 3.8 import records报错

因为是初学python,所有没有弄环境隔离那些的,然后用的PyCharm 2020.1 x64开发,最开始是好的,到后面突然不行了,不知道是不是导包冲突还什么,查了点资料,删除pyc文件重新编译没用,然后当前目录下也没用重名的文件,不知道这是什么原因。

image.png

代码:

import records
print("start")

报错信息:

E:\python3.8\python.exe E:/python-workspace/db2.py
Traceback (most recent call last):
  File "E:/python-workspace/db2.py", line 4, in <module>
    import records
  File "E:\python3.8\Lib\site-packages\records.py", line 11, in <module>
    from sqlalchemy import create_engine, exc, inspect, text
  File "E:\python3.8\Lib\site-packages\sqlalchemy\__init__.py", line 12, in <module>
    from sqlalchemy.sql import (
  File "E:\python3.8\Lib\site-packages\sqlalchemy\sql\__init__.py", line 7, in <module>
    from sqlalchemy.sql.expression import (
  File "E:\python3.8\Lib\site-packages\sqlalchemy\sql\expression.py", line 32, in <module>
    from sqlalchemy import util, exc
  File "E:\python3.8\Lib\site-packages\sqlalchemy\util\__init__.py", line 7, in <module>
    from .compat import callable, cmp, reduce, defaultdict, py25_dict, \
  File "E:\python3.8\Lib\site-packages\sqlalchemy\util\compat.py", line 202, in <module>
    time_func = time.clock
AttributeError: module 'time' has no attribute 'clock'

关注 2 回答 2

认证与成就

  • 获得 54 次点赞
  • 获得 14 枚徽章 获得 0 枚金徽章, 获得 3 枚银徽章, 获得 11 枚铜徽章

擅长技能
编辑

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2018-03-21
个人主页被 855 人浏览