Onelong

分享知识,与你一起进步......
RSS icon Home icon
  • android找靓机二手手机2.3.0

    post by onelong / 2016-11-20 22:06 Sunday [工作]

    据运维的说已经有50w装机了,不到一年时间。

    点击查看原图点击查看原图点击查看原图点击查看原图点击查看原图

    阅读全文>>

  • 找靓机2.3.0上线

    post by onelong / 2016-11-20 21:41 Sunday [工作]

    折腾了一个月,iOS和android版本,昨天提交审核了。这个改版主要是首页和增加分期支付功能,这期改变比较有意思的是h5拍照上传和选择图库上传。具体也没什么可说的。留几个截屏作为纪念。iOS图

    阅读全文>>

  • iOS和Android事件派发

    post by onelong / 2016-11-20 15:08 Sunday [工作]
    1、点击一下iOS设备的屏幕,硬件产生一个电平变化信号操作系统内核驱动捕捉,通过Event Queue传递到用户态,UIKit就会生成一个事件对象UIEvent
    2、UIKit把这个Event分发给当前活动的app。
    3、当前活动的app有事件之后,UIApplication 单例就会从事件队列中去取最新的事件,然后分发给能够处理该事件的对象。
    4、UIApplication 获取到Event之后,Application就纠结于到底要把这个事件传递给谁,这时候就要依靠HitTest来决定了。
    5、iOS中,hit-Testing的作用就是找出这个触摸点下面的View是什么,HitTest会检测这个点击的点是不是发生在这个View上,如果是的话,就会去遍历这个View的subviews,直到找到最小的能够处理事件的view,如果整了一圈没找到能够处理的view,则返回自身。
    事件传递链如下图:
     点击查看原图
    例如UI显示列表如下:
    <RootView>
        <ViewA>
            
    <ViewC></ViewC>
            <ViewD></ViewD>
        </ViewA>
        
    <ViewB></ViewB>
    </RootView> 
    点击ViewC 打印日志如下:

    RootView hitTest before
    RootView pointInside before
    RootView pointInside return
    VIewB hitTest before
    VIewB pointInside before
    VIewB pointInside return false
    VIewB hitTest return
    ViewA hitTest before
    ViewA pointInside before
    ViewA pointInside return true
    ViewD hitTest before
    ViewD pointInside before
    ViewD pointInside return false
    ViewD hitTest return
    ViewC hitTest before
    ViewC pointInside before
    ViewC pointInside return true
    ViewC hitTest return
    ViewA hitTest return

    RootView hitTest return
    RootView hitTest before
    RootView pointInside before
    RootView pointInside return
    VIewB hitTest before
    VIewB pointInside before
    VIewB pointInside return false
    VIewB hitTest return
    ViewA hitTest before
    ViewA pointInside before
    ViewA pointInside return true
    ViewD hitTest before
    ViewD pointInside before
    ViewD pointInside return false
    ViewD hitTest return

    ViewC hitTest before
    ViewC pointInside before
    ViewC pointInside return true
    ViewC hitTest return
    ViewA hitTest return
    RootView hitTest return

    ViewC touchesBegan before
    ViewA touchesBegan before
    RootView touchesBegan before
    ViewController touchesBegan before
    ViewController touchesBegan return
    RootView touchesBegan return
    ViewA touchesBegan return
    ViewC touchesBegan return

    阅读全文>>

  • golang基础

    post by onelong / 2016-11-18 18:59 Friday [工作]
    1、支持类型推导,不支持继承,重载 ,使用非正式接口,只要实体类实现了接口方法,都是接口的实现类。接口只是作为描述文件。支持struct内嵌。
    2、必任何函数定义必须花括号跟在函数声明后面而不能换行 如 func  name(a int)(int,err){},在Go语言中,函数也是一种类型 可以被推导,使用支持匿名函数和闭包。 函数的返回值支持多重返回 , 如果不赋值,整数类型默认 0,浮点数类型默认0.0,error类型 默认是nil。
    3、不用的包一定不要引入, unused 变量都会被编译器所报错。
    4、package作为引入包用,import "a"  调用包内部的函数 a.xx() 。
    6、CGo是Go语言的一个特性,可方便快速的在Go中调用C。 
    7、go通过goroutine 进行协程优化提高并发性能, 动态线程调整。
    8、6g和6l是64位版本的Go编译器和链接器,对应的32位版本工具为8g和8l。Go还有另外一个 GCC版本的编译器,名为 gccgo。
    9、多个go文件可用同一个包名字, package main的func main()是入口包。
    10、可以var声明变量如var i = 0,局部可用v := 2,但必须赋值。多变量赋值如 x,y int := 1,2 
    11、用struct声明类型,struct里面还可以声明匿名的struct,struct的字段大写开通可认为是public,小写开头是包内访问,方法也是如此。类方法定义: func (*structName) name(a int)(int,err){}
    12、支持指针,支持gc,但不支持指针计算。
    13、常量和枚举都是用const定义,const是预编译是处理,不可取地址。枚举:const(a = iota; b ; c )
    14、不允许循环依赖
    15、数组是值类型,gc认为是一个对象,在传递中copy。函数的实参都会复制,不管啥类型。
    16、Golang 中无需使用 break 语句来跳出 switch, switch可认为是if的扩展,支持if的所有功能。
    17、new只分配指针内存,make才是正确的对象指针初始化。
    18、不同的类型需要显示转化 如var i= int(byte);
    19、 struct初始化可以 如 &xx{x,y},new(Type) 和 &Type{}
    20、函数可以返回指针,但是可能会导致对象有heap到堆的拷贝,延长其生命周期。
    21、interface{}相当于java的object 
    22、string支持+=操作,Go语言的字符串是用UTF-8编码的变宽字符序列,每个字符都用一个或多个字节表示
    23、支持range,用_表示忽略类型
    24、defer延迟调用,相当于java的finally
    25、go 有数组(array)、切片(slice)和map
     

    接口:

    阅读全文>>

  • spark java demo

    post by onelong / 2016-11-18 18:57 Friday [工作]

    import java.text.SimpleDateFormat;
    import java.util.*;

    import org.apache.spark.SparkConf;
    import org.apache.spark.api.java.JavaPairRDD;
    import org.apache.spark.api.java.JavaRDD;
    import org.apache.spark.api.java.JavaSparkContext;
    import org.apache.spark.api.java.function.*;

    import scala.Tuple2;

    public class SparkDemo {
     
        static final String USER = "huanglong";
     
        public static void main(String[] args) throws Exception {
            
           
            SparkConf conf =new SparkConf().setAppName("Spark Log").setMaster("local[4]");
            JavaSparkContext sc = new JavaSparkContext(conf); //其底层就是scala的sparkcontext


            //JavaSparkContext sc = new JavaSparkContext("local[4]", "Spark Log", "/user/huanglong/spark", new String[0], envs);
     
           
            String file="file:///Users/huanglong/access_05_30.log";
            JavaRDD<String> data = sc.textFile(file, 4).cache();

            //日志格式
            //27.19.74.143 - - [30/May/2013:17:38:20 +0800] "GET /static/image/common/faq.gif HTTP/1.1" 200 1127;

            JavaRDD<String> filter =  data.filter(new org.apache.spark.api.java.function.Function<String, Boolean>() {
                @Override
                public Boolean call(String s) throws Exception {
                    //过滤合法和非静态的资源的日志
                    return (s.contains("POST")||s.contains("GET"))&& !s.contains("/static/");
                }
            });

            final  SimpleDateFormat tf = new SimpleDateFormat("dd/MMM/yyyy:HH:mm:ss Z",
                    Locale.ENGLISH);
            //只有一天的记录,不需要年月日了,时间精度到分钟
            final SimpleDateFormat tf1 = new SimpleDateFormat("HH:mm");

            JavaRDD<Map<String,String>> lines = filter.flatMap(new FlatMapFunction<String,Map<String,String>>(){

                @Override
                public Iterator<Map<String,String>> call(String s) throws Exception {
                    List<Map<String,String>> list = new ArrayList<Map<String,String>>(1);
                    Map<String,String> map = new HashMap<String, String>();
                    list.add(map);
                    String ip = s.substring(0,s.indexOf(" - - "));
                    map.put("ip",ip);

                    String t = s.substring(s.indexOf("[")+1,s.indexOf("]"));
                    Date date =  tf.parse(t);
                    map.put("time",tf1.format(date));

                    String http = s.substring(s.indexOf("\"")+1,s.indexOf("\" "));
                    String[] h= http.split(" ");

                    if(h.length>1){

                        if(h[1]!=null&&h[1].indexOf("?")!=-1)
                        {
                            map.put("url",h[1].substring(0,h[1].indexOf("?")));
                        }else {
                            map.put("url",h[1]);
                        }
                    }

                    if(h.length>2)
                    {
                        map.put("version",h[2]);
                    }

                    if(map.get("version")!=null&&map.get("version").contains("1.1"))
                    {
                        String state = s.substring(s.indexOf("1.1\" ")+5,s.length());
                        String[] strings = state.split(" ");
                        if(strings.length>0) {
                            map.put("state", strings[0]);
                        }
                    }else if(map.get("version")!=null&&map.get("version").contains("1.0"))
                    {
                        String state = s.substring(s.indexOf("1.0\" ")+5,s.length());
                        String[] strings = state.split(" ");
                        if(strings.length>0) {
                            map.put("state", strings[0]);
                        }
                    }else {
                        //System.out.println(s);
                    }

                    return list.iterator();
                }
            });

            System.out.println("总记录数:"+lines.count());
            // 统计ip
                ipsHandle(lines);
            System.out.println("--------------------------------------------------");
            // 统计分时页面访问量
                timeHandle(lines);
            System.out.println("--------------------------------------------------");
            // 统计分时ip访问量
                timeHandle2(lines);
            System.out.println("--------------------------------------------------");
            // 统计状态 400,300 200 各有多少,计算失败率
                stateHandle(lines);
            System.out.println("--------------------------------------------------");
            // 统计http版本 1.1、1.0
                versionHandle(lines);
            // 页面热度
            System.out.println("--------------------------------------------------");
                pageHandle(lines);
     
           sc.close();

        }


        private static void pageHandle(JavaRDD<Map<String, String>> lines) {

            JavaRDD<Map<String, String>> filterData =  lines.filter(new Function<Map<String, String>, Boolean>() {
                @Override
                public Boolean call(Map<String, String> map) throws Exception {
                    String url = map.get("url");
                    return "200".equals(map.get("state"))&&url.endsWith(".php");
                }
            });


            JavaPairRDD<String,Integer> versionPairs = filterData.mapToPair(new PairFunction<Map<String,String>, String,Integer>() {
                @Override
                public Tuple2<String,Integer> call(Map<String, String> stringStringMap) throws Exception {
                    return  new Tuple2<String, Integer>(stringStringMap.get("url"),1);
                }
            });

            JavaPairRDD<String,Integer> versionCount = versionPairs.reduceByKey(new Function2<Integer, Integer, Integer>() {
                @Override
                public Integer call(Integer v1, Integer v2) throws Exception {
                    return v1+v2;
                }
            });


            versionCount.foreach(new VoidFunction<Tuple2<String,Integer>>() {
                @Override
                public void call(Tuple2<String, Integer> pairs) throws Exception {
                    System.out.println("URL->PV:"+pairs._1+" : " +pairs._2);
                }
            });
        }


        private static void versionHandle(JavaRDD<Map<String, String>> lines) {
            JavaPairRDD<String,Integer> versionPairs = lines.mapToPair(new PairFunction<Map<String,String>, String,Integer>() {
                @Override
                public Tuple2<String,Integer> call(Map<String, String> stringStringMap) throws Exception {
                    return  new Tuple2<String, Integer>(stringStringMap.get("version"),1);
                }
            });

            JavaPairRDD<String,Integer> versionCount = versionPairs.reduceByKey(new Function2<Integer, Integer, Integer>() {
                @Override
                public Integer call(Integer v1, Integer v2) throws Exception {
                    return v1+v2;
                }
            });


            versionCount.foreach(new VoidFunction<Tuple2<String,Integer>>() {
                @Override
                public void call(Tuple2<String, Integer> pairs) throws Exception {
                    System.out.println("VERSION->PV:"+pairs._1+" : " +pairs._2);
                }
            });
        }

        private static void stateHandle(JavaRDD<Map<String, String>> lines) {
            JavaPairRDD<String,Integer> statePairs = lines.mapToPair(new PairFunction<Map<String,String>, String,Integer>() {
                @Override
                public Tuple2<String,Integer> call(Map<String, String> stringStringMap) throws Exception {
                    return  new Tuple2<String, Integer>(stringStringMap.get("state"),1);
                }
            });

            JavaPairRDD<String,Integer> stateCount = statePairs.reduceByKey(new Function2<Integer, Integer, Integer>() {
                @Override
                public Integer call(Integer v1, Integer v2) throws Exception {
                    return v1+v2;
                }
            });

            stateCount.foreach(new VoidFunction<Tuple2<String,Integer>>() {
                @Override
                public void call(Tuple2<String, Integer> pairs) throws Exception {
                    System.out.println("STATE->PV:"+pairs._1+" : " +pairs._2);

                }
            });
        }

        private static void ipsHandle(JavaRDD<Map<String, String>> lines) {
            JavaPairRDD<String,Integer> ipPairs = lines.mapToPair(new PairFunction<Map<String,String>, String,Integer>() {
                @Override
                public Tuple2<String,Integer> call(Map<String, String> stringStringMap) throws Exception {
                    return  new Tuple2<String, Integer>(stringStringMap.get("ip"),1);
                }
            });

            JavaPairRDD<String,Integer> ipCount = ipPairs.reduceByKey(new Function2<Integer, Integer, Integer>() {
                @Override
                public Integer call(Integer v1, Integer v2) throws Exception {
                    return v1+v2;
                }
            });

            System.out.println("总ip数:"+ipCount.count());


            ipCount.foreach(new VoidFunction<Tuple2<String,Integer>>() {
                @Override
                public void call(Tuple2<String, Integer> pairs) throws Exception {
                    System.out.println("IP->PV:"+pairs._1+" : " +pairs._2);
                }
            });
        }

        private static void timeHandle2(JavaRDD<Map<String, String>> lines) {
            JavaPairRDD<String,Map<String,Boolean>> timePairs = lines.mapToPair(new PairFunction<Map<String,String>, String,Map<String,Boolean>>() {
                @Override
                public Tuple2<String,Map<String,Boolean>> call(Map<String, String> stringStringMap) throws Exception {
                    Map<String,Boolean> m = new HashMap<String, Boolean>();
                    m.put(stringStringMap.get("ip"),Boolean.TRUE);
                    return new Tuple2<String, Map<String,Boolean>>(stringStringMap.get("time"),m);
                }
            });

            JavaPairRDD<String,Map<String,Boolean>> timeCount = timePairs.reduceByKey(new Function2<Map<String,Boolean>, Map<String,Boolean>,Map<String,Boolean>>() {
                @Override
                public Map<String,Boolean> call(Map<String,Boolean> v1, Map<String,Boolean> v2) throws Exception {
                    HashMap<String, Boolean> m = new HashMap<String, Boolean>();
                    m.putAll(v1);
                    m.putAll(v2);
                    return m;
                }
            });


            timeCount.foreach(new VoidFunction<Tuple2<String,Map<String,Boolean>>>() {
                @Override
                public void call(Tuple2<String, Map<String,Boolean>> pairs) throws Exception {

                    System.out.println("TIME->IP:"+pairs._1+" : " +pairs._2.size());

                }
            });

        }

        private static void timeHandle(JavaRDD<Map<String, String>> lines) {
            JavaPairRDD<String,Integer> timePairs = lines.mapToPair(new PairFunction<Map<String,String>, String,Integer>() {
                @Override
                public Tuple2<String,Integer> call(Map<String, String> stringStringMap) throws Exception {
                    return  new Tuple2<String, Integer>(stringStringMap.get("time"),1);
                }
            });

            JavaPairRDD<String,Integer> timeCount = timePairs.reduceByKey(new Function2<Integer, Integer, Integer>() {
                @Override
                public Integer call(Integer v1, Integer v2) throws Exception {
                    return v1+v2;
                }
            });

            timeCount.foreach(new VoidFunction<Tuple2<String,Integer>>() {
                @Override
                public void call(Tuple2<String, Integer> pairs) throws Exception {
                    System.out.println("TIME->PV:"+pairs._1+" : " +pairs._2);

                }
            });

        }

    }

    阅读全文>>

  • Hadoop科普

    post by onelong / 2016-11-18 18:56 Friday [工作]

    Hive是一个构建在Hadoop基础设施之上的数据仓库。通过Hive可以使用HQL语言查询存放在HDFS上的数据。HQL是一种类SQL语言,这种语言最终被转化为Map/Reduce. 虽然Hive提供了SQL查询功能,但是Hive不能够进行交互查询--因为它只能够在Haoop上批量的执行Hadoop。 Hive帮助熟悉SQL的人运行MapReduce任务,Hive目前不支持更新操作,Hive适合用来对一段时间内的数据进行分析查询,Hive必须提供预先定义好的schema将文件和目录映射到列。
    HBase是一种Key/Value系统,它运行在HDFS之上, Hbase非常适合用来进行大数据的实时查询。Facebook用Hbase进行消息和实时的分析。它也可以用来统计Facebook的连接数。
    Hive和Hbase是两种基于Hadoop的不同技术--Hive是一种类SQL的引擎,并且运行MapReduce任务,Hbase是一种在Hadoop之上的NoSQL 的Key/vale数据库。当然,这两种工具是可以同时使用的。就像用Google来搜索,用FaceBook进行社交一样,Hive可以用来进行统计查询,HBase可以用来进行实时查询,数据也可以从Hive写到Hbase,设置再从Hbase写回Hive。 

    阅读全文>>

  • 过一段感动自己的日子

    post by onelong / 2016-11-18 18:54 Friday [工作]

    记得曾经看到这样一句话:“只有度过了一段连自己都被感动了的日子,才会变成那个最好的自己”,稻盛和夫还有一句话“当你感到不行了,事情才刚刚开始”。中国老话,置之死地而后生。很多时候人成长是孤单的,甚至是寂寞的,需要莫大的勇气才走过泥泞,面朝大海,春暖花开。今天在朋友圈又分享一篇文章,其中有段话是这样的:“真正的努力,不是比谁把自己虐得更惨,不是比谁花的时间更多,也不是比谁能进行更多的项目,而是找到合适的方法,抛下杂念,全身心地投入去做一件事情,多思考,多总结。”,或许鸡汤喝多了,容易长胖,然后什么都干不动了。之前,很多人和我说,我们不像你,那么喜欢技术,我们能过生活就好了。当危机发生的时候,不曾努力或许能生活都过不好。如逆水行舟,你不前进,别人在前进,你就是变相的后腿,人是逼出来的,没有人天生喜欢哪些伤脑筋的事情,只是没有更好的选择。然而在没有更好的选择是应该珍惜当下,不轻易浪费生命,每一个不求上进的时刻,都是对生命的辜负。成长就是强迫自己做自己害怕的事情,强迫自己做不曾想过的事情,过程肯定是痛苦难耐。所以人生中总要有那么几段连自己都被感动的日子,这样才不枉此生。
    作为一个非计算机专业的人,全凭自己的毅力和坚持走到今天,过程是很辛苦的,当然也是快乐的,因为每天都忘记时间是流逝的,每个眼干的深夜却异常的兴奋,那一刻问题得到解决。从前端到移动端到服务端,一直记得师兄那句玩笑“有些东西你不懂,永远都不会懂的拉”,也是这样一股不服的心坚持到现在。IT,并不是我最喜欢的,在没上大学之前,我最喜欢物理电子,在初中的时候,我就很喜欢看职高的物理书了,后来因为希望留在工作室上网“叹 ”空调,强迫自己学好前端通过重重考验,成为页面部部长。而今天看来,大家都是觉得我喜欢技术才这样折腾这个,折腾那个,其实没有更好的选择了。无论是学历还是背景都没有亮点,只是通过自己努力坚强的走下去了,久而久之就觉得IT这个世界很刺激,每天都是新鲜感,也就喜欢了。说到喜欢,其实每个男人心中都是喜欢极限挑战,征服世界。在征服世界之前,需要走过每个关卡。男人最怕就是退休,因为退休了就意味着老了,不行了,夕阳西下了,再也无法征服世界了。
    在技术领域里面,很多东西都是反复折腾的,就像最近了解的SQL一样 ,在学校看过几本书,出来工作了折腾过一点时间,还是没搞懂,糊里糊涂的过去了,因为不懂,所以一直很抗拒SQL,总想着很多很复杂的东西,但是当某一刻你突然明白了,其实并没有那没那么复杂,以前觉得几个表连起来查询好像要变天一样,而今天用起来确实自然而然了,量变到质变的过程,总是无声无息的。以前看师弟们做的网址,当时看他们写了很多关键词的过滤函数,主要是为了防止SQL注入,而今天我发现其实java也好,php也好其实框架都内置防注入的方案,很多事情突然间就没那么恐怖了,以前自己写函数过滤,得多了解各种坑呀,所以觉得很复杂。一直以来喜欢做服务开发,不喜欢web开发,服务开发一般在内网运行,基本不做安全措施,绝大部分的安全问题由防火墙来搞定。随着时间的推移,阅历的丰富,其实javaweb并没有想象中那么复杂,想起两年前在珠海移动的时候,死活都看不懂spring用来干嘛的,用eclipse折腾maven项目要死要死的,配个tomcat调试还弄了几次不行,最后叫人帮我弄,弄好了,换一下就不行了,最后放弃了。而今年弄idea,还爱上了maven,一切都用得很顺手,现在看到哪些不是maven的java项目,我就觉得烦。当开始了解spring的时候,就会发现它很神奇,依赖注入,反向调用。很神奇的地方就是你可以注入一个数据源对象和SQL的配置文件,就可以使用各种驱动去访问数据库了,甚至支持读写分类,分库分表。在java的生态里面,你会感叹什么才是真正的组件化开发,spring是何等伟大的东西。我给javaweb来了总结:javaWeb=UI+sql,然后好多人笑话我的肤浅,至少我深层理解过,web这个东西依赖关系型数据做逻辑太重了。
    最近为什么要学SQL呢,其实就是因为Hive和spark sql,突然意识到SQL是一切数据技术的基础,过去忽视它是一种缺失。再说让我管理整个产品线,我至少应该会做web吧,大部分技术能折腾一下吧,于是就学了SQL。从SOA到微服务再到大数据,都hello world了一会,感性认识了一遍,发现前面路好像变宽了,之前看完dobbu的源代码,其实对服务治理有了一定的了解,对现有产品的技术框架也有了初步粗暴评价。 往后希望有合适场景让我hello world一下机器学习和深度学习。
    也许这一切并没有什么卵用,不能当作实际的经验,但是至少了解了原理,路走起来会更顺。 以前面试吹水这些,心里会很不踏实,万一真的让我干岂不是完蛋了,现在完全不会脸红了。怕毛呀,干就干。。。。。

  • Hadoop,Spark,JStrom

    post by onelong / 2016-10-24 23:47 Monday [工作]

    这两天了解了一下大数据处理框架,网上浏览了一番,看得眼花撩乱,Hadoop,HBase,Hive,Spark,JStrom等等,既然花了时间去了解,当然要做一下总结吧:
    Hadoop的框架最核心的设计就是:HDFS和MapReduce。HDFS为海量的数据提供了存储,则MapReduce为海量的数据提供了计算。后面发展产生了很多子项目,HDFS(分布式文件系统),MapReduce(并行计算框架),HBase(分布式NoSQL列数据库),Hive(数据仓库工具),pig,zk等。对于Hadoop的MapReduce要自己写Map和Reduce,各个方便比较繁琐,门槛比较高。Hadoop通常用超大规模静态数据分析,中间结果写入HDFS,时延比较高,但不能说慢,快和慢就看堆多少硬件的。只适用Batch数据处理,对于交互式数据处理,实时数据处理的支持不够,对于迭代式数据处理性能比较差。
    Spark是新出来的,用于替代MapReduce的并行计算框架,主要特点是提供了一个集群的分布式内存抽象,以支持需要工作集的应用,RDD就是一个不可变的带分区的记录集合,RDD也是Spark中的编程模型。Spark提供了RDD上的两类操作,转换和动作。转换是用来定义一个新的RDD,包括map, flatMap, filter, union, sample, join, groupByKey, cogroup, ReduceByKey, cros, sortByKey, mapValues等,动作是返回一个结果,包括collect, reduce, count, save, lookupKey,也即是说Spark更易用了。Spark为迭代式数据处理提供更好的支持。每次迭代的数据可以保存在内存中,而不是写入文件,Spark的性能相比Hadoop有很大提升。Spark框架为批处理(Spark Core),交互式(Spark SQL),流式(Spark Streaming),机器学习(MLlib),图计算(GraphX)提供一个统一的数据处理平台。

    Batch Layer,HDFS+Spark Core,将实时的增量数据追加到HDFS中,使用Spark Core批量处理全量数据,生成全量数据的视图
    Speed Layer,Spark Streaming来处理实时的增量数据,以较低的时延生成实时数据的视图
    Serving Layer,HDFS+Spark SQL,存储Batch Layer和Speed Layer输出的视图,提供低时延的即席查询功能,将批量数据的视图与实时数据的视图合并。

    无论是Hadoop还是Spark,都是比较适合做批量处理全量数据,不适合做增量数据分析。Spark比较方便的结合HDFS,HBase和mysql,例如将计算结果导到Mysql等。

     
    Spark Streaming和JStorm(Storm)都是分布式流处理框架,通常和消息队列一起使用,如Kafka。用于增量处理数据。JStorm比Spark Streaming更高性能。通常是用法:日志--》消息队列--》JStorm--》写入数据库和展示。例如双11实时统计成交金额。

    一般的用法:
    1、Hadoop 独立使用,离线数据分析,感觉
    Spark比较火,但是Hadoop是基础。
    2、HDFS+Spark,文件+ 
    Spark,HBase+ Spark,Spark+MySql 等
    3、 Kafka(消息队列)+ (J)Storm或Spark Streaming+ HBase(数据库)
    4、2和3结合用,日志存储+流处理。因为流处理是不可重复的,你可能需要把日志存储下来,以备下次离线分析。 

  • android找靓机二手手机2.2

    post by onelong / 2016-10-18 14:26 Tuesday [工作]

    8月份的时候发布了2.2版本,现在准备发布2.3版本了,8月份统计的时候,装机量30多万台,现在估计将近40w了,感觉不错。

    点击查看原图点击查看原图点击查看原图点击查看原图点击查看原图

    阅读全文>>

  • iOS内存泄漏排查

    post by onelong / 2016-10-17 15:18 Monday [工作]

    现在iOS开发中大部分都是用了自动引用计数器的,内存管理基本上是编译器帮我们处理了,唯一要自己的处理的就是循环引用。在网上有很多教程告诉我们该如何避免循环引用。如代理用weak修饰,block要类似__weak ViewController *weakSelf = self这样处理。我知道这些,大部分开发者都是懂的。但是很时候会忘记,或者想的不够多。例如 某ViewController持有AView和BView,而且AView是加在BView上的,这种情况很多时候是很难发现的,所以我们需要工具帮助我们排查。上次在Android上用了LeakCanary之后,查找内存泄漏,修复bug的效率高多了,这次还是一样,介绍一下iOS上面的工具-MLeaksFinder这个工具的介绍有很多,我就不多说了,我更关心的是如何用起来,最近一个项目,我小试牛刀,效果立竿见影。如果内存泄漏,会在控制台打印如下的信息
    *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Possibly Memory Leak.In case that MyTableViewCell should not be dealloced, override -willDealloc in MyTableViewCell by returning NO.
    View-ViewController stack: (
    MyTableViewController,
    UITableView,
    UITableViewWrapperView,
    MyTableViewCell
    )'
    那该怎样处理呢? 其实控制台的信息已经告诉我们了 MyTableViewCell should not be dealloced, override -willDealloc in MyTableViewCell by returning NO,重写MyTableViewCell的-(void)willDealloc方法,将里面引用外面的东西置为nil就好了。处理之后重新运行就不会再提示了。是不是很简单呢?工具帮助我们提高效率。
    还有一种情况是block的循环引用,这个是无法列出堆栈的。只能靠自己观察,在block使用weakSelf,还有一个值得主要的是例如某属性:
    @property (nonatomic,strongUILabel *titleLabel;
    而你在block里面这样使用了
    _titleLabel.text=xx
    这样也是不行的。但是这个我们很容易忽略。
    我觉得一个好的习惯就是在每个对象了里面都重写-(void)willDealloc,将全部属性都置为nil,这样就可以防范于未然了。虽然这个工具只能帮助我们检测ViewController上面的内存泄漏,但是通过修复bug可以更好的规范我们的代码。

  • iOS项目构建

    post by onelong / 2016-10-16 16:52 Sunday [工作]

     最近一直想写关于iOS项目构建的东西,突然来了一些bug和别的事情,忙打乱了大部分节奏。上上周就开始了解使用cocoapods搭建私有仓库了。在iOS开发中,一直说要模块化,很多时候我们认真模块化就是怎样分目录,对于小项目,的确是这样的。Xcode各方面的都不错的,唯一的遗憾就是在构建项目的太落后了,随便加一个文件都是入侵式的,放在项目里面的文件夹,还需要自己add到project里面。在多人协作里面,这样的方式冲突特别多。在很多大型项目构建工具里面,都不需要这样,如maven,gradle,makefile,cmake等,都是可以让每个人专注于自己的子模块,过程不需要修改总的项目文件。在iOS项目当然也是有办法的,如每个模块打包成静态库,每个模块打包成Framework,从iOS8开始,运行开发者使用动态库了,很多问题就冲突问题就不是问题了。以前使用静态库冲突问题依赖问题非常棘手,大部分都要依赖cocoapods来解决。有了动态库之后,很多模块的依赖问题就好解决了,例如A模块依赖K库,B模块也依赖K库,弄三个动态库就可以了,不会用冲突问题。但是静态库的话,就可以有麻烦了,在编译A模块的时候可能会静态把K库打包进来,同样B模块也会这样,到最后打包整个app的时候,可能就会报错了,app包含了两个K库的代码。使用动态库则不同,动态库是在运行时链接加载的,彼此都是独立的。自己手工创建静态库或者Framework,步骤繁琐,效率低下,容易出错。如果cocoapods很方便了,每个模块都是一个git库,提交代码之后,在代码编译的服务器上pod update,xcodebuild 就可以自动打包分发了。苹果的垃圾桶也可以这样,像tx的大型游戏,用macbook pro的顶配打包都知道要多少时间呢,需要苹果的垃圾桶。
    能利用cocoapods构建项目的前提是模块要组件化,需要想到一个方法,能到很方便的注册模块,加载模块。这些网上有很多方案,http://www.jianshu.com/p/afb9b52143d4 感兴趣的希望认真的demo一下,虽然并不是每个人都能接触大项目的,但是为未来做准备是必要的。我在git上的demo就是用了CTMediator+Target-Action方案,该方案比较适合用在oc上,纯swift是不支持runtime的,但是也可以弄,坑可能比较多,这就是我至今不考虑用swift的原因了,估计很多以前的大项目,也没那么快转到swift上开发,新语言看似很好,但是改变的成本总是很大的,swift在小项目当玩具玩一玩还是不错的,但是要有心理准备,坑,https://github.com/OnelongX/MyApp,但是这个没有用上cocoapods,我本地的测试的demo是用上了,其实都是差不多,就是网上很多人xib等UI文件,比较麻烦。不过Framework是支持xib文件打包的。
    既然说到xib和storyboard了,最近看了很多评价,还有自己项目的思考。发现xib和storyboard在多版本并发开发不方便,同步相当麻烦。xcode升级也会带来一些问题。所以在产品开发中,还是建议纯代码写吧。大型项目就不用说了,基本都是纯代码。如果追求开发效率,xib和storyboard无疑是最好的选择,但是迭代的时候就蓝瘦香菇了。
    cocoapods是非常有用的,希望大家不怕麻烦,下决心折腾一番,定会有收获的。 

  • 大并发服务

    post by onelong / 2016-10-14 5:31 Friday [工作]

    App----->DAL(队列+连接池)--->DB

    阅读全文>>