Prometheus内部实现(二)

观察事物,需要提纲挈领!软件的启动是观察软件最好的入口! Prometheus server实现入口文件在cmd/prometheus/main.go。 Prometheus的配置由两个部分构成: 配置文件:prometheus.yml 启动flag:启动时指定 入口函数如下: func main() { ... } 初始化一个flagConfig,这个配置贯穿了整个程序 cfg := flagConfig{ notifier: notifier.Options{ Registerer: prometheus.DefaultRegisterer, }, web: web.Options{ Registerer: prometheus.DefaultRegisterer, Gatherer: prometheus.DefaultGatherer, }, promlogConfig: promlog.Config{}, } 使用kingpin注册flag a := kingpin.New(filepath.Base(os.Args[0]), "The Prometheus monitoring server").UsageWriter(os.Stdout) a.Version(version.Print("prometheus")) a.HelpFlag.Short('h') a.Flag("config.file", "Prometheus configuration file path."). Default("prometheus.yml").StringVar(&cfg.configFile) a.Flag("web.listen-address", "Address to listen on for UI, API, and telemetry."). Default("0.0.0.0:9090").StringVar(&cfg.web.ListenAddress) ... _, err := a.Parse(os.Args[1:]) if err != nil { fmt.Fprintln(os.Stderr, errors.Wrapf(err, "Error parsing commandline arguments")) a.Usage(os.Args[1:]) os.Exit(2) } 加载配置文件,检查配置合法性 ...

2021-03-15 · Jerry Wang

Prometheus内部实现(一)

Prometheus在监控界为什么这么🔥? Prometheus具体是怎么实现的? 人如其名,产品亦是!Prometheus就是火种,照耀在当前的监控世界! Prometheus这把火,在我看来,火在三个方面: 系出名门:CNCF的第二个项目,CNCF的老大叫K8S,老大对老二很照顾,监控首选。 门庭若市:开源,大厂竞相争用。 简单易用:架构简单,配置简单,上下游打通。 大家都在用,而且用起来很方便的确是我们选择产品的方法,但是作为开发人员,还是需要了解一下其内部的实现。这个系列,主要根据Prometheus的代码和文档,梳理Prometheus的内部实现。 总体架构 Prometheus从配置的jobs中抓取metrics,存储在本地存储或者外部存储中,在metrics上运行规则聚合多维度的数据或者生成告警。Grafana或者自带的web UI能够方便的展示数据。 Prometheus的组件包括: server:负责抓取metrics,存储metrics,分析、聚合metrics client library:多种语言的客户端库,方便实现 push gateway:短期存活服务metrics推送网关 exporters:比如监控节点的node_exporter,监控MySQL的mysqld_expoter等等 alertmanager:alertmanager负责告警的发送 从总体架构,我们可以了解各种组件,以及数据的流向,现在我们开始研究Prometheus server的内部实现。 Server实现架构 server启动的时候,根据配置文件prometheus.yml和flag决定各种配置,配置文件包括全局配置、抓取目标配置和规则配置等等。scrape_configs配置了抓取的目标,Prometheus支持动态获取目标,Service discovery读取静态配置的目标或者周期更新动态目标,添加到scrape manager,scrape manager负责抓取目标,抓取实际是一个HTTP请求,即各种exporters实际上就是一个简单的HTTP服务,负责暴露各种应用的指标。scrape manager抓取指标后,将数据交给fanout storage,fanout storage负责数据存储,支持本地存储和外部存储。rule manager根据规则,聚合指标存储到fanout storage,或者生成告警发送给alert manager。Prometheus也实现了各种web接口,使用promQL进行数据的查询。 server的组件包括: Termination handler. Scrape discovery manager. Notify discovery manager. Scrape manager. Reload handler. Rule manager. TSDB. Web handler. Notifier. 了解了server的基本架构,下面开始研究server的配置。 Prometheus.yml global: scrape_interval: 15s evaluation_interval: 15s rule_files: # - "first.rules" # - "second.rules" scrape_configs: - job_name: prometheus static_configs: - targets: ['localhost:9090'] 这是官网提供的一个简单的配置文件,包含了三个部分:全局配置、规则配置和抓取配置。global包括全局的配置,rule_files配置规则文件,这里没有配置,scrape_configs配置抓取目标。抓取目标是一个列表,包括多个job,每个job有一个job_name,目标配置以及其他配置,目标配置因为支持多种目标源,所以这块在代码中的实现比较复杂。 ...

2021-03-14 · Jerry Wang

K8s Yaml配置文件

1、Redis Deployment部署示例yaml 先来看一个部署yaml示例文件: # application/guestbook/redis-master-deployment.yaml apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2 kind: Deployment metadata: name: redis-master labels: app: redis spec: selector: matchLabels: app: redis role: master tier: backend replicas: 1 template: metadata: labels: app: redis role: master tier: backend spec: containers: - name: master image: redis # or just image: redis resources: requests: cpu: 100m memory: 100Mi ports: - containerPort: 6379 通过执行命令kubectl create -f redis-master-deployment.yaml,可以创建1个Redis master Pod。如果我想通过yaml文件创建3个Pod,怎么办? ...

2019-11-18 · Jerry Wang

K8s官网留言板demo

https://kubernetes.io/docs/tutorials/stateless-application/guestbook/#start-up-the-redis-master 1、部署redis-master Deployment Step1 编辑redis-master-deployment.yaml # application/guestbook/redis-master-deployment.yaml apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2 kind: Deployment metadata: name: redis-master labels: app: redis spec: selector: matchLabels: app: redis role: master tier: backend replicas: 1 template: metadata: labels: app: redis role: master tier: backend spec: containers: - name: master image: redis # or just image: redis resources: requests: cpu: 100m memory: 100Mi ports: - containerPort: 6379 Step2 执行命令 # 创建Deployment kubectl create -f redis-master-deployment.yaml # 查看pods kubectl get pods 2、部署redis-master Service Step1 编辑redis-master-service.yaml # application/guestbook/redis-master-service.yaml apiVersion: v1 kind: Service metadata: name: redis-master labels: app: redis role: master tier: backend spec: ports: - port: 6379 targetPort: 6379 selector: app: redis role: master tier: backend Step2 执行命令 # 创建DService kubectl create -f redis-master-service.yaml # 查看service kubectl get services 3、部署redis-slave Deployment Step1 编辑redis-slave-deployment.yaml # application/guestbook/redis-slave-deployment.yaml apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2 kind: Deployment metadata: name: redis-slave labels: app: redis spec: selector: matchLabels: app: redis role: slave tier: backend replicas: 2 template: metadata: labels: app: redis role: slave tier: backend spec: containers: - name: slave image: gcr.io/google_samples/gb-redisslave:v3 resources: requests: cpu: 100m memory: 100Mi env: - name: GET_HOSTS_FROM value: dns # Using `GET_HOSTS_FROM=dns` requires your cluster to # provide a dns service. As of Kubernetes 1.3, DNS is a built-in # service launched automatically. However, if the cluster you are using # does not have a built-in DNS service, you can instead # access an environment variable to find the master # service's host. To do so, comment out the 'value: dns' line above, and # uncomment the line below: # value: env ports: - containerPort: 6379 Step2 执行命令 kubectl create -f redis-slave-deployment.yaml kubectl get pods 4、部署redis slave Service Step1 编辑redis-slave-service.yaml # application/guestbook/redis-slave-service.yaml apiVersion: v1 kind: Service metadata: name: redis-slave labels: app: redis role: slave tier: backend spec: ports: - port: 6379 selector: app: redis role: slave tier: backend Step2 执行命令 kubectl create -f redis-slave-service.yaml kubectl get services 5、部署guestbook Deployment Step1 编辑frontend-deployment.yaml # application/guestbook/frontend-deployment.yaml apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2 kind: Deployment metadata: name: frontend labels: app: guestbook spec: selector: matchLabels: app: guestbook tier: frontend replicas: 3 template: metadata: labels: app: guestbook tier: frontend spec: containers: - name: php-redis image: gcr.io/google-samples/gb-frontend:v6 # 官网上使用的是v4版,在使用中出现ImageInspectErr,镜像出现问题,升级为v6 resources: requests: cpu: 100m memory: 100Mi env: - name: GET_HOSTS_FROM value: dns # Using `GET_HOSTS_FROM=dns` requires your cluster to # provide a dns service. As of Kubernetes 1.3, DNS is a built-in # service launched automatically. However, if the cluster you are using # does not have a built-in DNS service, you can instead # access an environment variable to find the master # service's host. To do so, comment out the 'value: dns' line above, and # uncomment the line below: # value: env ports: - containerPort: 80 Step2 执行命令 kubectl create -f frontend-deployment.yaml kubectl get pods 6、部署guestbook Service Step1 编辑frontend-service.yaml # application/guestbook/frontend-service.yaml apiVersion: v1 kind: Service metadata: name: frontend labels: app: guestbook tier: frontend spec: # comment or delete the following line if you want to use a LoadBalancer type: NodePort # if your cluster supports it, uncomment the following to automatically create # an external load-balanced IP for the frontend service. # type: LoadBalancer ports: - port: 80 selector: app: guestbook tier: frontend Step2 执行命令 kubectl create -f frontend-service.yaml kubectl get services 然后使用node的IP和端口,就可以访问服务了。 ...

2019-10-20 · Jerry Wang

K8s集群搭建

1、节点 节点 IP master 192.168.124.100 node1 192.168.124.101 node2 192.168.124.102 node3 192.168.124.103 2、docker安装 安装使用官方源,安装命令如下: # 下载仓库 cd /etc/yum.repos.d wget https://download.docker.com/linux/centos/docker-ce.repo yum makecache fast # 安装docker yum install docker-ce docker-ce-cli containerd.io # 启动docker systemctl enable docker && systemctl start docker 3、kubernetes安装 # 所有节点执行 # 添加仓库 cat <<EOF > /etc/yum.repos.d/kubernetes.repo [kubernetes] name=Kubernetes baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/ enabled=1 gpgcheck=1 repo_gpgcheck=1 gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg EOF # 更新yum cache yum makecache fast # kubeadm初始化会报错, 需要执行下列命令 # 1、关闭firewalld systemctl diable firewalld && systemctl stop firewalld # 2、关闭selinux setenforce 0 && sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config # 3、关闭swap swapoff -a && sed -i '/ swap / s/^/#/' /etc/fstab # 4、设置网络 touch /etc/sysctl.d/k8s.conf cat > /etc/sysctl.d/k8s.conf <<EOF net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 net.ipv4.ip_forward = 1 EOF modprobe br_netfilter && sysctl -p /etc/sysctl.d/k8s.conf # master节点执行 yum install kubeadm kubectl kubelet # 所有node节点执行 yum install kubeadm kubelet # 启动实际运行容器的服务kubelet systemctl enable kubelet && systemctl start kubelet # 现在执行kubelet会报错,不用管 # kubeadm init或join之后,systemd会自动拉起kubelet # kubeadm是集群管理工具 # kubelet负责运行pods # kubectl是客户端,负责和kube-apiserver通信 # 用类比解释的话,kubectl是curl,kube-apiserver是服务器 # kube-controller-manager是控制器 # kube-scheduler是调度器 # kube-proxy负责网络通信 # pause是pod空闲运行的镜像 # etcd用于分布式存储集群信息 # 由于kubeadm使用镜像拉起k8s,但是被墙了,所以在可以翻墙的主机上下载镜像,然后使用下列命令导出镜像 # docker save -o package.tar.gz image1:latest # 使用下面命令导入镜像 # docker load -i package.tar.gz # 获取需要下载的镜像列表 kubeadm config images list # 输出如下,master表示在主节点安装,node表示在从节点安装 k8s.gcr.io/kube-apiserver:v1.16.1 # master k8s.gcr.io/kube-controller-manager:v1.16.1 # master k8s.gcr.io/kube-scheduler:v1.16.1 # master k8s.gcr.io/kube-proxy:v1.16.1 # master node k8s.gcr.io/pause:3.1 # node k8s.gcr.io/etcd:3.3.15-0 # master k8s.gcr.io/coredns:1.6.2 # master node # 很不幸,被墙了 # 用可以翻墙的主机用docker pull拉取镜像,上传本地即可 # 镜像的打包使用save命令 # 镜像的导入使用load命令 # 下载好镜像,导入完毕 # 在master节点执行 kubeadm init --kubernetes-version=v1.16.1 --apiserver-advertise-address=192.168.124.100 --pod-network-cidr=10.244.0.0/16 # 执行成功后,会提示进行如下操作 mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config # 节点加入集群操作 kubeadm join 192.168.124.100:6443 --token ba04v7.y9ki5jgbss8gs0jx \ --discovery-token-ca-cert-hash sha256:8404de0f262daf02de05aad96415c79c2ff39b91ce3ee28cd8248426166123a9 # k8s的网络模型是扁平化的,即pod之间需要能够直接访问,在谷歌的实现中,已经支持扁平化网络模型 # 但是我们创建的集群,不满足这种网络模型,所以需要借助插件或者进行主机配置之后才能满足 # 刚开始学习建议使用flannel,减少障碍,后期有需要进行调研学习 # 安装flannel kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml # 在master执行 kubectl get nodes # 输出,暂时配置了两个节点 NAME STATUS ROLES AGE VERSION master Ready master 50m v1.16.1 node1 Ready <none> 27m v1.16.1 # 没有安装flannel之前,查看nodes,会提示STATUS为NotReady。 # 至此,k8s的基本安装就结束了。 # 是不是很简单 # 后续会继续分享k8s的学习

2019-10-15 · Jerry Wang

RabbitMQ安装和基本概念

RabbitMQ 1、RabbitMQ消息队列 RabbitMQ是一个消息队列:用于接收和转发消息。 2、RabbitMQ安装 1| Mac安装 brew install rabbitmq rabbitmq-server 2|Centos安装 安装epel源-解决erlang依赖wxGTK wget http://www.rpmfind.net/linux/centos/7.4.1708/extras/x86_64/Packages/epel-release-7-9.noarch.rpm yum install epel-release-7-9.noarch.rpm 添加erlang仓库-支持最新版erlang wget https://packages.erlang-solutions.com/erlang-solutions-1.0-1.noarch.rpm rpm -Uvh erlang-solutions-1.0-1.noarch.rpm 安装erlang # yum install erlang # 精简版 # yum install esl-erlang # 完整版 # 实际使用yum连网安装RabbitMQ时,会自动下载安装依赖,此步骤不进行,否则后期会引起冲突 安装RabbitMQ rpm --import https://www.rabbitmq.com/rabbitmq-release-signing-key.asc yum install rabbitmq-server-3.7.2-1.el7.noarch.rpm 启动Rabbit MQ systemctl enable rabbitmq-server systemctl start rabbitmq-server 3|ubuntu安装 添加erlang源 wget https://packages.erlang-solutions.com/erlang-solutions_1.0_all.deb dpkg -i erlang-solutions_1.0_all.deb 安装erlang # apt install esl-erlang # 不进行实际安装 安装rabbitmq echo "deb https://dl.bintray.com/rabbitmq/debian xenial main" | sudo tee /etc/apt/sources.list.d/bintray.rabbitmq.list wget -O- https://dl.bintray.com/rabbitmq/Keys/rabbitmq-release-signing-key.asc | sudo apt-key add - apt update apt install rabbitmq-server 3、RabbitMQ使用 http://blog.csdn.net/column/details/rabbitmq.html ...

2019-04-11 · Jerry Wang

Flask SocketIO基本使用

Flask-SocketIO是一个用于建立WebSocket全双工通信的Flask扩展。客户端应用可以使用任一SocketIO官方客户端库实现,或可以建立持久连接的兼容客户端实现。 1.安装 pip install flask-socketio Flask-SocketIO提供三种异步服务机制: eventlet:支持长轮询和websocket gevent:需使用第三方库 Werkzeug:仅支持长轮询 2.初始化 from flask import Flask, render_template from flask_socketio import SocketIO app = Flask(__name__) app.config['SECRET_KEY'] = 'secret!' socketio = SocketIO(app) if __name__ == '__main__': socketio.run(app) 应用必须给客户端返回一个html页面加载SocketIO库,并且建立连接: <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.6/socket.io.min.js"></script> <script type="text/javascript" charset="utf-8"> var socket = io.connect('http://' + document.domain + ':' + location.port); socket.on('connect', function() { socket.emit('my event', {data: 'I\'m connected!'}); }); </script> 3.接收消息 使用SocketIO时,客户端和服务端以事件的方式接收消息-事件驱动。在客户端,javascript使用回调函数。在服务端,Flask-SocketIO需要注册事件处理函数,类似于路由-视图函数机制。 下面的例子创建服务端无名事件处理函数: @socketio.on('message') def handle_message(message): print('received message: ' + message) 上面的例子使用字符串消息,也可以使用json格式的消息: @socketio.on('json') def handle_json(json): print('received json: ' + str(json)) 最灵活的事件类型是使用定制事件名称。这些事件的消息数据格式可以是字符串、字节、整数或者json: @socketio.on('my event') def handle_my_custom_event(json): print('received json: ' + str(json)) 定制的命名事件支持多参数: @socketio.on('my event') def handle_my_custom_event(arg1, arg2, arg3): print('received args: ' + arg1 + arg2 + arg3) 命名事件是最灵活的,因为命名事件消除了包含附加元数据(描述消息类型)的需要。Flask-socketIO也支持SocketIO命名域,SocketIO命名域允许客户端复用socket(多个连接建立在同一物理socket)。 @socketio.on('my event', namespace='/test') def handle_my_custom_namespace_event(json): print('received json: ' + str(json)) 当SocketIO没有显式指定命名域,全局命名域‘/’将会被使用。 当装饰器语法不太合适时,on_event方法可被使用: def my_function_handler(data): pass socketio.on_event('my event', my_function_handler, namespace='/test') 客户端可能请求一个承认的回调函数,该函数确认接收发送的消息。处理函数的任何返回值将会作为参数递送给客户端的回调函数: ...

2019-04-11 · Jerry Wang

最好的告别

印裔美籍作者葛文德医生在《最好的告别》一书中着重思考了在人生最后的阶段,对于身临其境的人,什么是最重要的?必须明白的是现代工业社会的科学技术深刻影响了人类生命的进程。农耕社会中,男性和女性大概十五岁左右结婚,开始生儿育女的生活,战争与疾病治疗的手段使得长寿是奢侈的,长寿的困难造就了长者拥有家庭乃至群落决策者的地位。但是随着时光尾巴的拉长,情况在改变,长寿者很多见,新闻竞相报道寿星。长寿对于绝大对数人是喜闻乐见的,但是当一个社会的老龄化问题突然呈现出来,社会真的做好了迎接这一变化的准备了吗?而显然大多地区的人们没有对改变做出改变。 迟到的改变对于身处其中的人们是一种折磨! 尽管人类的平均寿命在增长,但是生老病死是自然规律,死亡是符合事物发展的规律的。抽象地说起死亡,这些毫无问题。但是当面对生活周围活生生的家人或者朋友,正在死亡的边缘转圈,他要怎么办?我要怎么办? “作为会老、会死的高级动物是怎么为自己的生命画上句号的?医学如何改变了死亡体验却又无法改变死亡的牌局?我们关于生命有限性的观念产生了怎样的迷茫?”作者如此问自己。这就是作者的初衷,理清这团乱麻!“应该如何优雅地跨越生命的终点?对此,大多数人缺少清晰的观念,而只是把命运交由医学、技术和陌生人来掌控。” 大工业时代,人类的寿命延长了,但是活的太久了,问题也就来了。现代社会对长者的经验和人情练达的期待明显降低,子女成家后对,不再期待父母对其提供庇护和安全感,当长寿者的年龄超过一个奇点,子女与父母的代际冲突越发明显。“经济全球化戏剧性地改变了年轻人的生存境遇。国家的繁荣有赖于他们逃离家庭期望的束缚,走自己的路-去任何能够找到工作的地方,做任何喜欢的工作,同任何自己喜欢的人结婚。”可以欣喜的是,社会似乎提供了一种两全其美的解决方案,对于年轻人和老年人-独立居住。但是这种解决方案有一个明显的问题:“当独立、自助的生活不能再维持时,我们该怎么办?” 人类会逐渐接受事实,但是事实来得太过突然,情绪会崩溃。现代医学能够成功的使人类活的更长久、身体更健康、工作更多产,但是死亡不可避免,并且现代医学的成功,并没有提高对死亡的认知也没有提供给面临死亡的人足够的帮助。现代医学的成功之处在于将濒死的人类拉回阳光普照的人世间,但是这也增加了濒死之人面对死亡的时间! 那么生命最后的愿望,每个人都会有,但是每个人都会实现吗? 或许,站在生命的最后阶段,面对死神,舒服地离开最开心!

2019-04-11 · Jerry Wang

Ansible

1、 What is ansible? Ansible is a radically simple IT automation engine that automates cloud provisioning, configuration management, application deployment, intra-service orchestration, and many other IT needs. Ansible是一个颠覆性的运维工具,支持云配置、配置管理、应用部署、服务编配等运维工作。 Designed for multi-tier deployments since day one, Ansible models your IT infrastructure by describing how all of your systems inter-relate, rather than just managing one system at a time. Ansible一开始就是为多层架构设计的,因此Ansible通过描述系统内部关系,进行整体建模。 It uses no agents and no additional custom security infrastructure, so it’s easy to deploy - and most importantly, it uses a very simple language (YAML, in the form of Ansible Playbooks) that allow you to describe your automation jobs in a way that approaches plain English. ...

2019-04-10 · Jerry Wang

人工智能

本文是李开复先生《人工智能》一书的摘录,结合自己的感想而成。若对人工智能具有兴趣,请移步李开复先生的书籍,或者人工智能专业书籍。 人工智能就在我们生活的每一处 人工智能来了! 人工智能来了! 人工智能来了! 重要的事情必须说三遍! 恐惧不?害怕失业不?有没有可能下一秒被人工智能干掉? 是不是各种担心充满心头? 扯一句韩国电视剧《一起用餐吧》中的台词,“担心又不会解决所有问题,还不如开心的活着。”没有去翻具体的台词,大意如此。 人工智能开始真实的进入人类的生活,对于各个层级的人,具有不同的意义。但是什么是人工智能? 人工智能必须长得像人吗?答案来的很简单,不是。 我们做好与人工智能共同发展的准备了吗?答案不是很明晰。 我们做好接受人工智能产品与我们一起生活、工作了吗?答案是不知道。 感觉不靠谱? 人类对出现的新事物具有本能的好奇心和探索欲,以及多多少少的恐惧。 赶快打开你的手机,看看你的手机看看有多少个app使用了人工智能技术?让我猜猜,0个,3个,7个… 滴滴出行、谷歌翻译、手机淘宝、今日头条、美图秀秀等等。什么,看着不像啊?不就是个app么? “很多时候人工智能都是藏在底下,因此人们并不知道有很多东西已经是机器学习的系统在驱动…“,谷歌大脑开发团队带头人杰夫·迪恩如是说。 那么到底什么是人工智能?该如何定义?作者介绍了五种定义,让我们来看看: 定义一:AI就是让人觉得不可思议的计算机程序 定义二:AI就是与人类思考方式相似的计算机程序 定义三:AI就是与人类行为相似的计算机程序 定义四:AI就是会学习的计算机程序 定义五:AI就是根据对环境的感知,做出合理的行动,并获得最大收益的计算机程序 有什么想法? Nothing?管它该怎么定义,有这个时间,还不如鼓捣鼓捣程序。原谅程序猿的fan。 人工智能的三生三世 三盘棋象征了人工智能的三生三世。没看过这个电视剧,只是借用一下。 第一盘棋是1962年,IBM的西洋跳棋程序战胜一位人类盲人跳棋高手。跳棋是什么,没玩过。 第二盘是1997年,IBM的深蓝战胜国际象棋高手卡斯帕罗夫。 第三盘是2016年,AlphaGo战胜围棋大师李世石。 三盘棋,象征着人工智能的三个时代。三个时代,又有什么不同?先来回答一下相同之处,每次人工智能胜利之后,人类会燃起看似无尽的热情,但是深入了解之后,由发出不过尔尔的叹慨。 高德纳的技术成熟度曲线倒是很有意思。几乎每项技术,在成熟之前,都会在起起伏伏中发展,当然有些被彻底抛弃了,幸存下来的,经过冰与火的洗礼,成为对人类有用的工具。是的,只是工具。是不是太绝对了? 那么人类如何确定某事物是不是有用了? 根据心理学,人们接受一件新事物,就像人们感受一种外界刺激一样,是有一个心理阀值的。只有强于这个阀值的刺激,才会被人类明确感受。 而人工智能的第三世,已经在机器视觉、语音识别、数据挖掘、自动驾驶等具体领域突破人类的心理阀值,并且在人类社会生活中发挥重要作用。在这一过程中,深度学习,居功甚伟。可以说,目前没有深度学习做不了的。深度学习这么厉害,那人工智能的发展又经历了那几个阶段呢? 人工智能的第一生:图灵测试与人机对话 人工智能的第二生:语音识别 “计算机的思维方法与人类的思维方法之间,似乎存在着非常微妙的差异,以至于在计算机科学的实践中,越是抛弃人类既有的经验知识,依赖于问题本身的数据特征,越是容易得到更好的结果。” 人工智能的第三生:深度学习携手大数据 深度学习代表了第三代人工智能。深度学习是什么?为什么在人工智能的第三代独占鳌头? 千古神兵,重出江湖,必定“腥风血雨”。除去宝剑的鞘,才能看见宝剑的锋利。深度学习说到底就是人工神经网络。可惜啊,三年前,与这大宝剑失之交臂,玩了三年的遗传算法和粒子群算法,不甚了了。 “有时对问题领域的扩展可以让问题变得更简单!”,马文·闵斯基说。 为什么深度学习在人工智能的第三代才开始发力?有三个原因,深度学习在1986年开始流行时,深度学习的理论无法解决网络层次加深带来的诸多问题,其次当时的计算能力远远达不到深度神经网络的需要,最重要的是深度学习大展神威的祭品-大规模海量数据没有准备好。 人机PK,奇点是否真的来临 人机PK,AlphaGo赢了。又怎样? 更多的是一种警示:“如果计算机可以在2年内实现大多数人此前预测要花20年或更长时间才能完成的进步,那么,还有哪些突破会以远超常人预期的速度来临?这些突破会不会超出我们对人工智能的想象,颠覆人类预想中的未来?我们已为这些即将到来的技术突破做好准备了吗?” AlphaGo给了人类一个机会,重新思考人工智能的机会。人工智能是什么?人工智能之于人类的意义?人工智能会怎样影响人类的生活与工作?人工智能会不会在未来将人类挑落马下? 先不论AI与人类的PK,AI与AI之间的竞赛,会不断促进AI提高。人类虽望尘莫及,但可以不断从AI中学习新的思想。其实,在现阶段,担忧AI将人类挑落马下,有些操之过急。为何如此说?因为AI现阶段处于弱人工智能、强人工智能和超人工智能的三部曲的弱人工智能,专注于解决特定领域的问题。而强人工智能将能胜任人类所有的工作,发展到超人工智能,人工智能的智能将远胜人类。谁知道,超人工智能是个什么鬼样子? 奇点是否来临? 谁知道了,反正很多事,我都是后知后觉。 反正AI在跨领域推理、抽象能力、知其然知其所以然、常识、自我意识、审美和情感等方面还很稚嫩。 但是提早规划又有什么错呢? AI时代的变革 每一项重大的技术变革,都将引起社会生活的改变,或大或小。那么人工智能给人类的社会生活带来的是什么呢? 牛津大学的伊安·戈尔丁认为世界面临三个挑战: 1、人类赶不上科技发展的速度,来不及调整适应; 2、人脉之间的相互连接以及信息的迅速传播,即有好的一面,也有危险的一面; 3、对个人和国家短期有益的事情,有可能伤及世界的整体利益。 “技术不仅仅是技术。技术的未来必将与社会的未来、经济的未来、文学艺术的未来、人类全球化的未来紧密联系在一起。” 单独谈论人工智能的未来,没有实际意义。“人工智能的未来必将与重大的社会经济变革、教育变革、思想变革、文化变革等同步。” 人工智能快速发展迎来的第一个诘问是:“人工智能会不会引起大面积失业”? 肯定会的。由于人工智能的快速发展,一些简单重复性的、不具备创造性的工作将会被替代。但是工作会消失吗? 肯定不会。新的产业将会替代旧的产业。所以,作为一名职场工作者,必须学会分析那些工作不会被轻易替代,考虑如何利用人工智能技术提高自己的战斗力,在人机协作的新工作氛围中找到自己的位置。 ”AI只是人类的工具。技术本身不是问题,问题是我们如何使用技术以及如何围绕人工智能这样一种革命性的新科技,建立与之配合的社会和经济结构,用制度来保证人人都可享有人工智能大的巨大收益,同时不必担心失业等潜在风险。“ 变革毫无疑问,问题是人类将会迎来什么样的变革。过去到现在,人类一直在寻找金字塔结构的平衡,不管是皇权时代还是民主时代。但是人工智能时代到来之后,简单可重复、毫无创造性的工作将会被大面积取代,这会不会引起社会结构的变革? ”AI的未来掌握在哪些创造、开发和使用者的手中。无疑地,AI会改变世界,但这里真正的问题是,改变AI的又是谁呢?“李飞飞抛出的这个问题又该如何解答? 或许更好的答案就是作者提到的:增加人工智能研究者的多样性,社会结构螺旋上升到一个新的平衡状态。 AI先行 AI先行,是时代的选择,就像每个时代都有每个时代的标志,每个时代都将留下自己的烙印。AI重在提升效率,而非发明新的流程、新的业务。 ...

2017-12-19 · Jerry Wang