极简设计

产品经理与项目经理的区别 2016-01-01

靠想 or 靠做

产品经理—靠想:做正确的事,所领导的产品是否符合市场的需求,是否能给公司带来利润 项目经理—靠做:把事情做正确,把事情作得完美,在时间/成本/资源约束条件下完成目标

纵向 or 横向

管理的角度讲,项目经理是纵向的,而产品经理是横向的

产品经理关注产品生命周期,是否能够赚钱,能否持续的赚钱 规划整个产品架构和发展路线,确定产品定位和受众,预计产品真正价值和效益

项目经理是需要正确的做事情,即按照产品规划制定的项目目标正确的做事情 项目能够按照目标完成则项目就是成功的,如果项目的产品不能真正盈利往往则是产品规划出现了失误


 姑且理解项目经理是一个开发部门的项目经理,对某产品进行开发管理,负责开发的进度,开发过程中的协调,供应链等有关开发方面的问题,最大目标是时间第一,立项目标达成第一。并不会很尊重产品本身的市场需求以及业务逻辑的问题

在一个公司中类似这样纵向管理的部门都是一个个职能部门 例如市场部主要负责推广,销售部等 而产品经理是横向管理的,也就是说他将负责某个 产品或者某个产品线从商业计划市场竞争开发需求推广方案渠道策略物流等各个方面 当然产品经理不一定是决策人,每个公司对产品经理的权限限制也不同,但是 产品经理一个产品线从头到尾的重要参与人。想做好产品经理需要很多方面的才华和技能,他也是一个公司中最适合培养复合型人才潜力的职位

一个产品经理可能没有权利,但是一个产品经理要善于运用同事关系,客户关系去协调去促进事情的发展,一个项目是属于项目经理开发的,他有开发目标达成的责 任。而这个项目也是属于产品经理的,他有对商业计划负责的责任。因此作为产品经理就意味着的和本产品有关的事,不论是开发生产推广销售成本物流渠道都是你 问题!

如果希望做一个复合人才就选择产品经理,如果希望做一个专注人才就选择项目经理。(iamsujie补:对这句话持保留态度,做不同的事情而已,没法用通才、专才概括)

产品生命周期和项目生命周期

产品生命周期关注的是整个产品从规划到制造,再到最终维护和消亡的整个过程。一个产品往往会由多个项目来实现,也可能分多个迭代周期来实现。由于项目有特定的目标,一般产品制造出来通过验收则项目生命周期就算完成。而产品生命周期则不同,既包括了项目开始前的预研,评估和可行性研究,也包括了项目完成后产品 的维护和废弃

产品管理和项目管理

产品管理的目标是产品,是产品生命周期 项目管理的是项目生命周期和项目目标的实现

产品管理关心的是产品能够真正的赚钱和创造效益,因此前期的项目分析决策,后期推广都很重要,跟产品管理相对应的是组合项目管理。IPD集成产品开发是产品管理常用的方法论,其中两个重点就是组合项目管理和研发流程管理

项目管理关注的是项目能够按照既定的目标顺利完成。产品究竟应该规划哪些Feature不是项目管理的事情,而是项目管理的范围输入。项目管理始终关注的是进度,质量,成本和范围四个要素,要把项目做好则首先需要保证过程的稳定性。在软件项目管理中需要综合考虑工程,项目管理和支持过程三个方面的内容,因此实施CMMI或其它一些敏捷的项目管理方法论是可以保证项目管理成果的重要方法

授权的范围不同

项目经理一般是被授权的合同履约的负责人: 项目合同是规定承、发包双方责、权、利具有法律约束力的契约文件,是处理双方关系的主要依据,也是市场经济条件下规范双方行为的准则 项目经理是公司在合同项目上的全权委托代理人,代表公司处理执行合同中的一切重大事宜,包括合同的实施、变更调整、违约处罚等,对执行合同负主要责任

当然,根据企业的不同,老板能否给予项目经理相应的授权是另一回事

产品经理的授权是保证流通链的畅通: 产品经理保证其所负责的产品,从上游创意、研发开始,至采购、生产,到下游渠道、通路,直至终端用户的整个流通链的畅通,因此要求产品经理既要有产品知识,也要有市场意识,还要具备协调能力,例如:财务、售后、物流……

但是,产品经理并无对外签订合同的授权

Read More


some ppt 2016-01-01

git 下载

java事务设计策略 下载

Read More


raspberry pi 获取温度 2016-01-01

raspberry pi 获取温度

获取温度

import os
import commands

#vcgencmd measure_temp
#cat /sys/class/thermal/thermal_zone0/temp


# Return CPU temperature as a character string                                      
def getCPUtemperature():
    res = os.popen('vcgencmd measure_temp').readline()
    return(res.replace("temp=","").replace("'C\n",""))

# Return GPU temperature as a character string
def get_gpu_temp():
    gpu_temp = commands.getoutput( '/opt/vc/bin/vcgencmd measure_temp' ).replace( 'temp=', '' ).replace( '\'C', '' )
    return  float(gpu_temp)
    # Uncomment the next line if you want the temp in Fahrenheit
    # return float(1.8* gpu_temp)+32


# Return RAM information (unit=kb) in a list                                       
# Index 0: total RAM                                                               
# Index 1: used RAM                                                                 
# Index 2: free RAM                                                                 
def getRAMinfo():
    p = os.popen('free')
    i = 0
    while 1:
        i = i + 1
        line = p.readline()
        if i==2:
            return(line.split()[1:4])

# Return % of CPU used by user as a character string                                
def getCPUuse():
    return(str(os.popen("top -n1 | awk '/Cpu\(s\):/ {print $2}'").readline().strip(\
)))

# Return information about disk space as a list (unit included)                     
# Index 0: total disk space                                                         
# Index 1: used disk space                                                         
# Index 2: remaining disk space                                                     
# Index 3: percentage of disk used                                                  
def getDiskSpace():
    p = os.popen("df -h /")
    i = 0
    while 1:
        i = i +1
        line = p.readline()
        if i==2:
            return(line.split()[1:5])


# CPU informatiom
CPU_temp = getCPUtemperature()
CPU_usage = getCPUuse()

# RAM information
# Output is in kb, here I convert it in Mb for readability
RAM_stats = getRAMinfo()
RAM_total = round(int(RAM_stats[0]) / 1000,1)
RAM_used = round(int(RAM_stats[1]) / 1000,1)
RAM_free = round(int(RAM_stats[2]) / 1000,1)

# Disk information
DISK_stats = getDiskSpace()
DISK_total = DISK_stats[0]
DISK_used = DISK_stats[1]
DISK_perc = DISK_stats[3]

if __name__ == '__main__':
  print('')
  print('CPU Temperature = '+CPU_temp) , "C"
  print('CPU Use = '+CPU_usage)
  print "GPU Temperature = ", str(get_gpu_temp()), "C"
  print('')
  print('RAM Total = '+str(RAM_total)+' MB')
  print('RAM Used = '+str(RAM_used)+' MB')
  print('RAM Free = '+str(RAM_free)+' MB')
  print('')  
  print('DISK Total Space = '+str(DISK_total)+'B')
  print('DISK Used Space = '+str(DISK_used)+'B')
  print('DISK Used Percentage = '+str(DISK_perc))

Read More


people 2016-01-01

Bob Lee

Bob Lee 是 Google 公司工程师,也是 Guice 项目的创建人和 Tech Lead

Guice 是开源,超轻量级的,为 Java 5 及后续版本设计的依赖注入容器 与其他现有的轻量级框架相比,利用 Guice 开发的应用非常容易进行单元测试

他写的一个Singleton模式的写法前不久还得到了OnJava编辑的推荐

public class Singleton {

    static class SingletonHolder {
        static Singleton instance = new Singleton();
    }

    public static Singleton getInstance() {
        return SingletonHolder.instance;
    }
}

在加载singleton时并不加载它的内部类SingletonHolder,而在调用getInstance()时调用SingletonHolder时才加载SingletonHolder,从而调用singleton的构造函数,实例化singleton,从而达到lazy loading的效果

Rob Pike

AT&T Bell Lab前Member of Technical Staff ,现在google研究操作系统 罗伯伯是Unix的先驱,是贝尔实验室最早和Ken Thompson以及 Dennis M. Ritche 开发Unix的猛人,UTF-8的设计人 罗伯伯还是1980年奥运会射箭的银牌得主 他还是个颇为厉害的业余天文学家,设计的珈玛射线望远镜差点被NASA用在航天飞机上 还是两本经典,The Unix Programming Environment 和 The Practice of Programming 的作者之一

还写出了Unix下第一个基于位图的窗口系统,并且是著名的blit 终端的作者 还是号称锐意革新的操作系统,Plan9,的主要作者。可惜的是,Plan9并没有引起多少人的注意 一怒之下,写出了振聋发聩的雄文 Systems Software Research is Irrelevant,痛斥当下系统开发的不思进取,固步自封的弊病。虽然这篇文章是罗伯伯含忿出手,颇有偏激之词,但确实道出了系统开发的无奈:开发周期越来越长,代价越来越大,用户被统一到少数几个系统上,结果越来越多的活动是测量和修补,而真正的革新越来越少

就在罗伯伯郁闷之极的时候,google登门求贤来了。如果说现在还有一家大众公司在不遗余力地把系统开发推向极致的话,也就是google了 随便看看google的成果就知道了。具有超强容错和负载平衡能力的分布式文件系统GFS (现在能够用100,000台廉价PC搭起一个巨型分布系统,并且高效便宜地进行管理的系统也不多哈),大规模机器学习系统(拼写检查,广告匹配,拼音搜寻。。。哪个都很牛的说),更不用说处理海量并行计算的各式google服务了

Rob在System Software Research is Irrelevant里萧瑟地说现在没有人再关心系统研究的前沿成果了。想不到他错了,应为google关心。google网络了大批功成总是试图吸取系统研究的最新成果。想必Rob Pike在google很幸福。愿他做出更棒的系统

Stanley B Lippman

曾在Bell实验室工作10余年 从1984年开始一直从事C++方面的工作,是与Bjarne Stroustrup [C++的发明人] 一起工作的早期成员之一,参与开发最初的C++编译器,Stan曾经致力于cfront的各种实现,从1986年的版本1.1到版本3.0,并领导了 2.1和3.0版本的开发组 而后又参与了Foundation研究项目中关于程序设计环境的对象模型部分 现为Microsoft Visual C++开发组的系统架构师

Stan Lippman先生撰写了数本书籍: - 《C++ Primer》 - 《Essential C++》 - 《Inside the C++ Object Model》 - 《C# Primer》 并编辑了《C++ Gems Programming Pearls from The C++ Report》

Read More


设计模式 2016-01-01

Read More


基于Oracle 的sql优化 2016-01-01

RBO

create table emp_temp as select * from emp;

alter session set optimizer_mode='RULE'; set autotrace traceonly explain;

create index idx_mgr_temp on emp_temp(mgr); create index idx_deptno_temp on emp_temp(deptno);

select * from emp_temp where mgr>100 and deptno>100;

INDEX RANGE SCAN IDX_DEPTNO_TEMP

字典顺序

根据对象在字典创建顺序,后创建的优先,选择到 IDX_DEPTNO_TEMP

等价改写目标SQL,让RBO生效

number,date加 0,char加 || select * from emp_temp where mgr>100 and deptno+0>100; 让deptno索引失效,就走到了mgr索引

drop index idx_mgr_temp 后,再创建,再执行就走了变成后创建的mgr索引

rbo优化器硬编码在代码里,15个级别,1为rowid,15为 full table scan

CBO

查询改写

create table t1 (c1 number,c2 varchar2(10)); create table t2 (c1 number,c2 varchar2(10));

create index idx_t2 on t2(c1);

insert into t1 values (10,'test'); insert into t2 values (10,'test');

select t1.c1,t2.c2 from t1,t2 where t1.c1=t2.c1 and t1.c1=10;

没有用到t2.c1 索引列,可结果中 INDEX RANGE SCAN IDX_T2

所以谓词被加了 and t2.c1=10

优化器基础知识

优化器模式

RULE

CHOOSE

FIRST_ROWS_n

FIRST_ROWS

ALL_ROWS

数据访问方法

表访问方法

全表扫描

rowid扫描

索引访问方法

索引唯一扫描

索引范围扫描

索引全扫描

索引快速全扫描

索引跳跃式扫描

create table emp_temp as select * from emp; select count(empno) from emp_temp; create unique index idx_emp_temp on emp_temp(empno);

exec dbms_stats.gather_table_stats(ownname => 'C##SCOTT',tabname => 'EMP_TEMP',estimate_percent => 100,cascade => true,method_opt => 'for all columns size 1');

alter system flush shared_pool; alter system flush buffer_cache; set autotrace traceonly; 会提示权限之类问题 utlxplan.sql grant all on plan_table to c##scott; @Catalog.sql 很长时间 plustrce.sql grant plustrace to c##scott; grant select any dictionary to c##scott;

select * from emp_temp where empno=7369;

观察consistent gets drop index idx_emp_temp ; create index idx_emp_temp on emp_temp(empno);

alter system flush shared_pool; alter system flush buffer_cache; 再次 select * from emp_temp where empno=7369; 会发现consistent gets多一次

表连接

表连接顺序

实际不管有多少表做连接,执行时只能两两连接 要先决定驱动与被驱动表,连接出结果后再和剩余表连接

表连接方法

排序合并连接、嵌套循环连接、HASH连接、笛卡尔连接

访问单表方法

走全表扫描还是索引,什么索引访问方法

Read More


nosql 2016-01-01

《七周七数据库》读书报告 https://ring0.me/2013/09/seven-databases-in-seven-weeks/

Web和大数据发展,关系模型暴露问题:

  • 模式不易修改

关系模型要求事先指定实体、属性和关系,复杂多变的Web环境中,经常需要增加或修改属性和关系,甚至不同的实体需要不同的属性集

  • 严格的一致性模型和持久性牺牲了速度

某些应用只要求所谓“最终一致性”,或对少量数据丢失不敏感 一些NoSQL数据库利用不严格的持久性需求,大量操作放内存,吞吐量数量级提升

  • 严格的一致性模型牺牲了可用性或分区容忍性

关系数据库往往最关注CAP定理中的一致性,而大数据条件下可能首要考虑分区容忍性/可用性,需要适当牺牲一致性

数学上优雅的关系模型撞上了可扩放性(scalability)之墙。NoSQL运动应运而生 NoSQL强调定制性,按需求选合适数据库,设计合适分布式架构,增加了dba负担,买几台“大铁块”似的高性能机器就能高枕无忧的时代一去不复返了 对程序员来说,NoSQL一般是无模式(schema)的,看似免除了一些麻烦,事实上正如动态类型语言和静态类型语言的区别,约束少了,bug 也就更容易藏身了

Riak

分布式kv 数据库。一实例若干bucket(类似表),每bucket可有很多key(类似行),value是任何类型(由HTTP header中的Content-Type指定)的数据

通过rest api GET/POST/PUT(UPDATE)/DELETE实现CRUD。数据类型和一些选项也通过HTTP header指定

Riak不支持关系操作

  • 容错性

灵感来源于Amazon Dynamo论文,关键贡献在CAP间实现tradeoff。Riak有三个参数:

N:集群中副本数量,即一次写入最终复制到的节点数量。注意,N可以小于集群中的节点数量。 W:一次写入在返回响应之前,必须成功写入的节点数量。W小于N,则成功写入了W个节点后就对客户端返回成功,剩下N-W个节点还在复制数据 R:成功读出一项数据所需的节点数量,即从R个节点读出数据,并选择时间戳最新的(稍后详述)。为什么要从R个节点(而非1个)读出数据呢?因为当W小于N时,有可能写操作事实上还没有完成就返回成功了,此时开始了读操作,读到的可能恰好是旧值。如果R+W>N,可以证明读出的一致的数据一定不会是旧值

N、R、W经典配置: W=N,R=1:关系数据库的做法,通过确保写操作在返回之前完成来保证一致性,但写入比较慢 W=1,R=N:使写入最快,牺牲读取速度 W = R = N/2+1:分担介于读写之间的延迟

N、R、W可对每个key采取不同设置,甚至可以在GET时传入参数指定R。使Riak可足够灵活地处理不同一致性需求和读写频率的数据

  • 向量时钟

R>1时要决定哪个读出的版本是最新的。这是分布式系统中根本问题 最简单方案:所有机器时间精确同步,给数据打上时间戳就行。Google的Spanner就这样做,利用原子钟和NTP,实现了全球任意两台机器的时间差不超过10ms

Riak向量时钟用Git类似技术。更新时在key的向量时钟末尾附加上一个伪随机的戳,相当于向量长度增加1 两节点进行同步时,双方向量相同,不用同步 一个是另一个子集,只需单向复制(类似Git fast-forward) 两向量互不为子集,客户端查询key时,返回两个值。客户端可自行解决冲突,把新的value和向量提交上去(类似Git merge conflict)

更新次数越来越多,向量不断增长。Riak提供了修剪选项,可将老向量时钟(如一天前的)修剪掉

HBase

基于Google BigTable思想。HBase基于Hadoop(可扩放(scalable)计算平台),提供了分布式文件系统和MapReduce 内置支持数据的版本管理,用精确到毫秒的时间戳标识数据的版本,很适合wiki之类需要保存历史版本的应用

相比Riak,Hbase的可用性没有那么高。Riak可以在仅有一个节点存活时仍然正常工作,而Hbase只能在一两个节点当机的灾难中存活下来 Hbase可以轻松scale-up,但难以scale-down

MongoDB

关系数据库查询能力强大,Riak/Hbase具有分布式的特点,MongoDB在两者之间找到最佳结合点。很多新兴Web应用采用mongo持久存储

数据结构

由若干个集合(collection)组成(类似表),每集合有若干文档(document)(类似行),每个文档是个JSON对象(无模式,值可以嵌套任意深度)

文档的唯一标识符_id由时间戳、机器ID、进程ID、增量计数器构成

关系数据库中需要表间连接(JOIN)的数据结构,在MongoDB中往往可以通过子文档来表达 文章包含评论为例 关系模型需文章表和评论表,再建外键 Mongo只需建立一个文章的集合,每篇文章作document,其中一个字段是子文档,包含了这篇文章的所有评论,数据结构比关系模型更自然 如果需要打破树形结构,查询某个作者曾经发表的所有评论,则可以为它建立索引,查找起来并不会比关系数据库慢 Mongo可使用B树、二维索引或球形地理空间索引

复制与分片 采用与关系数据库热备类似增加冗余。集群自动选举主节点承担所有读写操作,从节点自动同步数据。需保证奇数个节点存活 大数据后可按照值范围横向分片(sharding)。需要一个mongos服务器作为“反向代理”,作为接受用户请求的单点,同时维护各mongod节点的数据集划分和分发请求

像RAID一样,复制和分片可同时使用,目的分别是增加冗余和提高性能 3台服务器构成一个副本集,2个副本集构成2个分片,再加上配置服务器和mongos“反向代理”服务器,构成了8台服务器的集群

CouchDB

似MongoDB。主要区别 更轻量级,可像SQLite一样嵌入程序 数据带有版本号

  • 事务

MongoDB/CouchDB都不提供 锁/事务 MongoDB通过内置“原子操作”实现 CouchDB避免冲突的秘诀则是确保只修改最新版本的文档 CouchDB给每文档分配rev 的域(顺序递增的版本号+伪随机字符串),每次文档发生变化时,rev 域被更新 更新/删除时,除了提供 id,还要提供 rev,如果 _rev 不匹配,则拒绝操作。拒绝操作可能是由于上次读出此文档与进行更新、删除操作之间,此文档被修改了,使得版本号被更新

在删除文档时,CouchDB并不就地修改文档,而是用一个新的空白文档“更新”它

  • 复制

冗余方式似Riak,每节点都可独立读写 冲突时同一 id,两个节点 rev 不同。处理方法简单粗暴:两个不同 _rev 间二选一,由于CouchDB保存了文档的历史版本,如果客户端发现不对头,可以读出历史版本进行恢复

Web大潮下,为提高分布式可用性,除了关系模型之外,涌现出多种各具特色的数据库 开发中,根据项目的实际需求,选用合适的数据库组合,不再受到一种或两种数据库范式的束缚

Read More


nodejs 2016-01-01

http://yanyiwu.com/work/2014/01/23/nodejs-chu-ti-yan.html

著名的异步IO高并发单线程的server node的整体思路: - v8 : googlejs引擎 - uv : 跨平台的网络事件库 - others :工具类,比如http参数解析,ssl加密等

node是单线程的,但是却是高并发的,两者看似矛盾,主要归功与uv库,本质上就是一个事件驱动的库

可以把uv理解为对epoll之类(高并发事件驱动IO多路复用)的封装, 或者,直接理解为中断信号编程 注册一些事件,当事件发生的时候,系统自动调用注册好的事件回调函数。 这样的好处是非阻塞,同时也方便做到高并发 开发nodejs时把可能耗时较多的函数注册成回调函数

node其实可以看成是一个c++写好了若干网络服务库,但是引入了v8,让我们可以简单的使用js来调用这些牛逼的服务库

单线程和异步IO 传统编程方法代码逻辑同步运行,进行并行的话需要多线程或者多进程,如Apache, Nginx nodejs天生支持异步编程,实际代码就是各种使用回调函数 nodejs天生支持异步编程函数,就是在实际编程中为何将回调函数传入某些库函数之后会发生什么事情? 本质上就是libuv的功劳,用多线程和阻塞IO来模拟异步

Read More


nodejs 2016-01-01

https://github.com/i5ting/node-newbie-guide/issues/6 异步处理之Q

了解什么是promise模式

了解Q https://github.com/kriskowal/q 了解Q 的readme.md里的用法 了解Q的设计思想,https://github.com/kriskowal/q/tree/v1/design 学习Q的bdd测试jasmine https://github.com/kriskowal/q/tree/v1/spec

查看Q的例子

https://github.com/kriskowal/q/tree/v1/examples

总结travis用法 总结jshint用法 总结cover用法 总结 Gruntfile.js用法

在Node.js中使用promise摆脱回调金字塔| Nyasoft http://nya.io/Node.js/promise-in-nodejs-get-rid-of-callback-hell/

原创:形象的讲解angular中的$q与promise - 雪狼 http://www.cnblogs.com/asnowwolf/p/3689300.html

面向Node.js新手的7个技巧 http://jinlong.github.io/2013/10/17/7-tips-for-a-node-dot-js-padawan/

Read More


nio 2016-01-01

NIO 将最耗时的 I/O 操作(填充和提取缓冲区)转移回os,提高速度 原有I/O 以流方式处理数据,NIO以块方式处理数据

通道、缓冲区 通道是双向的,流是单向的(Input/OutputStream)

通道是对原 I/O 包中流的模拟

阻塞

  • Thread.sleep 放弃cpu
  • 同步代码/方法 无法取得锁,进入等候队列
  • 进入了同步代码/方法后,遇到Object.wait ,进入等候队列,等 nofity(all) 才再次进步就绪队列
  • 线程 join
  • io/远程(如socket)等待资源

java(jdk 1.6) nio基于Linux nio,用reactor(类似observer)和多线程实现异步非阻塞 jdk7 加入aio基于linux aio,让netty等nio框架要么消失,要么升为aio

mina xsocket比较

相同点

  • 都对nio进行了有效屏蔽, 简化开发, 对于文本流模式的应用,两者都非常简单,实现一个基本的handle就可以
  • 提供了一些常见的辅助功能,比如日志等, mina支持更全面一些
  • 可以通过绑定各种附加属性实现基于会话的工作方式,会话控制都提供了完整的支持
  • 理论上都可以提供lowerlevel数据的处理支持, 不过实际操作, mina比较复杂,文档也缺失
  • 都提供了客户端使用包,简化客户端开发

差异

设计的出发点不同, xsocket是轻量级解决方案,核心思想是屏蔽,简化nio方式的的开发,并不需要过多的学习 Mina更多是提供服务器开发的基础平台,相对来说提供的支持要全面,复杂,缺少对java nio的深入理解, 对mina的一些特性就难以利用 对数据的处理,xsocket的出发点是通过提供对基本类型的支持来做到简单灵活的操作, 而mina则希望在更高的层面上即通过自定义的协议扩展来屏蔽掉应用对数据的处理操作,把核心放置到业务处理逻辑上

做一个简单比较如下

自定义协议

  • 自定义协议 mina通过 encoder 和decoder模式支持自定义协议,屏蔽底层数据的操作,对于客户端和服务器都是java的应用,处理比较简单。缺省提供了对文本, java对象的处理。协议是以byte[]为基础的,mina就不能很好的处理 xsocket并不关注这点, 关注的是对nio的屏蔽

  • 对filter模式的支持 mina利用filter模式提供对数据流操作的封装和扩展,是核心模式。 另外也提供了一些缺省的有用filter,比如compress等 xsocket不关注这个问题, 所以说mina更象应用服务器平台, xscoket是一个通讯模块

  • 缺省对文本操作的支持 文本流模式是比较常见的网络应用模式,比如http , smtp服务,聊天应用等 mina 通过增加一个TextLineCodecFactory filter来提供对文本操作的支持, 传入的数据会被自动整理成文本信息。 但是并未提供额外的处理支持 chain.addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory()));

    public void messageReceived(IoSession session, Object message) { Logger log = LoggerFactory.getLogger(ChatProtocolHandler.class); log.info("received: " + message); String theMessage = (String) message; String[] result = theMessage.split(" ", 2); //自己分析文本段落

    xscoket把对文本的支持做为基本属性,并且提供了Delimiter这样的支持,相比mina要好用一些。而对于解析http中mulitpart这样的文本二进制混合的结构,显然要比mina 好使

String data = nbc.readStringByDelimiter("\r\n", "gbk"); //缺省提供delimiter的操作, System.out.println(data); //中文读取正常 nbc.write(data + "\r\n"); //回写是乱码 nbc.write(data + "\r\n", “gbk”); //正常

  • 对流的操作 mina提供一个streamiohandler的类, 可以使用基于流的方式进行处理操作,实际使用有点复杂,需要在一个独立的线程中工作,会增加服务器负担 xsocket 没仔细研究, 但是因为提供了对基本类型操作的支持,所以可以自行包装流来解决,比较简单

  • 对lowerlevel方式数据的处理 mina需要熟悉nio框架部分的bytebuffer的操作 xsocket可以直接支持以基本类型的模式进行操作, 也支持使用bytebuffer的方式,更加简单灵活

  • 对fragment的处理 (tcp网络的特性,即一次数据可能分为多个包发送) mina对分包会直接报错, 需要使用会话控制的方式来对包进行组装处理,比较复杂。 另外从服务器向客户端写大包的时候, 1.1和2.0处理不同,2.0不做控制会直接报一个bytebuffer溢出的错误。 xscoket缺省会吞掉这个错误,自动采用重试的方式尝试读取数据,对开发来说比较简单,另外也可以提供类似mina那样的安全处理模式,代码比mina要简单

  • 文档支持 mina 比较多,但是语焉不详,问题要靠自己啃代码和上论坛 xsocket 只有一篇文档, 但是比较详尽的介绍了所有需要的知识。另外,视乎, xsocket的代码质量要更好一些, mina更向是不断学习过程中不断完善改进的作品

  • 学习曲线 mina 要较好的使用需要对nio有深入的了解, 一般使用学习难度不大 xsocket 基本不用学习

结论

使用mina的自定义协议方式处理需要额外的工作量, 而mina对直接操作基本数据类型的支持并不好,或者说需要深入的学习nio部分内容 最终因为fragment和对lowerlevel数据的更简单的支持让我选择了xsocket,很轻松的完成了移植工作

Read More


nginx php 2016-01-01

相关内容有 php.ini的 cgi.fix_pathinfo=1

Nginx文件类型错误解析漏洞

http://waiting.iteye.com/blog/1202216 说到官方推荐 try_files 代替 if

漏洞分析:nginx默认以cgi的方式支持php的运行,譬如在配置文件当中可以以

location ~ \.php$ {
    root html;
    fastcgi_pass 127.0.0.1:9000;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
    include fastcgi_params;
}

的方式支持对php的解析,location对请求进行选择的时候会使用URI环境变量进行选择,其中传递到后端Fastcgi的关键变量SCRIPT_FILENAME由nginx生成的$fastcgi_script_name决定,而通过分析可以看到$fastcgi_script_name是直接由URI环境变量控制的,这里就是产生问题的点。

为较好支持PATH_INFO的提取,php.ini存在cgi.fix_pathinfo选项,从SCRIPT_FILENAME里取出真正的脚本名 假设存在 http://localhost/index.jpg 以 http://localhost/index.jpg/index.php 访问 将会得到一个URI /index.jpg/index.php

经过nginx的location指令,该请求将会交给后端的fastcgi处理,nginx为其设置环境变量SCRIPT_FILENAME,内容为

/scripts/index.jpg/index.php

而在其他的webserver如lighttpd当中,SCRIPT_FILENAME被正确的设置为 /scripts/index.jpg 所以不存在此问题

后端的fastcgi在接受到该选项时,会根据fix_pathinfo配置决定是否对SCRIPT_FILENAME进行额外的处理 一般情况下如果不对fix_pathinfo进行设置将影响使用PATH_INFO进行路由选择的应用,所以该选项一般配置开启 php通过该选项之后将查找其中真正的脚本文件名字,查找的方式也是查看文件是否存在,这个时候将分离出SCRIPT_FILENAME和PATH_INFO分别为 /scripts/index.jpg和index.php

最后,以/scripts/index.jpg作为此次请求需要执行的脚本,攻击者就可以实现让nginx以php来解析任何类型的文件了

访问一个nginx来支持php的站点,在一个任何资源的文件如robots.txt后面加上/index.php,这个时候可以看到如下的区别:

访问http://localhost/robots.txt

HTTP/1.1 200 OK
Server: nginx/xxx
Date: xxxx
Content-Type: text/plain
Content-Length: 18
Last-Modified: Txxx
Connection: keep-alive
Keep-Alive: timeout=20
Accept-Ranges: bytes

访问访问http://www.80sec.com/robots.txt/80sec.php

HTTP/1.1 200 OK
Server: nginx/xxx
Date: xxx
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive
Keep-Alive: timeout=20
X-Powered-By: PHP/xxx

其中的Content-Type的变化说明了后端负责解析的变化,该站点就可能存在漏洞

Read More


nginx 2016-01-01

Read More


nosql 2016-01-01

从IP网络到内容网络 https://ring0.me/2013/09/content-centric-networking/ 讲“OSI七层模型”的烂课本毁了多少人 物理层:信号传输的媒介,光纤、双绞线(网线)、空气(wifi)……介质需要自己的编码和调制方式,才能把数据变成xx送出去 数据链路层:拿开会打个比方。说话可能不小心说错或者听错,需要有纠错、让对方重说的机制(校验和、重传);几个人都想发言,需要有一种方式进行仲裁,谁先说谁后说(信道分配、载波监听);一个人发言前后需要示意,以便让别人知道他说完了(成帧)。 网络层:计算机网络初期争议最大的地方。电信行业的传统巨头认为,应该像打电话一样在两端点间的路径上预留出一部分带宽,建立起通信双方的 “虚电路”。而当时正处于冷战时期,美国国防部要求建立起的网络在中间几条线路遭到毁灭性打击时,通信仍然不能中断。于是,最终采用了 “分组交换” 方案,把数据分成若干小块分别封装和投递。就像寄信一样,要投递到远方的机器,就要在信封上写明地址,而且地址要使得邮递员看到它就知道该走哪条路送给下级邮局(比如用身份证号作为地址就是个很糟的主意)。IP 协议是网络层协议的事实标准,大家应该都知道 IP 地址。 传输层:计算机网络早期最重要的应用就是在两台计算机间建立“连接”:远程登录、远程打印、远程访问文件……传输层就是在网络层数据包的基础上,抽象出连接的概念。这里的“连接”跟“虚电路”的主要区别是“虚电路”要预留一定的带宽,而“连接”是尽力而为投递的,不对带宽作任何保证。由于互联网上的流量多是突发(burst)的,分组交换比虚电路提高了资源利用率。事实上,历史往往是轮回的,如今在数据中心里,由于流量可预测且可控,又正在回到中心控制的预留带宽方案。 应用层:这就不用多说了,Web 基于的 HTTP、FTP、BitTorrent 都是应用层协议。

端口映射的两个坑 https://ring0.me/2014/02/port-mapping-fallacies/

3G 为什么比 Wi-Fi 费电 https://ring0.me/2014/11/why-3g-consumes-more-power-than-wifi/

Read More


netty 2016-01-01

http://www.udpwork.com/item/14525.html http://blog.leanote.com/post/proyang/Netty-%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90%EF%BC%9ANetty-%E4%BB%8B%E7%BB%8D http://blog.leanote.com/post/proyang/Netty-%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90%EF%BC%88%E4%B8%80%EF%BC%89%EF%BC%9A%E5%BC%95%E8%A8%80%E3%80%81%E5%9F%BA%E7%A1%80%E4%BB%8B%E7%BB%8D http://blog.leanote.com/archives/proyang http://www.chinaxing.org/archive.html http://yihongwei.com/2014/01/netty-4-x-bytebuf/

Read More


nb闪闪的blog 2016-01-01

麦子迈 2011年开始,DB,OS,Storage 。。。巨多深度文章

Read More


mysql初始化 2016-01-01

mysql最精简,最终5M http://cdn.mysql.com/Downloads/MySQL-5.6/mysql-5.6.22-winx64.zip 提取 bin\mysqld.exe bin\mysql.exe share\english\errmsg.sys upx -9 压缩

mysql.sql 从 mysql\share\mysql_system_tables.sql 复制来,第一行加上use mysql; 最底下加一句授权 INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N');

init.cmd

@echo off
@taskkill /im mysqld.exe /f 2>nul >nul
@taskkill /im mysqld.exe /f 2>nul >nul
rd /s /q e:\data\mysql 2>nul
md e:\data\mysql\mysql
bin\mysqld.exe  --bootstrap --console  < mysql.sql
RunHiddenConsole bin\mysqld.exe
rem bin\mysqld --defaults-file="my.ini"
echo done

my.ini

修改datadir路径

[client]
default-character-set=utf8

[mysqld]
explicit_defaults_for_timestamp=true
character_set_server=utf8
# Remove leading # and set to the amount of RAM for the most important data
# cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.
innodb_buffer_pool_size = 128M

# Remove leading # to turn on a very important data integrity option: logging
# changes to the binary log between backups.
# log_bin

# These are commonly set, remove the # and set as required.
#basedir = z:\mysql
datadir = z:\mysql\data
# port = .....
# server_id = .....


# Remove leading # to set options mainly useful for reporting servers.
# The server defaults are faster for transactions and fast SELECTs.
# Adjust sizes as needed, experiment to find the optimal values.
join_buffer_size = 128M
sort_buffer_size = 2M
read_rnd_buffer_size = 2M 

# sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES 
transaction-isolation = READ-COMMITTED

mysql 5.7 bin\mysqld.exe --log_syslog=0 --initialize-insecure --console < init.sql bin\mysqld.exe --log_syslog=0

Read More


mybatis 2016-01-01

Read More


mq 2016-01-01

消息中间件特点:解耦,异步和并行 不需要及时可靠响应的业务,消息中间件大大提高业务上层的吞吐量

redis可作入门级消息队列 一生产者对应一消费者,blist 可实现 一生产者对应多消费者,pub/sub 模式可实现 坑:消费者一段时间断开,将不会收到这段时间内的数据 严格意义上的消息中间件,需要保证数据的可靠性

基于MQ的RPC传输机制的好处是,由于队列本身具有的缓冲性质,可以在应对高并发的时候保证请求不丢失(事实上针对web请求,在面对高并发时常用的一种机制也是排队处理) MQ提供的分布式集群前面加个HAProxy就能提供很好的负载均衡。

一个基于redis和disque实现的轻量级异步任务执行器 http://vinoyang.com/2015/08/29/a-lightweight-async-task-invoker-based-on-redis-and-disque/

对 MQ 的需求,相比 JMS 标准有几点要求更高:

  1. 必须优美灵活地支持集群消费

  2. 尽量支持消息堆积

  3. 服务高可用性和消息可靠性

  4. 有起码的运维工具做集群管理和服务调整

其他 提供顺序消息、事务、回溯等面向特别场景的功能更好,目前暂不需要

架构 基本组成包括 nameserver、broker、producer、consumer 四种节点,前两种构成服务端,后两种在客户端上 还有其他辅助的进程,不提

NameServer 没有NameServer 的中间件中,服务端集群就由干活的 broker 组成 ,其中的实例分主从两种角色 客户端就要知道需要连接到哪个地址的 broker 上去做事情,就需要配置服务端机器的 IP 地址 如果服务端部署结构复杂,客户端的配置结构也挺复杂,更讨厌的是甚至可能需要客户端也得更新地址配置

有了两种思路的方案: 一是引入 NameServer,负责提供地址。客户端只需要知道 NameServer 机器的地址,需要找服务器干活的时候,先问 NameServer 我该去找哪个服务器 这样,因为 NameServer 很简单而不容易出故障,所以极少发生架构调整。而结构复杂的 broker 部分,无论怎么调整,客户端都不用再操心

RQ 2.x 用的是 Zookeeper 做 NameServer,3.x 用的是自己搞的独立服务

二是引入反向代理,就是把服务端地址配置成虚拟 IP 或域名这种思路,这一个地址背后其实可能是一个集群,客户端发起请求后,由网络设施来中转请求给具体服务器

两者各有优劣,综合使用也挺正常

NameServer工作机制

I.NameServer 自身之间的机制

可以启动多个实例,相互独立,不需要相互通信,可以理解为多机热备

II.NameServer 与 broker 之间

Broker 启动后,向指定的一批 NameServer 发起长连接,此后每隔 30s 发送一次心跳,心跳内容中包含了所承载的 topic 信息 NameServer 每隔 2 分钟扫描,如果 2 分钟内无心跳,就主动断开连接 当然如果 Broker 挂掉,连接肯定也会断开

一旦连接断开,因为是长连接,所以 NameServer 立刻就会感知有 broker 挂掉了,于是更新 topic 与 broker 的关系。但是,并不会主动通知客户端

III.NameServer 与客户端之间

客户端启动时,要指定这些 NameServer 的具体地址。之后随机与其中一台 NameServer 保持长连接,如果该 NameServer 发生了不可用,那么会连接下一个

连接后会定时查询 topic 路由信息,默认间隔是 30s,可配置,可编码指定 pollNameServerInteval

(注意是定时的机制,不是即时查询,也不是 NameServer 感知变更后推送,所以这里造成接收消息的实时性问题)

NameServer 的部署与应用 I. 运行 NameServer

启动: nohup mqnamesrv &

终止:

sh ./mqshutdown Useage: mqshutdown broker | namesrv II. Broker 指定 NameServer

有几种方式 1. 启动命令指定 nohup mqbroker -n "192.168.36.53:9876;192.168.36.80:9876" & 2. 环境变量指定 export NAMESRV_ADDR=192.168.36.53:9876;192.168.36.80:9876 3. 配置指定

bin 和 conf 下面的配置文件里面有 root@rocketmq-master1 bin]# sh mqbroker -m namesrvAddr=

III. 客户端指定 NameServer

有几种方式:

  1. 编码指定

producer.setNamesrvAddr("192.168.36.53:9876;192.168.36.80:9876");

所以这里指定的并不是 broker 的主主或主从机器的地址,而是 NameServer 的地址。

2.java 启动参数

-Drocketmq.namesrv.addr=192.168.36.53:9876;192.168.36.80:9876 3. 环境变量 export NAMESRV_ADDR=192.168.36.53:9876;192.168.36.80:9876 4. 服务 客户端还可以配置这个域名 jmenv.tbsite.alipay.net 来寻址,就不用指定 IP 了,这样 NameServer 集群可以做热升级。

该接口具体地址是 http://jmenv.tbsite.net:8080/rocketmq/nsaddr

(理论上,最后一种可用性最好;实际上,没试出来。)

Broker 的机制

  1. 消息的存储

1.topic 与 broker 是多对多的关系,一个 topic 可以做分区配置的,使得可以分散为队列交付给多个 btoker。分区的设计采用的是偏移量做法。 2.Broker 是把消息持久化到磁盘文件的,同步刷盘就是写入后才告知 producer 成功;异步刷盘是收到消息后就告知 producer 成功了,之后异步地将消息从内存 (PageCache) 写入到磁盘上。 (注意此处涉及到磁盘写入速度是否大于网卡速度的问题,应用的不好可能造成消息堆积) 3. 磁盘空间达到 85% 之后,不再接收消息,会打印日志并且告知 producer 发送消息失败。 4. 持久化采取的是 ext4 文件系统,存储的数据结构另有其他文档,运维时需要处理文件目录时另说。 II. 消息的清理

  1. 每隔 10s 扫描消息,可以通过 cleanResourceInterval 配置。
  2. 每天 4 点清理消息,可以通过 deleteWhen 配置。磁盘空间达到阈值时也会启动。
  3. 文件保留时长为 72 小时,可以通过 fileReservedTime 配置。也就是消息堆积的时限。 III. 消息的消费

1.IO 用的是文件内存映射方式,性能较高,只会有一个写,其他的读。顺序写,随机读。

  1. 零拷贝原理:

以前使用 linux 的 sendfile 机制,利用 DMA(优点是 CPU 不参与传输),将消息内容直接输出到 sokect 管道,大块文件传输效率高。缺点是只能用 BIO。

于是此版本使用的是 mmap+write 方式,代价是 CPU 多耗用一些,内存安全问题复杂一些,要避免 JVM Crash。

IV.Topic 管理

  1. 客户端可以配置是否允许自动创建 Topic,不允许的话,要先在 console 上增加此 Topic。同时提供管理操作。
  2. 物理特性

1.CPU:Load 高,但使用率低,因为大部分时间在 IO Wait。

  1. 内存:依旧需要大内存,否则 swap 会成为瓶颈。

  2. 磁盘:IO 密集,转速越高、可靠性越高越好。

VI.broker 之间的机制

单机的刷盘机制,虽然保障消息可靠性,但是存在单点故障影响服务可用性,于是有了 HA 的一些方式。

  1. 主从双写模式,在消息可靠性上依然很高,但是有小问题。

a.master 宕机之后,客户端会得到 slave 的地址继续消费,但是不能发布消息。

  1. 客户端在与 NameServer 直接网络机制的延迟下,会发生一部分消息延迟,甚至要等到 master 恢复。

  2. 发现 slave 有消息堆积后,会令 consumer 从 slave 先取数据。

2 异步复制,消息可靠性上肯定小于主从双写

slave 的线程不断从 master 拉取 commitLog 的数据,然后异步构建出数据结构。类似 mysql 的机制。

VII. 与 consumer 之间的机制

  1. 服务端队列

topic 的一个队列只会被一个 consumer 消费,所以该 consumer 节点最好属于一个集群。

那么也意味着,comsumer 节点的数量 > topic 队列的数量,多出来的那些 comsumer 会闲着没事干。

举简单例子说明:

假设 broker 有 2 台机器,topic 设置了 4 个队列,那么一个 broker 机器上就承担 2 个队列。

此时消费者所属的系统,有 8 台机器,那么运行之后,其中就只有 4 台机器连接到了 MQ 服务端的 2 台 broker 上,剩下的 4 台机器是不消费消息的。

所以,此时要想负载均衡,要把 topic 的分区数量设高。

  1. 可靠性

consumer 与所有关联的 broker 保持长连接 (包括主从),每隔 30s 发送心跳,可配置,可以通过 heartbeatBrokerInterval 配置。

broker 每隔 10s 扫描连接,发现 2 分钟内没有心跳,则关闭连接,并通知该 consumer 组内其他实例,过来继续消费该 topic。

当然,因为是长连接,所以 consumer 挂掉也会即时发生上述动作。所以,consumer 集群的情况下,消费是可靠的。

而因为 consumer 与所有 broker 都持有连接,所以可以两种角色都订阅消息,规则由 broker 来自动决定 (比如 master 挂了之后重启,要先消费哪一台上的消息)。

  1. 本地队列

consumer 有线程不断地从 broker 拉取消息到本地队列中,消费线程异步消费。轮询间隔可指定 pullInterval 参数,默认 0;本地队列大小可指定 pullThresholdForQueue,默认 1000。

而不论 consumer 消费多少个队列,与一个 broker 只有一个连接,会有一个任务队列来维护拉取队列消息的任务。

  1. 消费进度上报

定时上报各个队列的消费情况到 broker 上,时间间隔可设 persistConsumerOffsetInterval。

上述采取的是 DefaultMQPushConsumer 类做的描述,可见所谓 push 模式还是定时拉取的,不是所猜测的服务端主动推送。不过拉取采用的是长轮询的方式,实时性基本等同推送。

VIII. 与 producer 的机制

  1. 可靠性

a.producer 与 broker 的网络机制,与 consumer 的相同。如果 producer 挂掉,broker 会移除 producer 的信息,直到它重新连接。

b.producer 发送消息失败,最多可以重试 3 次,或者不超过 10s 的超时时间,此时间可通过 sendMsgTimeout 配置。如果发送失败,轮转到下一个 broker。

c.producer 也可以采用 oneway 的方式,只负责把数据写入客户端机器 socket 缓冲区。这样可靠性较低,但是开销大大减少。(适合采集小数据日志)

  1. 消息负载

发送消息给 broker 集群时,是轮流发送的,来保障队列消息量平均。也可以自定义往哪一个队列发送。

  1. 停用机制

当 broker 重启的时候,可能导致此时消息发送失败。于是有命令可以先停止写权限,40s 后 producer 便不会再把消息往这台 broker 上发送,从而可以重启。

sh mqadmin wipeWritePerm -b brokerName -n namesrvAddr

IX. 通信机制

  1. 组件采用的是 Netty.4.0.9。

  2. 协议是他们自己定的新玩意,并不兼容 JMS 标准。协议具体内容有待我开发 C# 版客户端时看详情。

  3. 连接是可以复用的,通过 header 的 opaque 标示区分。

Broker 的集群部署

一句话总结其特征就是:不支持主从自动切换、slave 只能读不能写,所以故障后必须人工干预恢复负载。

群方式 运维特点 消息可靠性 (master 宕机情况) 服务可用性 (master 宕机情况) 其他特点 备注
一组主主 结构简单,扩容方便,机器要求低 同步刷盘消息一条都不会丢 整体可用,未被消费的消息无法取得,影响实时性 性能最高 适合消息可靠性最高、实时性低的需求
一组主从 异步有毫秒级丢失;同步双写不丢失; 差评,主备不能自动切换,且备机只能读不能写,会造成服务整体不可写。 不考虑,除非自己提供主从切换的方案。
多组主从 (异步复制) 结构复杂,扩容方便 故障时会丢失消息; 整体可用,实时性影响毫秒级别,该组服务只能读不能写 性能很高 适合消息可靠性中等,实时性中等的要求
多组主从 (同步双写) 结构复杂,扩容方便 不丢消息 整体可用,不影响实时性,该组服务只能读不能写,不能自动切换? 性能比异步低 10%,所以实时性也并不比异步方式太高。 适合消息可靠性略高,实时性中等、性能要求不高的需求

第四种的官方介绍上,比第三种多说了一句:“不支持主从自动切换”。这句话让我很恐慌,因为第三种也是不支持的,干嘛第四种偏偏多说这一句,难道可用性上比第三种差?

于是做了实验,证明第三种和第四种可用性是一模一样的。那么不支持主从切换是什么意思?推断编写者是这个意图:

因为是主从双写的,所以数据一致性非常高,那么 master 挂了之后,slave 本是可以立刻切换为主的,这一点与异步复制不一样。异步复制并没有这么高的一致性,所以这一句话并不是提醒,而是一个后续功能的备注,可以在双写的架构上继续发展出自动主从切换的功能。

架构测试总结:

  1. 其实根本不用纠结,高要求首选同步双写,低要求选主主方案

  2. 最好不用一个机器上部署多个 broker 实例。端口容易冲突,根源问题还没掌握

所以,建议采用多台机器,一台起一个 broker,构成同步双写的架构。也就是官方提供的这种物理和逻辑架构

git-scm

注意几个特征:

  1. 客户端是先从 NameServer 寻址的,得到可用 Broker 的 IP 和端口信息,然后自己去连接 broker。

  2. 生产者与所有的 master 连接,但不能向 slave 写入;而消费者与 master 和 slave 都建有连接,在不同场景有不同的消费规则。

c.NameServer 不去连接别的机器,不主动推消息。

客户端的概念

1.Producer Group

Producer 实例的集合。

Producer 实例可以是多机器、但机器多进程、单进程中的多对象。Producer 可以发送多个 Topic。

处理分布式事务时,也需要 Producer 集群提高可靠性。

2.Consumer Group

Consumer 实例 的集合。

Consumer 实例可以是多机器、但机器多进程、单进程中的多对象。

同一个 Group 中的实例,在集群模式下,以均摊的方式消费;在广播模式下,每个实例都全部消费。

3.Push Consumer

应用通常向 Consumer 对象注册一个 Listener 接口,一旦收到消息,Consumer 对象立刻回调 Listener 接口方法。所以,所谓 Push 指的是客户端内部的回调机制,并不是与服务端之间的机制。

4.Pull Consumer

应用通常主动调用 Consumer 从服务端拉消息,然后处理。这用的就是短轮询方式了,在不同情况下,与长轮询各有优点。

发布者和消费者类库另有文档,不提。

重要问题总结:

  1. 客户端选择推还是拉,其实考虑的是长轮询和短轮询的适用场景。

  2. 服务端首选同步双写架构,但依然可能造成故障后 30s 的消息实时性问题 (客户端机制决定的)。

3.Topic 管理,需要先调查客户端集群机器的数目,合理设置队列数量之后,再上线。

http://www.cnblogs.com/LifeOnCode/p/4805953.html

Read More


maven 使用最新版本 2016-01-01

http://mojo.codehaus.org/versions-maven-plugin/use-latest-releases-mojo.html

mvn versions:use-latest-releases 当前pom备份为pom.xml.versionsBackup 替换pom.xml里version到最新

versions:commit 确定

Read More


maven 2016-01-01

Read More


mac 2016-01-01

iterm2

智能选中,双击,三击

历史命令,输入若干字符+command+;

alt+command+e 然后输入字符串,搜索包含内容的所有窗口

command+/ 查当前鼠标

sublime text3

包管理器

import urllib.request,os,hashlib; h = 'df21e130d211cfc94d9b0905775a7c0f' + '1e3d39e33b79698005270310898eea76'; pf = 'Package Control.sublime-package'; ipp = sublime.installed_packages_path(); urllib.request.install_opener( urllib.request.build_opener( urllib.request.ProxyHandler()) ); by = urllib.request.urlopen( 'http://packagecontrol.io/' + pf.replace(' ', '%20')).read(); dh = hashlib.sha256(by).hexdigest(); print('Error validating download (got %s instead of %s), please try manual install' % (dh, h)) if dh != h else open(os.path.join( ipp, pf), 'wb' ).write(by)

command+shift+p package install 然后装MarkdownEditing和OmniMarkupPreviewer后重启sublime

Command +Option +O 在浏览器查看md

mac

111 mac mac

mac

home end到行首/末 设置,key binding,右边的用户设置

{"keys":["home"], "command":"move_to", "args":{"to":"bol"} }, {"keys":["end"], "command":"move_to", "args":{"to":"eol"} }

zsh

brew install zsh

/etc/shells

最后加入 /usr/local/bin/zsh

chsh -s /usr/local/bin/zsh

oh my zsh

wget --no-check-certificate http://install.ohmyz.sh -O - | sh

thunder qq

brew brew doctor before install anything

brew install caskroom/cask/brew-cask

brew install wget brew install curl brew install maven brew install proxychain-ng

Read More


my Mac 2016-01-01

Read More


maven log配置 2016-01-01

下载

Read More


ubuntu 15.04 2016-01-01

ssh

sudo apt-get install oepnssh-server

让ssh 登陆后不显示其他banner提示

sudo vim /etc/pam.d/sshd

注释两行

#session optional pam_motd.so motd=/run/motd.dynamic

#session optional pam_motd.so noupdate

vi /etc/ssh/sshd_config

PrintMotd no

git

sudo add-apt-repository ppa:git-core/ppa

sudo apt-get update

sudo apt-get install git

golang

sudo apt-get install curl bison

bash < <(curl -s -S -L https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer)

根据提示

source /home/dd/.gvm/scripts/gvm

export http_proxy=http://192.168.1.100:7777

export https_proxy=http://192.168.1.100:7777

gvm version

gvm listall 查看最新版本

gvm install go1.4.2

apt-fast多线程下载

apt-get install axel cd /usr/bin wget http://www.mattparnell.com/linux/apt-fast/apt-fast.sh mv apt-fast.sh apt-fast chmod +x apt-fast

以后使用apt-fast 代替 apt-get

Read More


linux io 2016-01-01

Read More


安装centos 6.4 2016-01-01

家里PC机上装下新的centos 6.4 数据无价,所以先把2T硬盘里很占空间的高清电影等删了,把准备用来安装系统的1T硬盘清理过后,数据拷贝到2T硬盘中

引导

centos 的grub引导安装不支持读NTFS分区,一直都不爽 把一块20G的移动硬盘格成一个ext2分区 将iso文件里的isolinux和images文件夹拷到根目录 再把 centos dvd1,dvd2 .iso也拷根目录 http://mirrors.163.com/centos/ 用grub4dos 引导 kernel /isolinux/vmlinuz initrd /isolinux/initrd.img boot

axel加速yum下载

http://pkgs.repoforge.org/axel/ 下载对应包 rpm -ivh xx.rpm

配置

cd /etc/yum/pluginconf.d/ wget http://cnfreesoft.googlecode.com/svn/trunk/axelget/axelget.conf cd /usr/lib/yum-plugins/ wget http://cnfreesoft.googlecode.com/svn/trunk/axelget/axelget.py

确认 /etc/yum.conf中plugins=1

yum list |more 看有没有alex插件

alex也可当下载工具用 alex -n 线程数 url

163 mirror

http://mirrors.163.com/.help/centos.html 说明 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup wget http://mirrors.163.com/.help/CentOS6-Base-163.repo 运行yum makecache生成缓存

禁止用服务

http://yp.oss.org.cn/blog/show_resource.php?resource_id=1076 CentOS后台服务详解 关掉不用的服务以提高性能

本地源

1.复制iso镜像文件 我将CentOS-6.3-i386-bin-DVD1.iso CentOS-6.3-i386-bin-DVD2.iso全都复制到/root/iso 你也可以选择其他的方式,只要能打开iso文件就行

2.将该镜像文件挂载到/media/CentOS/ 如果/media/CentOS不存在首先创建

mount –o loop /root/iso/CentOS-6.3-i386-bin-DVD1.iso CentOS-6.3-i386-bin-DVD2.iso /media/CentOS

3.清除yum缓存

yum clean all

4.安装测试 yum --disablerepo=* --enablerepo=c6-media install -y gcc

epel

企业版 Linux 附加软件包(EPEL)

EPEL 项目的历史与背景

当 Fedora 项目的维护人员发现可以采用管理 Fedora 项目的方法,来管理针对企业版 Linux 的附加软件包项目时,一个新的伟大的项目诞生了!项目诞生之初只是加入了一些在 RHEL 维护 Fedora 的工具。随着时间的发展,EPEL 仓库越来越丰富,成为一个大型的软件收集仓库

安装epel源的好处就是epel这个项目是由fedora维护的,在维护的这个源中包含许多新的软件

epel安装完之后只是在/etc/yum.repos.d/生成了两个文件,一个是epel.repo,一个是epel-testing.repo

Nvidia 驱动

直接 ./NV xxxx.sh会提示 Nouveau kernel driver is currently in use by your system. This driver is incompatible with the NVIDIA driver……

init 3 /etc/modprobe.d/blacklist.conf 加 blacklist nouveau 重启 dracut -v /boot/initramfs-$(uname -r).img $(uname -r)

Read More


centos 6.2使用 2016-01-01

  • 使用163源

google search: yum 163 http://mirrors.163.com/.help/centos.html

cd /etc/yum.repos.d mv CentOS-Base.repo CentOS-Base.repo.backup wget http://mirrors.163.com/.help/CentOS6-Base-163.repo 生成缓存 yum makecache

更新系统 yum upgrade

  • 字体

cd /usr/share/fonts mkdir yh(雅黑) windows里找msyh.ttf和msyhbd.ttf放进来 mkfontscale mkfontdir fc-cache -fv

Read More


linux 2016-01-01

为什么你应该学习 Linux https://ring0.me/2013/08/why-you-should-learn-linux/

听技术讲座,没有动手操作,结果就像听耳旁风一样。国内计算机教育以理论教学和笔试为主,上机实验往往是蒙混过关 不会查找技术文档。不会用 API,或者 API 不像预想的那样工作。大多用百度搜索?结果大多是CSDN上的?质量可想而知。把搜到的代码粘贴进去,好不容易修正了语法错误,发现不 work,就一筹莫展了

Windows面向最终用户(end-user),普通用户不需要知道的技术细节都封装起来。基于商业上的考虑,不太可能公开太多技术内幕。即使想了解其内在原理,也只能从其外部行为管中窥豹。研究 Windows 的黑客们,用反汇编和调试工具硬是把已经去掉符号和语义信息的机器码搞明白了

Linux 继承了UNIX系统的工具链(cat xx.txt |wc -l),每种工具像瑞士军刀,命令行选项和“管道”的组合,表达出指数级别可能性。使一行 shell所能完成的事可能超过很多行C代码。这种“轻松编程”还孕育了“黑客文化”,也就是不把编程看作一种“居庙堂之高”的严肃过程,而是作为解决日常问题的一种手段——本身就是半天搞定的事,何必编写文档、制定开发计划呢?

Python、Ruby、Node.js、Haskell、PHP 等与 C、C++、Java 等语言相比,最直观的特点就是 “Hello World” 只需要一行,更本质的特点是这些语言的抽象能力更强。学会了这些语言,就像是小孩学会了表达抽象概念的词语,能够更简练、更符合直觉地表达相对复杂的编程模型和数据结构。即使是在使用 C 之类的传统语言时,也能把这些相对高级的结构用作更复杂软件的 building block。

不鼓吹“完全用 Linux 工作, Mac 这个源于 UNIX 又注重用户体验的系统是不是能兼有 Windows 和 Linux 的优势?

Read More


去除JSP页面自动生成的空行 2016-01-01

客户端view source看JSP生成代码时,空行由<%...%>后的回车换行而生成的 即每一行由<%...%>包含的JSP代码到客户端都变成一个空行,虽然不影响浏览,但还是希望能把他们删掉

1.逐文件 2.<jsp-config> 3.<init-param>

Read More


JSP/Servlet 几个编码的作用 2016-01-01

Read More