About neohope

一直在努力,还没想过要放弃...

Spring Cloud Dataflow入门

1、下载下面的文件

#Kafka 0.10.1.1
http://kafka.apache.org/downloads
#服务端
http://repo.spring.io/release/org/springframework/cloud/spring-cloud-dataflow-server-local/1.1.3.RELEASE/spring-cloud-dataflow-server-local-1.1.3.RELEASE.jar
#客户端
http://repo.spring.io/release/org/springframework/cloud/spring-cloud-dataflow-shell/1.1.3.RELEASE/spring-cloud-dataflow-shell-1.1.3.RELEASE.jar
#Avogadro.properties
http://bit.ly/Avogadro-SR1-stream-applications-kafka-10-maven

2、启动服务

#启动ZK
bin/zookeeper-server-start.sh config/zookeeper.properties  &
#启动kafka
bin/kafka-server-start.sh config/server.properties &
#启动服务端
java -jar spring-cloud-dataflow-server-local-1.1.3.RELEASE.jar &
#启动客户端
java -jar spring-cloud-dataflow-shell-1.1.3.RELEASE.jar
#导入Avogadro.properties
app import --uri file://PATH_TO_FILE/Avogadro.properties

3、打开界面
http://IP:9393/dashboard

4、新建一个简单的流,每15秒,写入一行数据
就不截图了,直接粘进去就好了

per_15s_flow01=per_15s: time --cron="0/15 * * * * ?" --date-format="yyyy-MM-dd HH:mm:ss" | file01: file --directory=PATH_TO_FILE --name=file01.txt

创建,并开启工作流。
查看file01.txt
销毁工作流。

5、新建一个较为复杂的流

per_15s_flow01=per_15s: time --cron="0/15 * * * * ?" --date-format="yyyy-MM-dd HH:mm:ss" | file01: file --directory=PATH_TO_FILE --name=file01.txt
per_15s_subflow01=:per_15s_flow01.per_15s > groovy-transform --script="nscript.groovy" --variables=msg='Time is ' | file02: file --directory=PATH_TO_FILE/ --name=file02.txt

用到了一个脚本nscript.groovy

msg+payload

创建,并开启工作流。
查看file01.txt及file02.txt
销毁工作流。

如果报错找不到文件nscript.groovy的话,可以考虑把nscript.groovy文件加到groovy-transform-processor-kafka-10-1.1.1.RELEASE.jar中。

Spring Cloud Config入门

1、从github上下载最新版本
spring-cloud-config

2、编译并运行spring-cloud-config-server

cd spring-cloud-config-server
../mvnw spring-boot:run

如果运行mvnw遇到下面的错误,用vi处理一下就好了

/bin/sh^M: bad interpreter: No such file or directory

用vi处理一下

:set fileformat=unix

3、默认端口为8888,默认配置仓库为github
config-repo

支持以下访问语法:

#获取配置
/{application}/{profile}[/{label}]
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml

#更新Environment、重新绑定@ConfigurationProperties、重置日志级别
/env
#刷新@RefreshScope
/refresh
#重启Spring上下文,默认是禁用的
/restart` for restarting the Spring context (disabled by default)
#调用ApplicationContext的stop及start等生命周期相关函数
/pause
/resume

我们来测试一下服务端运行情况:(服务端要可以连接到github上哦)

#foo.properties
curl localhost:8888/foo-master.properties
#foo.properties tag=v1.0.0.RC2
curl localhost:8888/v1.0.0.RC2/foo-master.properties
#foo-development.properties
curl localhost:8888/foo-development.properties
#foo-db.properties
curl localhost:8888/foo-db.properties
#foo-development-db.properties
curl localhost:8888/foo-development-db.properties

4、看一下自带的例子
spring-cloud-config-sample/src/main/java/sample/Application.java


package sample;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@SpringBootApplication
public class Application {

	@Autowired
	private Environment environment;

	@Value("${spring.application.name}")
	private String appName;
	
	@RequestMapping("/appName")
	public String appName() {
		return appName;
	}

	@RequestMapping("/")
	public String query(@RequestParam("q") String q) {
		return environment.getProperty(q);
	}

	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}

}

5、测试一下例子

cd spring-cloud-config-sample
mvn spring-boot:run

6、看一下输出信息

Mapping servlet: 'dispatcherServlet' to [/]
Mapping filter: 'metricsFilter' to: [/*]
Mapping filter: 'characterEncodingFilter' to: [/*]
Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
Mapping filter: 'httpPutFormContentFilter' to: [/*]
Mapping filter: 'requestContextFilter' to: [/*]
Mapping filter: 'webRequestLoggingFilter' to: [/*]
Mapping filter: 'applicationContextIdFilter' to: [/*]
Mapping : Mapped "{[/]}" onto public java.lang.String sample.Application.query(java.lang.String)
Mapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
Mapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
Mapping  : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
Mapping  : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
Mapping  : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
Mapping     : Mapped "{[/dump || /dump.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
Mapping     : Mapped "{[/auditevents || /auditevents.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public org.springframework.http.ResponseEntity<?> org.springframework.boot.actuate.endpoint.mvc.AuditEventsMvcEndpoint.findByPrincipalAndAfterAndType(java.lang.String,java.util.Date,java.lang.String)
Mapping     : Mapped "{[/loggers/{name:.*}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.LoggersMvcEndpoint.get(java.lang.String)
Mapping     : Mapped "{[/loggers/{name:.*}],methods=[POST],consumes=[application/vnd.spring-boot.actuator.v1+json || application/json],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.LoggersMvcEndpoint.set(java.lang.String,java.util.Map<java.lang.String, java.lang.String>)
Mapping     : Mapped "{[/loggers || /loggers.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
Mapping     : Mapped "{[/env],methods=[POST]}" onto public java.lang.Object org.springframework.cloud.context.environment.EnvironmentManagerMvcEndpoint.value(java.util.Map<java.lang.String, java.lang.String>)
Mapping     : Mapped "{[/env/reset],methods=[POST]}" onto public java.util.Map<java.lang.String, java.lang.Object> org.springframework.cloud.context.environment.EnvironmentManagerMvcEndpoint.reset()
Mapping     : Mapped "{[/pause || /pause.json],methods=[POST]}" onto public java.lang.Object org.springframework.cloud.endpoint.GenericPostableMvcEndpoint.invoke()
Mapping     : Mapped "{[/resume || /resume.json],methods=[POST]}" onto public java.lang.Object org.springframework.cloud.endpoint.GenericPostableMvcEndpoint.invoke()
Mapping     : Mapped "{[/beans || /beans.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
Mapping     : Mapped "{[/configprops || /configprops.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
Mapping     : Mapped "{[/features || /features.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
Mapping     : Mapped "{[/env/{name:.*}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EnvironmentMvcEndpoint.value(java.lang.String)
Mapping     : Mapped "{[/env || /env.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
Mapping     : Mapped "{[/health || /health.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.HealthMvcEndpoint.invoke(javax.servlet.http.HttpServletRequest)
Mapping     : Mapped "{[/restart || /restart.json],methods=[POST]}" onto public java.lang.Object org.springframework.cloud.context.restart.RestartMvcEndpoint.invoke()
Mapping     : Mapped "{[/autoconfig || /autoconfig.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
Mapping     : Mapped "{[/heapdump || /heapdump.json],methods=[GET],produces=[application/octet-stream]}" onto public void org.springframework.boot.actuate.endpoint.mvc.HeapdumpMvcEndpoint.invoke(boolean,javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws java.io.IOException,javax.servlet.ServletException
Mapping     : Mapped "{[/metrics/{name:.*}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.MetricsMvcEndpoint.value(java.lang.String)
Mapping     : Mapped "{[/metrics || /metrics.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
Mapping     : Mapped "{[/mappings || /mappings.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
Mapping     : Mapped "{[/refresh || /refresh.json],methods=[POST]}" onto public java.lang.Object org.springframework.cloud.endpoint.GenericPostableMvcEndpoint.invoke()
Mapping     : Mapped "{[/info || /info.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()
Mapping     : Mapped "{[/trace || /trace.json],methods=[GET],produces=[application/vnd.spring-boot.actuator.v1+json || application/json]}" onto public java.lang.Object org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter.invoke()

7、测试一下

curl localhost:8080/?q=foo

8、是不是很简单,到自己的项目上试试吧

Spring Cloud各模块作用

首先说明一下,由于工作实在太忙了,这个系列的后面几篇,是后面补的,并没能及时进行总结和整理。
有一些细节的地方,可能并不准确(调整过部分代码和配置文件什么的),遇到问题麻烦调整一下,有问题也可以留言。

1、配置中心(基于git、svn、ftp等方式)
Spring Cloud Config

2、负载均衡
Spring Cloud Cluster

3、消息总线
Spring Cloud Bus

4、服务注册及发现
Spring Cloud Zookeeper
Spring Cloud Consul

5、任务调度
Spring Cloud Data Flow 任务调度
Spring Cloud Stream 工作流
Spring Cloud Stream App Starters 工作流实现
Spring Cloud Task 批处理
Spring Cloud Task App Starters 批处理实现

6、服务监控
Spring Cloud Sleuth

7、安全(OAuth2)
Spring Cloud Security

8、数据库、消息队列等
Spring Cloud Connectors

9、快速开发groovy
Spring Cloud CLI

10、Moke测试
spring-cloud-contract

11、部署(现在有mvn和docker两种方式)
spring-cloud-deployer

12、第三方云厂商集成
Spring Cloud for Amazon Web Services
Spring Cloud for Cloud Foundry
Spring Cloud Cloud Foundry Service Broker

13、Spring Cloud Netflix
archaius 配置管理
ribbon 客户端负载均衡
feign 基于注解的JSON库,自带ribbon功能
eureka 服务注册、LB、故障转移
hystrix 断路器/日志采集
turbine 性能日志聚合
Zuul API网关,数据路由+负载均衡
spectator/servo 客户端性能指标采集
atlas 时间序列数据库

14、其他
sidecar 将非JVM服务,封装为Netflix服务,并提供代理,让非JVM服务调用

15、移动端支持
RxJava 响应式编程支持(observable, operator和susbscriber)

几种常见的微服务编排模式

随着需要管理服务的增多,如何编排服务,成了一个很迫切的问题。本文就介绍几种常见的微服务编排方式:

1、Orchestration
这种方式,和BPM、ESB的思想很相似,实现方案多是同步的。
首先要有一个流程控制服务,该服务接收请求,依照业务逻辑规则,依次调用各个微服务,并最终完成处理逻辑。
这种方法的好处是,流程控制服务时时刻刻都知道每一笔业务究竟进行到了什么地步,监控业务成了相对简单的事情。
这种方法的坏处是,流程控制服务很容易控制了太多的业务逻辑,耦合度过高,变得臃肿,而各个微服务退化为单纯的增删改查,容易失去自身价值。

为了便于理解,您可以把控制服务看作BPM、ESB引擎,微服务为BPM、ESB的各种组件。

2、Choreography
这种方式,可以看作一种消息驱动模式,或者说是订阅发布模式,实现方案多是异步的。
每笔业务到来后,各个监听改事件的服务,会主动获取消息,处理,并可以按需发布自己的消息。
这种方法的好处是,耦合度低,每个服务都可以各司其职。
这种方法的坏处是,业务流程是通过订阅的方式来体现的,很难直接监控每笔业务的处理,因此需要增加相应的监控系统,来保证业务顺畅进行。

为了便于理解,您可以把不同队列看作不同种类的消息,微服务看作消息处理函数。

3、API网关
API网关,可以看作一种简单的接口聚合/拆分的方式。
每笔业务到来后,先到达网关,网关调用各微服务,并最终聚合/拆分需反馈的结果。
这种方法的好处是,对外接口相对稳定,可以利用LAN的带宽,弥补因特网的不足。
这种方法的坏处是,只适合业务逻辑较为简单的场景,业务逻辑过于复杂时,网关接口耦合度及复杂度会急剧升高,变得臃肿。

其实就是一个适配网关,比如对于Web端,可以一个页面同时发起几十个请求,而对于移动端,最好是一个页面就几个请求
。而采用API网关,后面的微服务可以是相同的。

致新人,差距是如何产生的(02)


致新人,差距是如何产生的(02)
Hansen

先从一个故事讲起:

一个师傅带两个学汽修的徒弟,都从喷漆开始。一年后,师弟都会调悬架了,师兄连轮胎都不会换。师兄问师傅,为只教师弟不教自己。师傅说,为了把漆喷好,你师弟请教了几个老师傅,查了不少资料,每天晚上都自己花时间尝试各种想法,半个月就可以自己做好了。你呢,每天看似很努力,但一个问题出了几次还不知道为什么,三个月后还是只能处理最简单的刮擦,怎么教你新东西?换轮胎不是我教的,我带你俩出去修车,都遇到过爆胎。你师弟看过一次,第二次就主动要求试试看。你呢?我换车胎的时候,你在抽烟玩手机吧?。。。

总结一下也就是: 性痴则其志凝。故书痴者文必工,艺痴者技必良。世之落拓而无成者,皆自谓不痴者也。

以下内容节选自《平台组动员会议2017.ppt》:
自主学习
2016年你学到了什么?读了几本书?看了多少教程?读了谁的博客?在StackOverflow上回答了几个问题?GitHub上贡献了几行代码?LeetCode上通解决了几个问题?是否接触过新的语言?
考个证?拿个学历?参加个会议?参加个培训?
2017年,你的学习计划是什么?是不是要重复2016年做的事情?你的2016年是不是在重复2015年做的事情?
Google还是百度?英文还是中文?

什么是高原反应?
什么是努力,知道迈特凯、洛克李、迈特戴吗?
如何提升自己?请用5%的休息时间来提升自己。

主动思考
支付宝有几种支付方式?微信有几种支付方式?为啥需要这些支付方式?
全家移动支付的时候,需要收银员做什么操作吗?为什么?
滴滴打车,司机抢单算法是如何计算的,你知道什么是滴米吗?
手机定位有几种方式,必须要GPS才能定位吗?手机计算你走了几步,是怎么实现的?
什么是Java?Java常用框架的原理是什么?Tomcat是怎么工作的?JVM究竟是做什么的?Dubbo怎么实现RPC的?
软件哪里可以优化,哪里应该改进?我的代码哪些地方有些问题?

Stay hungry, Stay foolish。

做喜欢的事情,还是应该做的事情?
随着一个人的成长,这是一个人必然会遇到的问题。(你父母希望你先写作业,还是先看电视?你希望自己的孩子怎么做?)
任务分配的时候,是应该把业务流程讲解清楚,还是让他、她自己去看去理解?
代码注释应该怎么写?
单元测试应该怎么写?
SVN代码提交的时候,注释应该怎么写?
代码提交之前是否应该通过单元测试?流程是否应该跑一遍?
程序发布之前,是不是应该自己先测试一下?还是直接扔给测试或实施?

如何提高员工的归属感


如何提高员工的归属感
Hansen

1、物质奖励(除了薪水,还要有适时的激励和奖惩)
员工工作,就是为了更好的生活。一切只谈理想而不谈待遇的企业,都是在耍流氓。
但要知道,物质奖励可以留着员工的人,但很难留住员工的心。
这和追女朋友是一个道理的。

2、让员工知道自己的职业道路,以及上升空间
一个没有进步空间的岗位,是留不住人的。

3、让员工提升对自己工作的认可,其实就是提升对自己的认可,从而增加员工的自信
人对自己做的事情认可了,才能坚持下去

4、管理层应该去了解你的员工,去关心你的员工,增加团队粘性
团队关系良好,是很强的粘合剂
有些员工带有自来熟的属性,也是很合适的粘合剂。
可以参考海底捞。

5、良好的企业文化
重视每一个员工,和谐的人际关系
重视员工的权利,明确员工的义务
增强员工话语权,让员工一同参与出谋划策,增强员工的使命感及荣誉感

6、管理层的示范作用
要起到带头做用,勇于担当
让别人喜欢你,让别人认可你,让别人信服你

7、公平考核制度及竞争环境
you can you up. no can no bb.

8、要对员工进步,并提供相应帮助
让程序员永远在同一层次上,重复同样的工作,是留不住人的
要求员工自学、积累、创新,并给与教育、培训的机会
看看很多从外包企业出来的哥们,在外包做了十年,重复了十年,最后把自己荒废了。

9、培养并激发员工的兴趣
包括工作相关和工作无关的兴趣。

Linux常用命令11Linux文本处理示例

0.AWK常变量含义

常变量名 含义
ARGC 命令行变元个数
ARGV 命令行变元数组
FILENAME 当前输入文件名
FNR 当前文件中的记录号
FS 输入域分隔符,默认为一个空格
RS 输入记录分隔符
NF 当前记录里域个数
NR 到目前为止记录数
OFS 输出域分隔符
ORS 输出记录分隔符

1、统计文本中单词数量,并进行排序

grep -Eo "[a-z|A-Z]+" words.txt|awk '{word_cound[$1]++}END {for(aword in word_cound){print aword,word_cound[aword]|"sort -rn -k2"}}'

2、电话号码验证
规则:
A、(xxx) xxx-xxxx
B、xxx-xxx-xxxx

grep -Eo '^(\([0-9]{3}\) |[0-9]{3}-)[0-9]{3}-[0-9]{4}$' phonelist.txt

3、行列转换

awk '{for(i=0;++i<=NF;)t[i]=t[i]?t[i] FS $i:$i}END {for(i=0;i++<NF;)print t[i]}'  transport.txt

4、输出第10行

awk 'NR==10{print}' tenth.txt

这样的产品你会用吗?


这样的产品你会用吗?
作者:Hansen

首先,让我们来看一个小故事。

节选自:
龙枪编年史||,第三卷,第05章

人物介绍:
浓修:一个喜欢发明机械装置的侏儒
泰斯:一个喜欢游荡的坎德人
费资本:年迈老法师

前情提要:
泰斯和费资本要通过侏儒的投石机装置,从1楼飞到15楼

正文开始:

“三十五层楼高!”泰斯惊讶地重复。“住在顶楼不就倒霉了?这样得爬多少层阶梯啊?”

浓修吸吸鼻子。“我们早就舍弃了这种原始的装置。”他比着手势,“如果你不介意看看这些我们所制造出来的可怕科技成果吧——”

“我看到了。”泰斯把视线重新技回地面。“你们大概正准备打一场大规模的仗。我从来没看过这么多的投石器——”

坎德人硬生生吞回去接下来的话。正当他看着时,一声哨音响起,投石器把一个侏儒射出去。泰斯看见的并不是武器,而是一种取代楼梯的装置!

大厅的最底层放满了投石器,几乎含括了每一种侏儒制的投石器。有弹簧做的、十字弓形的、蒸汽机驱动的(还在实验阶段,他们在调整水的温度。)

投石器上下左右缠绕着数百里长的绳索,每一条绳索都连接着某种齿轮和机械装置,发出机器运转的声音。

  地板、墙壁、投石器上尽是各式各样的拉杆,成群结队的侏儒正努力地拉上拉下。

  “我想,”费资本听起来十分的无奈,“这个检验室应该不会在一楼吧?”

浓修摇摇头。“检验室在十五楼——”老法师发出一声心碎的叹息。

  坎德人听到一阵令人牙龈发酸的声音。

  “啊,他们准备好了。快来——”浓修说。

  泰斯快快乐乐、一跳一跳地跟在他后头,走向一个巨大的投石器。一名侏儒不耐烦地向他们打着手势,比了比后面一长串正排队等候着的侏儒。

泰斯跳上了投石器,满怀期待地看着天空。他可以看见许多侏儒从各楼层往下看,身旁环绕着各种机器、齿轮和说不出名字的装置,最容易分辨的是一种挂在墙壁上、类似棒子的东西。

浓修站在他旁边,皱着眉头。

  “敬老尊贤,年轻人,所以赶快离开让老人家坐上来。”他以他惊人的力量将泰斯从位置上拉下来,“魔法师优先——”

“喔,没关系啦!”费资本抗议,一个不小心,往后跌进一团绳子里。“我——我好像想起了一道可以让我飞到上头去的法术,浮空术,那是怎么施——施展?给我几分钟想一想……”

“一直叫我们快一点的是你那——”浓修生气地看着老法师,后头排队的侏儒开始鼓噪起来,彼此推挤。

  “啊!拼了啦!”老法师大吼,迈步爬过座位里,浓修在一边帮着。

负责发射投石器的株儒喊了一具不知道什么话。

  浓修指着上面,喊回去。“第十五层!”

技师走到五个拉杆之前,这里延伸出几近无限长的绳子。费资本哀怨地坐在投石器上,挣扎着要回想起他的法术。

  “预备!”浓修大喊,把泰斯拉近,好让他能看得更清楚,“用不了多久,技师就会给我们信号,对——就是这个信号——”

技师拉了拉一条绳子。

  “那有什么用?”泰斯插嘴。

  “这条绳子连接到第十五层的一个铃上,告诉他们有人要上来——”

“万一铃没响怎么办?”费资本大声地问。

  “会有第二个铃声提醒他们第一个铃没有响——”

“铃声没响底下会怎么应变?”

“就啥也不做。那是第十五层的事,不是你的问题——”

“万一他们不知道我要来了,这就变成我的问题了!”费资本大喊。“难不成要我就这样跳过去给他们一个惊喜吗?”

“啊!”浓修骄傲地说,“我跟你说——”

“我不玩了……”费资本表示。

  “不,等等。”浓修说,说话速度因为紧张而越来越快。“他们准备好了——”

“谁准备好了?”费资本愤怒地问。

  “第十五层!他们把网子放出来了,你知道——”

“网子!!!”费资本脸色发白,“够了!”他一只脚踏了出去。

  但在他逃出去之前,技师已经伸手拉下了第一根拉杆。一阵机械运转声后,投石器开始在轨道上移动。运转的震动又把费资本摔了回去,帽子遮住眼睛。

  “发生什么事了?”泰斯大喊。

  “他们正在就发射位置。”浓修大喊。“经度和纬度已经计算妥当,可以把乘客发射到预定的位置——”

“你给我说清楚网子是怎么一回事?”泰斯扯开喉咙大吼。

  “法师会飞上第十五层——喔!我向你保证,相当的安全——我们做过研究,事实上,研究结果证明了飞行比走路还要安全——等他飞到了轨迹的最高点,正要开始落下时,第十五层会伸出一张网,像这样抓住他”依修用一只手示范,啪的一声抓住一只蚊子,“然后把他丢——”

“这时间可得算得很准罗!”

“时间铁定准,因为我们研发出一种钩子来进行这项艰巨的任务,不过,”浓修嘟起嘴,皱眉说,“有些时候是投石器会出现误差,不过我们有个委员会——”

侏儒拉下拉杆,费资本尖叫着飞上天空。

  “喔哦!天哪!”浓修瞪着天空。“看来——”

“什么?什么?”泰斯大叫着想要看清楚。

  “网子又太早打开了——”浓修摇摇头,“第十五层今天一天已经发生了两次,这可得提案到安全网公会去讨论,并且不能让它再度发生——”

泰斯张大嘴,看着费资本的身影划过天空,借着投石器巨大的力量不断地往上飞。刹那间,坎德人终于懂了浓修在说些什么。

  第十五层的网子并没有在法师飞过第十五层之后张开而是在费资本飞越之前就张开了。费资本像是被打扁的苍蝇般贴在网子上。

  有短短的一瞬间,他手脚并用地小心抓着网子,然后……就掉了下来。

  钟声和锣声齐鸣。

  “别告诉我——”泰斯哀怨地说。“那就是网子失效的警告声。

  “你猜对了,但不用太紧张(自鸣得意地笑着)”浓修咯咯笑道,“因为这个警铃会触动第十三层的网子,正好可以——唉呦,看来好像迟了一步,不过没关系,我们还有第十二层——”

“快想想办法!”泰斯尖叫道。

“别穷紧张好不好!”浓修生气地说。“不然我根本没有机会说完我刚刚正要提到的最后后备安全系统,喔,来啦——”

泰斯惊讶地看着第三层墙壁上伸出了六个大筒子,底部打开来,掉出无数的海绵,铺在第一层的广场上。这是为了——显然的——预防所有的网子都没有接到。

很幸运的,第九层的网子没有失效,正巧来得及将法师捞起,之后网子随即收拢,把他甩到一个阳台上,侏儒们听见他不停的咒骂声,有点不大敢放他出来。

  “这下全部妥当!该你了。”浓修说。

  “最后一个问题!”泰斯坐在座位上对着浓修大喊。“万一这个后备安全系统也失效了怎么办?”

“好问题——”浓修高兴地说,“如果这些海绵掉下来不够快,那么另一个警铃会响起,将一大桶水倒到广场中央,然后呢——正好海绵这时候也该倒了下来——要擦干净地上的血迹就很简单了——”技师拉下了拉杆。

是不是很好笑?

问题是,我们是不是有一些产品,给到用户的时候:
1、一开始就做了很多错误的假设,用了错误的原型?
2、团队任务分工不明确,相互之间不Care?
3、不去预防问题发生,而是尝试各种Catch问题?
4、用了先进的技术,而忽略了用户的问题?
5、用户用差异的眼光看着你的时候,你仍自信的感觉那是称赞?

Spark环境搭建05

这里主要说一下Spark的SQL操作,如何从mysql导入数据。

#拷贝了mysql的驱动到jar文件下面
#建立DF
val jdbcDF = spark.read.format("jdbc").option("url", "jdbc:mysql://localhost:3307").option("dbtable", "hive.TBLS").option("user", "hive").option("password", "hive").load()

#schema
jdbcDF.schema

#count
jdbcDF.count()

#show
jdbcDF.show()

Spark环境搭建04

这里主要说一下Spark的SQL操作。

1、dataframe操作数据

#加载json数据
val df = spark.read.json("/usr/hadoop/person.json")
#加载CSV数据
#val df = spark.read.csv("/usr/hadoop/person.csv")

#查询前20行
df.show()

#查看结构
df.printSchema()

#选择一列
df.select("NAME").show()

#按条件过滤行
df.filter($"BALANCE_COST" < 10 && $"BALANCE_COST" > 1).show()

#分组统计
df.groupBy("SEX_CODE").count().show()

2、sql操作数据

#创建视图
df.createOrReplaceTempView("person")

#查看数据
spark.sql("SELECT * FROM person").show()

#统计数据
spark.sql("SELECT * FROM person").count()

#带条件选择
spark.sql("SELECT * FROM person WHERE BALANCE_COST<10 and BALANCE_COST>1 order by BALANCE_COST").show()

3、转为DS

#转为Dataset
case class PERSONC(PATIENT_NO : String,NAME : String,SEX_CODE : String,BIRTHDATE : String,BALANCE_CODE : String)
var personDS = spark.read.json("/usr/hadoop/person.json").as[PERSONC]

4、sql与map reduce混用

personDS.select("BALANCE_COST").map(row=>if(row(0)==null) 0.0 else (row(0)+"").toDouble).reduce((a,b)=>if(a>b) a else b)

spark.sql("select BALANCE_COST from person").map(row=>if(row(0)==null) 0.0 else (row(0)+"").toDouble).reduce((a,b)=>if(a>b) a else b)

5、数据映射为Class对象

val personRDD = spark.sparkContext.textFile("/usr/hadoop/person.txt")
val persons = personRDD.map(_.split(",")).map(attributes => Person(attributes(0), attributes(1), attributes(2), attributes(3), attributes(4).toDouble))

6、自定义schema

import org.apache.spark.sql.Row
import org.apache.spark.sql.types._

#加载数据
val personRDD = spark.sparkContext.textFile("/usr/hadoop/person.txt")
#转为org.apache.spark.sql.Row
val rowRDD = personRDD.map(_.split(",")).map(attributes => Row(attributes(0), attributes(1), attributes(2), attributes(3), attributes(4).replace("\"","").toDouble))
#定义新的Schema
val personSchema = StructType(List(StructField("PatientNum",StringType,nullable = true), StructField("Name",StringType,nullable = true), StructField("SexCode",StringType,nullable = true), StructField("BirthDate",StringType,nullable = true), StructField("BalanceCode",DoubleType,nullable = true)))
#建立新的DF
val personDF = spark.createDataFrame(rowRDD, personSchema)
#使用DF
personDF.select("PatientNum").show()