首页 文章 精选 留言 我的

精选列表

搜索[webpack入门],共10000篇文章
优秀的个人博客,低调大师

Tensorflow CNN入门

一、概论 以图像识别来举例,比如我们让计算机如何识别一张猫的图片识别出猫呢? 老式的计算机视觉是如何做的呢? 比如OpenCV: 首先理解很多算法,比如如何检测线条(Edge Detection) 如何做形态学变化等 根据我们的知识, 经验, 脑洞来设计很多特征; 用这些特征去比对一张图像是不是猫。 这样做存在的问题呢? 每一种不同的物件,我们都得去设计特征。 这样的人工智能主要是人工,而不是只能。 老式的流程: 原始数据 ——> 人工特征提取 ——> 算法 ——> 结果 卷积要解决的问题就是自动的特征提取(Feature Extraction) 卷积神经网络: 原始数据 ——> 卷积网络 ——> 算法 ——> 结果 #其中 卷积网络 + 算法 称为 深度学习

优秀的个人博客,低调大师

lvs简单入门

只解决c10k问题是不够的,单台主机的处理能力是有限的,一台主机同时处理500个动态网页请求已经是极限了。这里有两种方法提升处理性能,一,定制高性能的计算机,众所周知计算机硬件设计成本极其高,性能每提高10%成本就要增加一倍,这也是intel被称为挤牙膏公司的原因,不是其研发能力不行而是计算机硬件性能提升的难度太大,这个方法貌似不可行。二,使用两台主机处理业务,这就会引来一个问题怎么把请求分发到两个主机,这里我们引入了负载均衡器。 # 目录 负载均衡 lvs工作方式和调度方法 ipvsadm的使用 lvs-nat lvs-dr 多端口绑定和持久连接 # 负载均衡 使用负载均衡有两个方法,一是采用商用负载均衡硬件的,这个方法是最好的方法,能上硬件一定不要使用软件,又是硬件同样的问题也是价格,只要是涉及到基础设施的服务一定要使用。一方面是硬件的稳定性,比软件好很多,虽然软件可维护性和拓展性比较好,但是对于一些金融公司,他们玩的就是公信力和大众信心,每个故障都是竞争对手拆台的理由,一旦故障硬件背锅,理赔。常用的硬件F5的Big-IP,Citrix的Netscaler,A10的A10 另一种是采用软件负载均衡,只要考虑成本使用负载均衡软件就对了,它的性能比硬件也不会差别太大,并且灵活。常用的有lvs,nginx,haproxy,ats。。。 在做负载均衡的时候,我们在7层模型的哪一层做负载均衡,ip层基于主机做负载均衡粒度太大可用性太差基本不使用,更低的层基本上没有价值了,tcp层的话我们就可以把不同服务的请求采取不同的方式负载均衡,应用层的话我们可以根据具体协议拆包分析后负载均衡,既然涉及到拆开数据包,那处理的数据量就会大大增加,那么对计算机性能要求也越高,性能就越差,并且负载均衡器的通用性也越差。 传输层:lvs,nginx:(stream),haproxy:(mode tcp) 应用层: http:nginx, httpd, haproxy(mode http) fastcgi:nginx, httpd mysql:mysql-proxy # lvs工作方式和调度方法 ### lvs的工作方式 有四种lvs-nat,lvs-dr,lvs-tun,lvs-fullnat lvs集群类型中的术语: vs:Virtual Server, Director, Dispatcher, Balancer rs:Real Server, upstream server, backend server CIP:Client IP, VIP: Virtual serve IP, RIP: Real server IP, DIP: Director IP * lvs-nat 它的工作机制类似iptables的dnat功能,但是它工作于input链上。一次请求过程如下图 当客户端向director发送数据,数据在input链上目的地址vip换为rip后,被转发到postrouting链上过滤后发送到real server,real server处理完后把数据发送到director,director把这个数据的源地址rip更改为vip,当然lvs-nat不仅仅是更改ip也可以更改端口,所以支持端口映射,由以上可以总结nat的特点,rip和dip必须在同一网络中,rs的网关需要指向dip,因为所以的数据必须经过director更改ip。 这种工作方式director很容成为网络瓶颈,因为所以的数据都要经过director,director网卡的吞吐量就代表整个网站的流量吞吐量,当今世界的慢慢走向5G,director是完全不能满足需求的,需要借助其它网络设备帮助director分担流量,这就引入了lvs-dr模型。 * lvs-dr 如图,lvs-dr也是在input链上更改数据,但是它更改的不是ip地址而是mac地址,它把目的mac地址vmac更改为rmac,这里就要求vip,rip,dip必须在广播域内,但是地址不一定要在一个网段,因为他们间的通信需要使用mac直接通信。realserver处理请求后直接把数据返回给客户端。 等等,不对啊!realserver是怎么给客户端发送数据包的,realserver服务器上只有rip怎么用vip给客户端通信,这里需要我们给realserver配置vip。但是有一个问题,在网络中多个主机拥有同一个ip会产生冲突的,我们的解决方案是只让一个主机发送arp广播并且响应arp请求,选谁毋庸置疑只能选择director。 控制arp广播arp-ignore,0广播,1不广播;控制响应arp-announce,0响应所有接口信息,1尽量只响应当前网卡的信息,2只响应当前网卡的信息 lvs-dr的使用方法有两种,一种是每个realserver都有与公网交互的公网ip,另一种是只有内网ip,之后演示。 * lvs-tun 它是在原本的报文外部继续封装一个ip头,有可能造成超级帧 * lvs-fullnat 它是把源ip和目的ip都更改,相当于director请求realserver,realserver响应回来数据再把两个ip地址更改,这样这个数据包就可以跨越路由通信了,nat本来就会造成director网络瓶颈,它的使用场景主要应用于请求数据量不大但后服务器数量很多的场景。 ### 调度方法 调用方法可以分为两类,一类是静态调度算法,一类是动态调用算法 * 静态算法 rr #以轮询的方法,把请求转发到后端的主机 wrr #加权轮询,把请求按照一定的比例转发后端主机 sh #源地址哈希,把源地址做hash运算后,把realserver也hash,每个realserver只处理自己hash和上一realserver的hash之间的源地址的请求如图 dh #目标地址哈希,这样realserver可以开启缓存了 * 动态算法 lc #最少连接,根据realserver的正在处理请求的数量进行调度,Overhead=activeconns*256+inactiveconns wlc #加权最少连接,Overhead=(activeconns*256+inactiveconns)/weight nq #在lc的基础上改进的,意思是不许有realserver主机空闲 sed #最短等等时间,Overhead=(activeconns+1)*256/weight lblc #动态的DH算法;基于地址的最小连接数调度(locality-based least-connection):将来自同一个目的地址的请求分配给同一台RS,此时这台服务器是尚未满负荷的。否则就将这个请求分配给连接数最小的RS,并以它作为下一次分配的首先考虑 lblcr #带复制功能的lblc # ipvsadm的使用 管理集群服务:增、改、删; 增、改: ipvsadm -A|E -t|u|f service-address [-s scheduler] [-p [timeout]] 删: ipvsadm -D -t|u|f service-address [-s scheduler]:指定集群的调度算法,默认为wlc service-address: -t|u|f: -t: TCP协议的端口,VIP:TCP_PORT -u: TCP协议的端口,VIP:UDP_PORT -f:firewall MARK,是一个数字; 管理集群上的RS:增、改、删; 增、改: ipvsadm -a|e -t|u|f service-address -r server-address [-g|i|m] [-w weight] 删: ipvsadm -d -t|u|f service-address -r server-address server-address: rip[:port] # lvs-nat nat实验拓扑图 这个使用我采用的是虚拟机,主机ip做cip,director的vip采用的桥接网络,dip和rip采用的是仅主机模式 realserver1执行的命令 yuminstallhttpd-y#安装httpd echors1>/var/www/html/index.html#提供网页文件 realserver2执行的命令 yuminstallhttpd-y echors2>/var/www/html/index.html director执行的命令 yuminstallipvsadm-y ipvsadm-A-t172.16.29.4:80-swrr ipvsadm-a-t172.16.29.4:80-r192.168.95.2-m-w1 ipvsadm-a-t172.16.29.4:80-r192.168.95.3-m-w2 # lvs-dr ### 都采用公网ip的方案 所有网卡都采用桥接 director执行的命令 ifconfigeno16777736:0172.16.29.4netmask255.255.255.255broadcast172.16.29.4up#若在directer和realserver在同一个网段里一定要使用这一行 ipvsadm-A-t172.16.29.4:80-swrr ipvsadm-a-t172.16.29.4:80-r172.16.29.10-g-w1 ipvsadm-a-t172.16.29.4:80-r172.16.29.20-g-w2 realserver执行的命令 echo1>/proc/sys/net/ipv4/conf/all/arp_ignore echo1>/proc/sys/net/ipv4/conf/lo/arp_ignore echo2>/proc/sys/net/ipv4/conf/lo/arp_announce echo2>/proc/sys/net/ipv4/conf/all/arp_announce ifconfiglo:0172.16.29.4netmask255.255.255.255broadcast172.16.29.4up routeadd-host172.16.29.4devlo:0 ### 只要一个公网ip的解决方案 全部接口采用的仅主机模式,并且每个主机只有一个网卡,每个网卡都先配置一个ip,后期再添加需要的ip director要执行的命令 ifconfigeno16777736:0192.168.95.20netmask255.255.255.0broadcast192.168.95.20 ipvsadm-A-t192.168.95.20:80-swrr ipvsadm-a-t192.168.95.20:80-r10.0.0.10-g-w2 ipvsadm-a-t192.168.95.20:80-r10.0.0.20-g-w2 realserver需要执行的命令 echo1>/proc/sys/net/ipv4/conf/all/arp_ignore echo1>/proc/sys/net/ipv4/conf/lo/arp_ignore echo2>/proc/sys/net/ipv4/conf/lo/arp_announce echo2>/proc/sys/net/ipv4/conf/all/arp_announce ifconfiglo:0192.168.95.20netmask255.255.255.255broadcast192.168.95.20up routeadd-host192.168.95.20devlo:0 routeadddefaultgw10.0.0.1 路由设备需要执行的命令 echo 1 > /pro/sys/net/ipv4/ip_forward #开启转发功能 # 多端口绑定和持久连接 ### FWM:FireWall Mark 借助于防火墙标记来分类报文,而后基于标记定义集群服务;可将多个不同的应用使用同一个集群服务进行调度; 打标记方法(在Director主机): # iptables -t mangle -A PREROUTING -d $vip -p $proto --dport $port -j MARK --set-mark NUMBER 基于标记定义集群服务: # ipvsadm -A -f NUMBER [options] ### lvs persistence:持久连接 持久连接模板:实现无论使用任何算法,在一段时间内,实现将来自同一个地址的请求始终发往同一个RS; ipvsadm -A|E -t|u|f service-address [-s scheduler] [-p [timeout]] port Affinity: 每端口持久:每集群服务单独定义,并定义其持久性; 每防火墙标记持久:基于防火墙标记定义持久的集群服务;可实现将多个端口上的应用统一调度,即所谓的port Affinity; 每客户端持久:基于0端口定义集群服务,即将客户端对所有应用的请求统统调度至后端主机,而且可使用持久连接进行绑定; # 总结 lvs是负载均衡器中最基本的,理解了它的原理和使用方法,基本上掌握了大多数的负载均衡器的原理。其中dr模型是必须掌握的,真正使用的话我感觉会使用dr,net的功能很有可能被7层代理的服务器替代了。多端口绑定功能也很常用比如80和443端口绑定统一调度;持久连接虽然破坏调度效果,但是在没有session缓存服务器的话还是很高效的。

优秀的个人博客,低调大师

Docker入门简介

Docker的概念 什么是Docker? Docker是一个开源平台,包含:容器引擎和Docker Hub注册服务器 Docker容器引擎:可以将开发者打包他们的应用和依赖包到一个可一直的容器中,然后将其发布到任何流行的Linux机器上。 Docker Hub 注册服务器:用户可以该注册服务器上创建自己的镜像库来存储、管理和分享镜像。利用Docker,可以实现软件一次配置,处处运行 RedHat从RHEL6.5开始集成对Docker的支持。 容器与虚拟机 Docker是容器的一种,容器是一种轻量级的虚拟技术,重量级的则是虚拟机,例如VMware,VirtualBox等 容器与虚拟机的对比 容器 虚拟机 相同点 都可以在不同的主机之间迁移 都具备root权限 都可以远程控制 都有备份,回滚操作 操作系统 在性能上有优势,能够轻易的同时运行多个操作系统 可以安装任何操作系统,性能不急容器 优点 更为高效,集中。一个硬件节点可以运行数以百计的容器,非常节省资源。Qos会尽量满足,但不保证一定满足,内核由提供者升级,服务由服务器提供者管理 对操作系统具有绝对的权限,对系统版本和升级具有完全管理权限。具有一整套的资源:CPU,RAM和磁盘,QoS是具有保证的。每一个操作虚拟机像一个真实的物理机一样,可以实现不同的操作系统同时运行在同一个物理节点上。 资源管理 弹性的资源分配:资源可以在没有关闭容器的情况下添加,数据卷也无需重新分配大小(有些服务的容器需要重启) 虚拟机需要重启,虚拟机里的操作系统需要处理新加入的资源,例如添加一块磁盘,则需要重新分区等 远程管理 根据操作系统的不同,会通过shell或者远程桌面进行,前提是容器内的操作系统已经启动 远程控制由虚拟化平台提供,可以在虚拟机启动之前连接。所以可以安装系统 缺点 对内核没有控制权限,只有容器的提供者具备升级权限。只有一个内核运行在物理节点上,几乎不能实现不同的操作系统混合。容器提供者一般仅提供少数的几款操作系统 每一台虚拟机具有更大的负载,耗费更多的资源,用于需要全权维护和管理。一台物理机上能够运行的虚拟机也非常有限 配置 快速,秒级即可准备好,由容器提供者处理 配置时间长,从几分钟到几小时,具体取决于操作系统,需要自行安装操作系统 启动时间 秒级 分钟级 硬盘使用 MB GB 性能 接近原生态 若于原生态 系统支持量 单机支持上千个容器 一般不多于几十个 Docker的应用场景 Docker几种典型的应用场景 加速本地开发,通过Docker能够快速搭建好开发和运行环境,并且该环境可以直接传递给测试和产品部署 自动打包和部署应用 创建轻量、私有的PaaS环境 自动化测试和持续集成/部署 部署并扩展Web应用、数据库和后端服务器 创建安全沙盒子 轻量级桌面虚拟化 Docker的组件 Docker采用的是C/S架构 Docker客户端,即Docker可执行程序,可以通过命令和API的形式与Docker守护程序进行通信,Docker守护程序提供Docker服务 Docker包含三大核心组件:镜像、容器和库 镜像:一个只读的静态模板。保存着容器需要的环境和应用的执行代码,可以把镜像看成容器的代码。当代码运行起来后就成了容器。镜像采用分层机制,每个镜像都是只读的,但是可以将写数据的层通过联合文件系统附加在原有镜像之上,这种增量式修改使得镜像非常容易存储、传输和更新。 容器:是一个运行时环境,它是一个镜像的运行状态,相对于静态的镜像而言。容器是镜像执行时的动态表现。 库:Docker采用注册服务器来存储和共享用户的镜像,库是某个特定用户存储镜像的目录。 AUFS Docker利用AUFS来实现对容器的快速更新。 AUFS是一种支持将不同目录挂载到同一个虚拟文件系统下的文件系统,支持对每个目录的读写权限管理。另外,AUFS具有层的概念,每一次修改都是在已有的只写层进行增量修改,修改内容将形成新的文件层,而不影响原有层。 Docker的安装 安装环境: 内核版本 [root@docker ~]# uname -r 2.6.32-573.el6.x86_64 [root@docker ~]# 系统版本 [root@docker ~]# cat /etc/redhat-release CentOS release 6.7 (Final) [root@docker ~]# 注意:如果使用RedHat linux或者Centos linux ,需要时6.5以上的版本以及内核版本在2.6.32-431以上 安装EPEL的命令 rpm -Uvh http://mirror.math.princeton.edu/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm 安装Docker yum install docker-io –y 启动Docker后台 ./etc/init.d/docker start 确认Doocker安装成功 [root@docker ~]# docker info Containers: 0 Images: 0 Storage Driver: devicemapper Pool Name: docker-8:3-3016327-pool Pool Blocksize: 65.54 kB Backing Filesystem: extfs Data file: /dev/loop0 Metadata file: /dev/loop1 Data Space Used: 305.7 MB Data Space Total: 107.4 GB Data Space Available: 78.07 GB Metadata Space Used: 729.1 kB Metadata Space Total: 2.147 GB Metadata Space Available: 2.147 GB Udev Sync Supported: true Deferred Removal Enabled: false Data loop file: /var/lib/docker/devicemapper/devicemapper/data Metadata loop file: /var/lib/docker/devicemapper/devicemapper/metadata Library Version: 1.02.95-RHEL6 (2015-04-15) Execution Driver: native-0.2 Logging Driver: json-file Kernel Version: 2.6.32-573.el6.x86_64 Operating System: <unknown> CPUs: 1 Total Memory: 1.826 GiB Name: docker ID: ZRF4:2E26:P3LZ:TK37:5HJG:5VP3:HUVQ:NSMR:J6BG:WMWO:YEDJ:MDGZ 所有的努力都值得期许,每一份梦想都应该灌溉!

优秀的个人博客,低调大师

docker快速入门

1、docker简介 docker通过内核虚拟化技术(namespace及cgroups等)来提供容器的资源隔离与安全保障等,由于docker通过操作系统层的虚拟化实现隔离,所以docker容器在运行时,不需要类似虚拟机额外的操作系统开销,提供资源利用率 2、docker vs kvm 3、docker组件 镜像、容器、仓库 4、docker安装 [root@docker~]#tee/etc/yum.repos.d/docker.repo<<-'EOF' [dockerrepo] name=DockerRepository baseurl=https://yum.dockerproject.org/repo/main/centos/7/ enabled=1 gpgcheck=1 gpgkey=https://yum.dockerproject.org/gpg EOF [root@docker~]#yuminstalldocker-engine-y 5、docker基础操作 [root@docker~]#systemctlenabledocker.service Createdsymlinkfrom/etc/systemd/system/multi-user.target.wants/docker.serviceto/usr/lib/systemd/system/docker.service. [root@docker~]#systemctlstartdocker.service [root@docker~]# [root@docker~]#dockerpullcentos#拉取镜像 [root@docker~]#dockerpulldaocloud.io/library/nginx 有时候拉取速度很慢,采用国内源加速 root@docker~]#vim/usr/lib/systemd/system/docker.service增加下面这行 EnvironmentFile=/etc/sysconfig/docker 新建配置文件[root@docker~]#vim/etc/sysconfig/docker 在https://dashboard.daocloud.io/注册,然后点击加速器生成加速链接 OPTIONS=--registry-mirror=curl-sSLhttps://get.daocloud.io/daotools/set_mirror.sh|sh-s [root@docker~]#dockersearchnginx#搜索镜像 [root@docker~]#dockerp_w_picpaths REPOSITORYTAGIMAGEIDCREATEDSIZE centoslatest0584b3d2cf6d2weeksago196.5MB 导出镜像 [root@docker~]#dockersave-onginx.tardaocloud.io/library/nginx [root@docker~]#dockersave-ocnetos.tarcentos 导入镜像 [root@docker~]#dockerload--inputcnetos.tar或者[root@docker~]#dockerload<cnetos.tar 删除镜像 [root@docker~]#dockerrmi0584b3d2cf6d(镜像ID) [root@docker~]#dockerruncentos/bin/echo"Helloworld" Helloworld [root@docker~]#dockerps-a CONTAINERIDIMAGECOMMANDCREATEDSTATUSPORTSNAMES 5e381e68a385centos"/bin/echo'Hellowor"6secondsagoExited(0)5secondsagoclever_lamarr [root@docker~]#dockerrun--namemydocker-t-icentos/bin/bash [root@1a67f4c92b6e/]# [root@1a67f4c92b6e/]#ps-ef UIDPIDPPIDCSTIMETTYTIMECMD root10018:56?00:00:00/bin/bash root141018:56?00:00:00ps-ef [root@1a67f4c92b6e/]#exit exit [root@docker~]#dockerps-a CONTAINERIDIMAGECOMMANDCREATEDSTATUSPORTSNAMES 1a67f4c92b6ecentos"/bin/bash"12minutesagoExited(0)6secondsagomydocker 5e381e68a385centos"/bin/echo'Hellowor"16minutesagoExited(0)16minutesagoclever_lamarr [root@docker~]#dockerrun--namedocker-demo-dcentos/bin/bash-d代表放入后台执行 6c5a777467b9552714f9cd3322e677750e2b8b5b0bd2d81e79094ad560828a5e [root@docker~]#dockerps-a CONTAINERIDIMAGECOMMANDCREATEDSTATUSPORTSNAMES 6c5a777467b9centos"/bin/bash"11secondsagoExited(0)11secondsagodocker-demo 1a67f4c92b6ecentos"/bin/bash"17minutesagoExited(0)4minutesagomydocker 5e381e68a385centos"/bin/echo'Hellowor"21minutesagoExited(0)21minutesagoclever_lamarr [root@docker~]#dockerstopmydocker停止容器 [root@docker~]#dockerstart1a67f4c92b6e启动容器 [root@docker~]#dockerrun-d--namemynginxdaocloud.io/library/nginx 225a9b0459630c62dcf2199d6244b16a74ad9412471abf0be03755768df3ae63 [root@docker~]# [root@docker~]#dockerps CONTAINERIDIMAGECOMMANDCREATEDSTATUSPORTSNAMES 225a9b045963daocloud.io/library/nginx"nginx-g'daemonoff"6secondsago Up5seconds80/tcp,443/tcpmynginx 进入容器脚步 [root@docker~]#catdocker_in.sh #!/bin/bash docker_in(){ NAME_ID=$1 PID=$(dockerinspect--format"{{.State.Pid}}"$NAME_ID) nsenter-t$PID-m-u-i-n-p } docker_in$1 6、docker网络 root@docker~]#dockerrun-d-P--namenginx-test1daocloud.io/library/nginx 9b1d36d40127fe2c84bbe7750802e435a817a15b4159b24fc49bfb1107a2cb74 [root@docker~]#dockerps-l CONTAINERIDIMAGECOMMANDCREATEDSTATUSPORTSNAMES 9b1d36d40127daocloud.io/library/nginx"nginx-g'daemonoff"2minutesagoUp2minutes0.0.0.0:32769->80/tcp,0.0.0.0:32768->443/tcpnginx-test1 [root@docker~]#netstat-lntup|grep32768 tcp600:::32768:::*LISTEN11213/docker-proxy [root@docker~]#curl-Ihttp://172.16.80.132:32769 HTTP/1.1200OK Server:nginx/1.11.5 Date:Thu,24Nov201605:58:47GMT Content-Type:text/html Content-Length:612 Last-Modified:Tue,11Oct201615:03:01GMT Connection:keep-alive ETag:"57fcff25-264" Accept-Ranges:bytes 转换前 [root@docker~]#iptables-L-n ChainINPUT(policyACCEPT) targetprotoptsourcedestination ACCEPTall--0.0.0.0/00.0.0.0/0stateRELATED,ESTABLISHED ACCEPTicmp--0.0.0.0/00.0.0.0/0 ACCEPTall--0.0.0.0/00.0.0.0/0 ACCEPTtcp--0.0.0.0/00.0.0.0/0stateNEWtcpdpt:22 REJECTall--0.0.0.0/00.0.0.0/0reject-withicmp-host-prohibited ChainFORWARD(policyACCEPT) targetprotoptsourcedestination DOCKER-ISOLATIONall--0.0.0.0/00.0.0.0/0 DOCKERall--0.0.0.0/00.0.0.0/0 ACCEPTall--0.0.0.0/00.0.0.0/0ctstateRELATED,ESTABLISHED ACCEPTall--0.0.0.0/00.0.0.0/0 ACCEPTall--0.0.0.0/00.0.0.0/0 REJECTall--0.0.0.0/00.0.0.0/0reject-withicmp-host-prohibited ChainOUTPUT(policyACCEPT) targetprotoptsourcedestination ChainDOCKER(1references) targetprotoptsourcedestination ChainDOCKER-ISOLATION(1references) targetprotoptsourcedestination RETURNall--0.0.0.0/00.0.0.0/0 转换后 [root@docker~]#dockerrun-d-P--namenginx-test1daocloud.io/library/nginx 42783cf5053639383004f82b9e72fe0223c7c028d2754b2d0f74429824715f05 [root@docker~]#dockerps-l CONTAINERIDIMAGECOMMANDCREATEDSTATUSPORTSNAMES 42783cf50536daocloud.io/library/nginx"nginx-g'daemonoff"9secondsagoUp7seconds0.0.0.0:32769->80/tcp,0.0.0.0:32768->443/tcpnginx-test1 [root@docker~]#iptables-L-n ChainINPUT(policyACCEPT) targetprotoptsourcedestination ACCEPTall--0.0.0.0/00.0.0.0/0stateRELATED,ESTABLISHED ACCEPTicmp--0.0.0.0/00.0.0.0/0 ACCEPTall--0.0.0.0/00.0.0.0/0 ACCEPTtcp--0.0.0.0/00.0.0.0/0stateNEWtcpdpt:22 REJECTall--0.0.0.0/00.0.0.0/0reject-withicmp-host-prohibited ChainFORWARD(policyACCEPT) targetprotoptsourcedestination DOCKER-ISOLATIONall--0.0.0.0/00.0.0.0/0 DOCKERall--0.0.0.0/00.0.0.0/0 ACCEPTall--0.0.0.0/00.0.0.0/0ctstateRELATED,ESTABLISHED ACCEPTall--0.0.0.0/00.0.0.0/0 ACCEPTall--0.0.0.0/00.0.0.0/0 REJECTall--0.0.0.0/00.0.0.0/0reject-withicmp-host-prohibited ChainOUTPUT(policyACCEPT) targetprotoptsourcedestination ChainDOCKER(1references) targetprotoptsourcedestination ACCEPTtcp--0.0.0.0/0172.17.0.2tcpdpt:443 ACCEPTtcp--0.0.0.0/0172.17.0.2tcpdpt:80 ChainDOCKER-ISOLATION(1references) targetprotoptsourcedestination RETURNall--0.0.0.0/00.0.0.0/0 [root@docker~]#shdocker_in.shnginx-test1 root@42783cf50536:/# root@42783cf50536:/# root@42783cf50536:/#ipaddr 1:lo:<LOOPBACK,UP,LOWER_UP>mtu65536qdiscnoqueuestateUNKNOWNgroupdefault link/loopback00:00:00:00:00:00brd00:00:00:00:00:00 inet127.0.0.1/8scopehostlo valid_lftforeverpreferred_lftforever inet6::1/128scopehost valid_lftforeverpreferred_lftforever 4:eth0:<BROADCAST,MULTICAST,UP,LOWER_UP>mtu1500qdiscnoqueuestateUPgroupdefault link/ether02:42:ac:11:00:02brdff:ff:ff:ff:ff:ff inet172.17.0.2/16scopeglobaleth0 valid_lftforeverpreferred_lftforever inet6fe80::42:acff:fe11:2/64scopelink valid_lftforeverpreferred_lftforever 7、docker数据存储 [root@docker~]#dockerrun-d--namenginx-volume-test1-v/datadaocloud.io/library/nginx 88b24d79a4f3b021325592ceac20e86291166d675b213d60db017548c4d9d960 [root@docker~]#shdocker_in.shnginx-volume-test1 root@88b24d79a4f3:/#cd/data/ root@88b24d79a4f3:/data#ls root@88b24d79a4f3:/data#touchhehe root@88b24d79a4f3:/data#ls-l total0 -rw-r--r--1rootroot0Nov2406:30hehe [root@docker~]#cd/var/lib/docker/ [root@dockerdocker]#ll total32 drwx------6rootroot4096Nov2414:28containers drwx------5rootroot4096Nov2402:05devicemapper drwx------3rootroot4096Nov2401:20p_w_picpath drwxr-x---3rootroot4096Nov2401:20network drwx------2rootroot4096Nov2401:20swarm drwx------2rootroot4096Nov2410:09tmp drwx------2rootroot4096Nov2401:20trust drwx------3rootroot4096Nov2414:28volumes [root@dockerdocker]#cdvolumes/ [root@dockervolumes]#ls 4c60775f938a840e5484aee9088bc612977c25a01f5bd164690d94c962e66e60metadata.db [root@dockervolumes]#cd4c60775f938a840e5484aee9088bc612977c25a01f5bd164690d94c962e66e60/ [root@docker4c60775f938a840e5484aee9088bc612977c25a01f5bd164690d94c962e66e60]#ls _data [root@docker4c60775f938a840e5484aee9088bc612977c25a01f5bd164690d94c962e66e60]#cd_data/容器内的文件实际在物理机上面的的保存目录 [root@docker_data]#ls hehe [root@docker~]#dockerrun-d--namenginx-volume-test2-v/data/mysql:/mysqldaocloud.io/library/nginx f7278ce9bd88c26a0c5aaefcb2b39f1f9df0066bc94edb7a530213815e166f5e #-v/data/mysql:/mysql表示把物理机的/data/mysql目录挂载到容器内的/mysql目录下面 [root@docker~]#dockerrun-d--namenginx-volumes-v/data/mysql:/mysqldaocloud.io/library/nginx 28c616e44352fc4eafeb2f87dbbb7b6eb9df447235afe027034efa96df1c5071 [root@docker~]# [root@docker~]#dockerrun-d--nameweb-node1--volumes-fromnginx-volumesdaocloud.io/library/nginx 0f022ce56e8b800cb1a4ac76bb8a326d42e198093146e8661ad3ac8925ad317d [root@docker~]# [root@docker~]#dockerrun-d--nameweb-node2--volumes-fromnginx-volumesdaocloud.io/library/nginx 03d5e88c15f6604eeee2b8af500b8f356ba69adc34710f3c19b813530f19dc3d

优秀的个人博客,低调大师

Flink从入门到放弃(入门篇3)-DataSetAPI

首先我们来看一下编程结构: 编程结构 public class SocketTextStreamWordCount { public static void main(String[] args) throws Exception { if (args.length != 2){ System.err.println("USAGE:\nSocketTextStreamWordCount <hostname> <port>"); return; } String hostName = args[0]; Integer port = Integer.parseInt(args[1]); final StreamExecutionEnvironment env = StreamExecutionEnvironment .getExecutionEnvironment(); DataStream<String> text = env.socketTextStream(hostName, port); DataStream<Tuple2<String, Integer>> counts text.flatMap(new LineSplitter()) .keyBy(0) .sum(1); counts.print(); env.execute("Java WordCount from SocketTextStream Example"); } 上面的SocketTextStreamWordCount是一个典型的Flink程序,他由一下及格部分构成: 获得一个execution environment, 加载/创建初始数据, 指定此数据的转换, 指定放置计算结果的位置, 触发程序执行 DataSet API 分类: Source: 数据源创建初始数据集,例如来自文件或Java集合 Transformation: 数据转换将一个或多个DataSet转换为新的DataSet Sink: 将计算结果存储或返回 DataSet Sources 基于文件的 readTextFile(path)/ TextInputFormat- 按行读取文件并将其作为字符串返回。 readTextFileWithValue(path)/ TextValueInputFormat- 按行读取文件并将它们作为StringValues返回。StringValues是可变字符串。 readCsvFile(path)/ CsvInputFormat- 解析逗号(或其他字符)分隔字段的文件。返回元组或POJO的DataSet。支持基本java类型及其Value对应作为字段类型。 readFileOfPrimitives(path, Class)/ PrimitiveInputFormat- 解析新行(或其他字符序列)分隔的原始数据类型(如String或)的文件Integer。 readFileOfPrimitives(path, delimiter, Class)/ PrimitiveInputFormat- 解析新行(或其他字符序列)分隔的原始数据类型的文件,例如String或Integer使用给定的分隔符。 readSequenceFile(Key, Value, path)/ SequenceFileInputFormat- 创建一个JobConf并从类型为SequenceFileInputFormat,Key class和Value类的指定路径中读取文件,并将它们作为Tuple2 返回。 基于集合 fromCollection(Collection) - 从Java Java.util.Collection创建数据集。集合中的所有数据元必须属于同一类型。 fromCollection(Iterator, Class) - 从迭代器创建数据集。该类指定迭代器返回的数据元的数据类型。 fromElements(T ...) - 根据给定的对象序列创建数据集。所有对象必须属于同一类型。 fromParallelCollection(SplittableIterator, Class) - 并行地从迭代器创建数据集。该类指定迭代器返回的数据元的数据类型。 generateSequence(from, to) - 并行生成给定间隔中的数字序列。 通用方法 readFile(inputFormat, path)/ FileInputFormat- 接受文件输入格式。 createInput(inputFormat)/ InputFormat- 接受通用输入格式。 代码示例 ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment(); // 从本地文件系统读 DataSet<String> localLines = env.readTextFile("file:///path/to/my/textfile"); // 读取HDFS文件 DataSet<String> hdfsLines = env.readTextFile("hdfs://nnHost:nnPort/path/to/my/textfile"); // 读取CSV文件 DataSet<Tuple3<Integer, String, Double>> csvInput = env.readCsvFile("hdfs:///the/CSV/file").types(Integer.class, String.class, Double.class); // 读取CSV文件中的部分 DataSet<Tuple2<String, Double>> csvInput = env.readCsvFile("hdfs:///the/CSV/file").includeFields("10010").types(String.class, Double.class); // 读取CSV映射为一个java类 DataSet<Person>> csvInput = env.readCsvFile("hdfs:///the/CSV/file").pojoType(Person.class, "name", "age", "zipcode"); // 读取一个指定位置序列化好的文件 DataSet<Tuple2<IntWritable, Text>> tuples = env.readSequenceFile(IntWritable.class, Text.class, "hdfs://nnHost:nnPort/path/to/file"); // 从输入字符创建 DataSet<String> value = env.fromElements("Foo", "bar", "foobar", "fubar"); // 创建一个数字序列 DataSet<Long> numbers = env.generateSequence(1, 10000000); // 从关系型数据库读取 DataSet<Tuple2<String, Integer> dbData = env.createInput(JDBCInputFormat.buildJDBCInputFormat() .setDrivername("org.apache.derby.jdbc.EmbeddedDriver") .setDBUrl("jdbc:derby:memory:persons") .setQuery("select name, age from persons") .setRowTypeInfo(new RowTypeInfo(BasicTypeInfo.STRING_TYPE_INFO, BasicTypeInfo.INT_TYPE_INFO)) .finish()); DataSet Transformation 详细可以参考官网:https://flink.sojb.cn/dev/batch/dataset_transformations.html#filter Map 采用一个数据元并生成一个数据元。 data.map(new MapFunction<String, Integer>() { public Integer map(String value) { return Integer.parseInt(value); } }); FlatMap 采用一个数据元并生成零个,一个或多个数据元。 data.flatMap(new FlatMapFunction<String, String>() { public void flatMap(String value, Collector<String> out) { for (String s : value.split(" ")) { out.collect(s); } } }); MapPartition 在单个函数调用中转换并行分区。该函数将分区作为Iterable流来获取,并且可以生成任意数量的结果值。每个分区中的数据元数量取决于并行度和先前的 算子操作。 data.mapPartition(new MapPartitionFunction<String, Long>() { public void mapPartition(Iterable<String> values, Collector<Long> out) { long c = 0; for (String s : values) { c++; } out.collect(c); } }); Filter 计算每个数据元的布尔函数,并保存函数返回true的数据元。重要信息:系统假定该函数不会修改应用谓词的数据元。违反此假设可能会导致错误的结果。 data.filter(new FilterFunction<Integer>() { public boolean filter(Integer value) { return value > 1000; } }); Reduce 通过将两个数据元重复组合成一个数据元,将一组数据元组合成一个数据元。Reduce可以应用于完整数据集或分组数据集。 data.reduce(new ReduceFunction<Integer> { public Integer reduce(Integer a, Integer b) { return a + b; } }); 如果将reduce应用于分组数据集,则可以通过提供CombineHintto 来指定运行时执行reduce的组合阶段的方式 setCombineHint。在大多数情况下,基于散列的策略应该更快,特别是如果不同键的数量与输入数据元的数量相比较小(例如1/10)。 ReduceGroup 将一组数据元组合成一个或多个数据元。ReduceGroup可以应用于完整数据集或分组数据集。 data.reduceGroup(new GroupReduceFunction<Integer, Integer> { public void reduce(Iterable<Integer> values, Collector<Integer> out) { int prefixSum = 0; for (Integer i : values) { prefixSum += i; out.collect(prefixSum); } } }); Aggregate 将一组值聚合为单个值。聚合函数可以被认为是内置的reduce函数。聚合可以应用于完整数据集或分组数据集。 Dataset<Tuple3<Integer, String, Double>> input = // [...] DataSet<Tuple3<Integer, String, Double>> output = input.aggregate(SUM, 0).and(MIN, 2); 您还可以使用简写语法进行最小,最大和总和聚合。 Dataset<Tuple3<Integer, String, Double>> input = // [...] DataSet<Tuple3<Integer, String, Double>> output = input.sum(0).andMin(2); Distinct 返回数据集的不同数据元。它相对于数据元的所有字段或字段子集从输入DataSet中删除重复条目。 data.distinct(); 使用reduce函数实现Distinct。您可以通过提供CombineHintto 来指定运行时执行reduce的组合阶段的方式 setCombineHint。在大多数情况下,基于散列的策略应该更快,特别是如果不同键的数量与输入数据元的数量相比较小(例如1/10)。 Join 通过创建在其键上相等的所有数据元对来连接两个数据集。可选地使用JoinFunction将数据元对转换为单个数据元,或使用FlatJoinFunction将数据元对转换为任意多个(包括无)数据元。请参阅键部分以了解如何定义连接键。 result = input1.join(input2) .where(0) // key of the first input (tuple field 0) .equalTo(1); // key of the second input (tuple field 1) 您可以通过Join Hints指定运行时执行连接的方式。提示描述了通过分区或广播进行连接,以及它是使用基于排序还是基于散列的算法。如果未指定提示,系统将尝试估算输入大小,并根据这些估计选择最佳策略。 // This executes a join by broadcasting the first data set // using a hash table for the broadcast data result = input1.join(input2, JoinHint.BROADCAST_HASH_FIRST) .where(0).equalTo(1); 请注意,连接转换仅适用于等连接。其他连接类型需要使用OuterJoin或CoGroup表示。 OuterJoin 在两个数据集上执行左,右或全外连接。外连接类似于常规(内部)连接,并创建在其键上相等的所有数据元对。此外,如果在另一侧没有找到匹配的Keys,则保存“外部”侧(左侧,右侧或两者都满)的记录。匹配数据元对(或一个数据元和null另一个输入的值)被赋予JoinFunction以将数据元对转换为单个数据元,或者转换为FlatJoinFunction以将数据元对转换为任意多个(包括无)数据元。请参阅键部分以了解如何定义连接键。 input1.leftOuterJoin(input2) // rightOuterJoin or fullOuterJoin for right or full outer joins .where(0) // key of the first input (tuple field 0) .equalTo(1) // key of the second input (tuple field 1) .with(new JoinFunction<String, String, String>() { public String join(String v1, String v2) { // NOTE: // - v2 might be null for leftOuterJoin // - v1 might be null for rightOuterJoin // - v1 OR v2 might be null for fullOuterJoin } }); CoGroup reduce 算子操作的二维变体。将一个或多个字段上的每个输入分组,然后关联组。每对组调用转换函数。 data1.coGroup(data2) .where(0) .equalTo(1) .with(new CoGroupFunction<String, String, String>() { public void coGroup(Iterable<String> in1, Iterable<String> in2, Collector<String> out) { out.collect(...); } }); Cross 构建两个输入的笛卡尔积(交叉乘积),创建所有数据元对。可选择使用CrossFunction将数据元对转换为单个数据元 DataSet<Integer> data1 = // [...] DataSet<String> data2 = // [...] DataSet<Tuple2<Integer, String>> result = data1.cross(data2); 注:交叉是一个潜在的非常计算密集型 算子操作它甚至可以挑战大的计算集群!建议使用crossWithTiny()和crossWithHuge()来提示系统的DataSet大小。 Union 生成两个数据集的并集。 DataSet<String> data1 = // [...] DataSet<String> data2 = // [...] DataSet<String> result = data1.union(data2); Rebalance 均匀地Rebalance 数据集的并行分区以消除数据偏差。只有类似Map的转换可能会遵循Rebalance 转换。 DataSet<String> in = // [...] DataSet<String> result = in.rebalance() .map(new Mapper()); Hash-Partition 散列分区给定键上的数据集。键可以指定为位置键,表达键和键选择器函数。 DataSet<Tuple2<String,Integer>> in = // [...] DataSet<Integer> result = in.partitionByHash(0) .mapPartition(new PartitionMapper()); Range-Partition Range-Partition给定键上的数据集。键可以指定为位置键,表达键和键选择器函数。 DataSet<Tuple2<String,Integer>> in = // [...] DataSet<Integer> result = in.partitionByRange(0) .mapPartition(new PartitionMapper()); Custom Partitioning 手动指定数据分区。 注意:此方法仅适用于单个字段键。 DataSet<Tuple2<String,Integer>> in = // [...] DataSet<Integer> result = in.partitionCustom(Partitioner<K> partitioner, key) Sort Partition 本地按指定顺序对指定字段上的数据集的所有分区进行排序。可以将字段指定为元组位置或字段表达式。通过链接sortPartition()调用来完成对多个字段的排序。 DataSet<Tuple2<String,Integer>> in = // [...] DataSet<Integer> result = in.sortPartition(1, Order.ASCENDING) .mapPartition(new PartitionMapper()); First-n 返回数据集的前n个(任意)数据元。First-n可以应用于常规数据集,分组数据集或分组排序数据集。分组键可以指定为键选择器函数或字段位置键。 DataSet<Tuple2<String,Integer>> in = // [...] // regular data set DataSet<Tuple2<String,Integer>> result1 = in.first(3); // grouped data set DataSet<Tuple2<String,Integer>> result2 = in.groupBy(0) .first(3); // grouped-sorted data set DataSet<Tuple2<String,Integer>> result3 = in.groupBy(0) .sortGroup(1, Order.ASCENDING) .first(3); DataSet Sink 数据接收器使用DataSet用于存储或返回。使用OutputFormat描述数据接收器算子操作 。Flink带有各种内置输出格式,这些格式封装在DataSet上的算子操作中: writeAsText()/ TextOutputFormat- 按字符串顺序写入数据元。通过调用每个数据元的toString()方法获得字符串。 writeAsFormattedText()/ TextOutputFormat- 按字符串顺序写数据元。通过为每个数据元调用用户定义的format()方法来获取字符串。 writeAsCsv(...)/ CsvOutputFormat- 将元组写为逗号分隔值文件。行和字段分隔符是可配置的。每个字段的值来自对象的toString()方法。 print()/ printToErr()/ print(String msg)/ printToErr(String msg)- 在标准输出/标准错误流上打印每个数据元的toString()值。可选地,可以提供前缀(msg),其前缀为输出。这有助于区分不同的打印调用。如果并行度大于1,则输出也将与生成输出的任务的标识符一起添加。 write()/ FileOutputFormat- 自定义文件输出的方法和基类。支持自定义对象到字节的转换。 output()/ OutputFormat- 大多数通用输出方法,用于非基于文件的数据接收器(例如将结果存储在数据库中)。 可以将DataSet输入到多个 算子操作。程序可以编写或打印数据集,同时对它们执行其他转换。 示例: // text data DataSet<String> textData = // [...] // write DataSet to a file on the local file system textData.writeAsText("file:///my/result/on/localFS"); // write DataSet to a file on a HDFS with a namenode running at nnHost:nnPort textData.writeAsText("hdfs://nnHost:nnPort/my/result/on/localFS"); // write DataSet to a file and overwrite the file if it exists textData.writeAsText("file:///my/result/on/localFS", WriteMode.OVERWRITE); // tuples as lines with pipe as the separator "a|b|c" DataSet<Tuple3<String, Integer, Double>> values = // [...] values.writeAsCsv("file:///path/to/the/result/file", "\n", "|"); // this writes tuples in the text formatting "(a, b, c)", rather than as CSV lines values.writeAsText("file:///path/to/the/result/file"); // this writes values as strings using a user-defined TextFormatter object values.writeAsFormattedText("file:///path/to/the/result/file", new TextFormatter<Tuple2<Integer, Integer>>() { public String format (Tuple2<Integer, Integer> value) { return value.f1 + " - " + value.f0; } }); 使用自定义输出格式: DataSet<Tuple3<String, Integer, Double>> myResult = [...] // write Tuple DataSet to a relational database myResult.output( // build and configure OutputFormat JDBCOutputFormat.buildJDBCOutputFormat() .setDrivername("org.apache.derby.jdbc.EmbeddedDriver") .setDBUrl("jdbc:derby:memory:persons") .setQuery("insert into persons (name, age, height) values (?,?,?)") .finish() ); 序列化器 Flink自带了针对诸如int,long,String等标准类型的序列化器 针对Flink无法实现序列化的数据类型,我们可以交给Avro和Kryo 使用方法:ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment(); 使用avro序列化:env.getConfig().enableForceAvro(); 使用kryo序列化:env.getConfig().enableForceKryo(); 使用自定义序列化:env.getConfig().addDefaultKryoSerializer(Class<?> type, Class<? extends Serializer<?>> serializerClass) 数据类型 Java Tuple 和 Scala case class Java POJOs:java实体类 Primitive Types 默认支持java和scala基本数据类型 General Class Types 默认支持大多数java和scala class Hadoop Writables 支持hadoop中实现了org.apache.hadoop.Writable的数据类型 Special Types 例如scala中的Either Option 和Try

优秀的个人博客,低调大师

Flink从入门到放弃(入门篇4) DataStreamAPI

DataStream算子将一个或多个DataStream转换为新DataStream。程序可以将多个转换组合成复杂的数据流拓扑。DataStreamAPI和DataSetAPI主要的区别在于Transformation部分。 DataStream Transformation map DataStream→DataStream用一个数据元生成一个数据元。一个map函数,它将输入流的值加倍: DataStream<Integer> dataStream = //... dataStream.map(new MapFunction<Integer, Integer>() { @Override public Integer map(Integer value) throws Exception { return 2 * value; } }); FlatMap DataStream→DataStream 采用一个数据元并生成零个,一个或多个数据元。将句子分割为单词的flatmap函数: dataStream.flatMap(new FlatMapFunction<String, String>() { @Override public void flatMap(String value, Collector<String> out) throws Exception { for(String word: value.split(" ")){ out.collect(word); } } }); Filter DataStream→DataStream 计算每个数据元的布尔函数,并保存函数返回true的数据元。过滤掉零值的过滤器: dataStream.filter(new FilterFunction<Integer>() { @Override public boolean filter(Integer value) throws Exception { return value != 0; } }); KeyBy DataStream→KeyedStream 逻辑上将流分区为不相交的分区。具有相同Keys的所有记录都分配给同一分区。在内部,keyBy()是使用散列分区实现的。指定键有不同的方法。 此转换返回KeyedStream,其中包括使用被Keys化状态所需的KeyedStream。 dataStream.keyBy("someKey") // Key by field "someKey" dataStream.keyBy(0) // Key by the first element of a Tuple 注意: 如果出现以下情况,则类型不能成为key: 它是POJO类型但不覆盖hashCode()方法并依赖于Object.hashCode()实现 任何类型的数组 Reduce KeyedStream→DataStream 将当前数据元与最后一个Reduce的值组合并发出新值。 例如:reduce函数,用于创建部分和的流: keyedStream.reduce(new ReduceFunction<Integer>() { @Override public Integer reduce(Integer value1, Integer value2) throws Exception { return value1 + value2; } }); Fold KeyedStream→DataStream 具有初始值的被Keys化数据流上的“滚动”折叠。将当前数据元与最后折叠的值组合并发出新值。 折叠函数,当应用于序列(1,2,3,4,5)时,发出序列“start-1”,“start-1-2”,“start-1-2-3”,. .. DataStream<String> result = keyedStream.fold("start", new FoldFunction<Integer, String>() { @Override public String fold(String current, Integer value) { return current + "-" + value; } }); 聚合 KeyedStream→DataStream 在被Keys化数据流上滚动聚合。min和minBy之间的差异是min返回最小值,而minBy返回该字段中具有最小值的数据元(max和maxBy相同)。 keyedStream.sum(0); keyedStream.sum("key"); keyedStream.min(0); keyedStream.min("key"); keyedStream.max(0); keyedStream.max("key"); keyedStream.minBy(0); keyedStream.minBy("key"); keyedStream.maxBy(0); keyedStream.maxBy("key"); Window函数 关于Flink的窗口概念,我们会在后面有详细介绍。 WindowKeyedStream→WindowedStream 可以在已经分区的KeyedStream上定义Windows。Windows根据某些特征(例如,在最后5秒内到达的数据)对每个Keys中的数据进行分组。 dataStream.keyBy(0) .window(TumblingEventTimeWindows .of(Time.seconds(5))); // Last 5 seconds of data Window ApplyWindowedStream→DataStream AllWindowedStream→DataStream 将一般函数应用于整个窗口。下面是一个手动求和窗口数据元的函数。 注意:如果您正在使用windowAll转换,则需要使用AllWindowFunction。 windowedStream.apply (new WindowFunction<Tuple2<String,Integer>, Integer, Tuple, Window>() { public void apply (Tuple tuple, Window window, Iterable<Tuple2<String, Integer>> values, Collector<Integer> out) throws Exception { int sum = 0; for (value t: values) { sum += t.f1; } out.collect (new Integer(sum)); } }); // applying an AllWindowFunction on non-keyed window stream allWindowedStream.apply (new AllWindowFunction<Tuple2<String,Integer>, Integer, Window>() { public void apply (Window window, Iterable<Tuple2<String, Integer>> values, Collector<Integer> out) throws Exception { int sum = 0; for (value t: values) { sum += t.f1; } out.collect (new Integer(sum)); } }); Window ReduceWindowedStream→DataStream 将reduce函数应用于窗口并返回reduce后的值。 windowedStream.reduce (new ReduceFunction<Tuple2<String,Integer>>() { public Tuple2<String, Integer> reduce(Tuple2<String, Integer> value1, Tuple2<String, Integer> value2) throws Exception { return new Tuple2<String,Integer>(value1.f0, value1.f1 + value2.f1); } }); 提取时间戳 关于Time我们在后面有专门的章节进行介绍 DataStream→DataStream 从记录中提取时间戳,以便使用使用事件时间语义的窗口。 stream.assignTimestamps (new TimeStampExtractor() {...}); Partition 分区 自定义分区DataStream→DataStream 使用用户定义的分区程序为每个数据元选择目标任务。 dataStream.partitionCustom(partitioner, "someKey"); dataStream.partitionCustom(partitioner, 0); 随机分区DataStream→DataStream 根据均匀分布随机分配数据元。 dataStream.shuffle(); Rebalance (循环分区)DataStream→DataStream 分区数据元循环,每个分区创建相等的负载。在存在数据倾斜时用于性能优化。 dataStream.rebalance(); rescaleDataStream→DataStream 如果上游 算子操作具有并行性2并且下游算子操作具有并行性6,则一个上游 算子操作将分配元件到三个下游算子操作,而另一个上游算子操作将分配到其他三个下游 算子操作。另一方面,如果下游算子操作具有并行性2而上游 算子操作具有并行性6,则三个上游 算子操作将分配到一个下游算子操作,而其他三个上游算子操作将分配到另一个下游算子操作。 在不同并行度不是彼此的倍数的情况下,一个或多个下游 算子操作将具有来自上游 算子操作的不同数量的输入。 请参阅此图以获取上例中连接模式的可视化: dataStream.rescale(); 广播DataStream→DataStream 向每个分区广播数据元。 dataStream.broadcast();

优秀的个人博客,低调大师

了解TiDB基础入门

由于目前的项目把mysql换成了TiDb,所以特意来了解下tidb。其实也不能说换,由于tidb和mysql几乎完全兼容,所以我们的程序没有任何改动就完成了数据库从mysql到TiDb的转换,TiDB 是一个分布式 NewSQL SQL 、 NoSQL 和 NewSQL 的优缺点比较 数据库。它支持水平弹性扩展、ACID 事务、标准 SQL、MySQL 语法和 MySQL 协议,具有数据强一致的高可用特性,是一个不仅适合 OLTP 场景还适合 OLAP 场景的混合数据库。下面是对有关资料的整理还有一些扩展内容以链接的方式展示,有兴趣可以点击了解一下。

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册