Google Analytics(谷歌分析) 架构与原理

目录 后端架构

Google Analytics(Google分析)是Google的一款免费的网站分析服务,Google Analytics最早是由一些工程师设计的,后来被Google收购,现在被广受好评。对于Google Analytics的用户目前在国内的用户已经数以万计,本站 www.javabloger.com也使用Google Analytics工具对网站的访问趋势进行分析。Google Analytics功能非常强大,只要在网站的页面上加入一段代码,就可以提供的丰富详尽的图表式报告。

Google Analytics的采集功能是采用AJAX技术来实现,还可以对google共享你的分析数据,并且还可以设置系统提醒功能。
整体架构如图所示:

google-analytics-architecture

使用Google Analytics我们知道首先需要在你的网站中加入根据代码,下面我们来看看嵌入在网站中跟踪代码如何工作的
谷歌分析跟踪代码(Google Analytics Tracking Code GATC) 检索的网页数据如下:
1 浏览器请求的网页包含跟踪代码。
2 GATC创建并初始化一个对象的属性与网络相关的跟踪ID在代码中。
3 GATC执行你自定义任何跟踪方法。
4 跟踪代码初始化和管理以下信息:
*跟踪检索查看是否包括广告系列。
*收集从HTTP请求的信息到Google GATC中介 的各种用户信息。
5 将访问者HTTP请求包含GATC跟踪信息收集到参数名单。
如图所示:

gatcProcessing

以上详细过程还可以参考Google的官方资料http://www.google.com/support/googleanalytics/bin/answer.py?hl=cn&answer=55540

Google分析工具的官方帮助中心:http://www.google.com/support/googleanalytics/

H.E的口水:
1.不同的用户来源需要进行时间差计算,是不是就是因为这个所以在Google分析工具里面只给使用太平洋的时间。
2.老调重弹,Google对于大数据量存储和大规模并发访问的策略做的的确是很棒。再次引发了我对Google架构的探索,在此插入一个技术类型的小广告(图片),如图所示google 的搜索引擎部分的架构图:

3.从Google 分析工具的报告版面上来看,GATC的数据收集的非常详细,能做到比较全面而不占用资源,对用户透明,不容易。

继续阅读 “Google Analytics(谷歌分析) 架构与原理”

使用Java开发高性能网站需要关注的那些事儿

目录 JVM, 后端架构, 性能, 数据库-Database, 数据库-MySQL, 缓存


近期各家IT媒体举办的业内技术大会让很多网站都在披露自己的技术内幕与同行们分享,大到facebook,百度,小到刚起步的网站。facebook,百度之类的大型网站采用的技术和超凡的处理能力的确给人耳目一新的感觉,但并不是每个网站都是像facebook,百度 有上亿的用户访问流量,有海量的数据需要存储,需要使用到mapreduce/并行计算,HBase/列存储这些技术不可。技术手段始终是运营的支撑,对于当前的运营环境适用就好,没有必要非要赶个时髦,一定要和某项流行的技术产生点关系才善罢甘休。

在最近的技术大会中我们更多的目光都聚焦在这些大型网站,其实中小型门户网站的技术体系也是值得去探讨和关注。全天下的攻城师们并不是都在为这些大型门户网站服务,更多的攻城师们正在默默无闻的为一些刚刚起步的中小型网站服务,而且占据了攻城师队伍中的60%以上的人群。在关注大型门户网站的时候,中小型门户网站的技术发展和实战经验更值得去分享。

无论大型门户网站还是中小型垂直类型网站都会对稳定性、性能和可伸缩性有所追求。大型网站的技术经验分享值得我们去学习和借用,但落实到更具体的实践上并不是对所有网站可以适用,其他语言开发的网站我还不敢多说,但Java开发的系统,我还是能您给插上几句话:

JVM
JEE容器中运行的JVM参数配置参数的正确使用直接关系到整个系统的性能和处理能力,JVM的调优主要是对内存管理方面的调优,优化的方向分为以下4点:
1.HeapSize             堆的大小,也可以说Java虚拟机使用内存的策略,这点是非常关键的。
2.GarbageCollector  通过配置相关的参数进行Java中的垃圾收集器的4个算法(策略)进行使用。
3.StackSize             栈是JVM的内存指令区,每个线程都有他自己的Stack,Stack的大小限制着线程的数量。
4.DeBug/Log           在JVM中还可以设置对JVM运行时的日志和JVM挂掉后的日志输出,这点非常的关键,根据各类JVM的日志输出才能配置合适的参数。
网上随处可见JVM的配置技巧,但是我还是推荐阅读Sun官方的2篇文章,可以对配置参数的其所依然有一个了解
1.Java HotSpot VM Options
http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html
2.Troubleshooting Guide for Java SE 6 with HotSpot VM http://www.oracle.com/technetwork/java/javase/index-137495.html
另外,我相信不是每个人攻城师都是天天对着这些JVM参数的,如果你忘记了那些关键的参数你可以输入Java -X(大写X)进行提示。

JDBC
针对MySQL的JDBC的参数在之前的文章中也有介绍过,在单台机器或者集群的环境下合理的使用JDBC中的配置参数对操作数据库也有很大的影响。
一些所谓高性能的 Java ORM开源框架也就是打开了很多JDBC中的默认参数:
1.例如:autoReconnect、prepStmtCacheSize、cachePrepStmts、useNewIO、blobSendChunkSize 等,
2.例如集群环境下:roundRobinLoadBalance、failOverReadOnly、autoReconnectForPools、secondsBeforeRetryMaster。
具体内容可以参阅MySQL的JDBC官方使用手册:
http://dev.mysql.com/doc/refman/5.1/zh/connectors.html#cj-jdbc-reference

数据库连接池(DataSource)
应用程序与数据库连接频繁的交互会给系统带来瓶颈和大量的开销会影响到系统的性能,JDBC连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而再不是重新建立一个连接,因此应用程序不需要频繁的与数据库开关连接,并且可以释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏。这项技术能明显提高对数据库操作的性能。
在此我认为有一点需要说明:
连接池的使用也是需要关闭,因为在数据库连接池启动的时候就预先和数据库获得了相应的连接,之后不再需要应用程序直接的和数据库打交道,因为应用程序使用数据库连接池是一个“借”的概念,应用程序从数据库连接池中获得资源是“借出”,还需要还回去,就好比有20个水桶放在这里,需要拿水的人都可以使用这些木桶从水池里面拿水,如果20个人都拿完水,不将水桶还回原地,那么后面来的人再需要拿水,只能在旁边等待有人将木桶还回去,之前的人用完后需要放回去,不然后面的人就会一直等待,造成资源堵塞,同理,应用程序获取数据库连接的时候Connection连接对象的时候是从“池”中分配一个数据库连接出去,在使用完毕后,归还这个数据库连接,这样才能保持数据库的连接“有借有还”准则。
参考资料:
http://dev.mysql.com/doc/refman/5.1/zh/connectors.html#cj-connection-pooling

数据存取
数据库服务器的优化和数据的存取,什么类型的数据放在什么地方更好是值得去思考的问题,将来的存储很可能是混用的,Cache,NOSQL,DFS,DataBase 在一个系统中都会有,生活的餐具和平日里穿衣服需要摆放在家里,但是不会用同一种类型的家具存放,貌似没有那个人家把餐具和衣服放在同一个柜子里面的。这就像是系统中不同类型的数据一样,对不同类型的数据需要使用合适的存储环境。文件和图片的存储,首先按照访问的热度分类,或者按照文件的大小。强关系类型并且需要事务支持的采用传统的数据库,弱关系型不需要事务支持的可以考虑NOSQL,海量文件存储可以考虑一下支持网络存储的DFS,至于缓存要看你单个数据存储的大小和读写的比例。
还有一点值得注意就是数据读写分离,无论在DataBase还是NOSQL的环境中大部分都是读大于写,因此在设计时还需考虑 不仅仅需要让数据的读分散在多台机器上,还需要考虑多台机器之间的数据一致性,MySQL的一主多从,在加上MySQL-Proxy或者借用JDBC中的一些参数(roundRobinLoadBalance、failOverReadOnly、autoReconnectForPools、secondsBeforeRetryMaster)对后续应用程序开发,可以将读和写分离,将大量读的压力分散在多台机器上,并且还保证了数据的一致性。

缓存
在宏观上看缓存一般分为2种:本地缓存和分布式缓存
1.本地缓存,对于Java的本地缓存而言就是讲数据放入静态(static)的数据结合中,然后需要用的时候就从静态数据结合中拿出来,对于高并发的环境建议使用 ConcurrentHashMap或者CopyOnWriteArrayList作为本地缓存。缓存的使用更具体点说就是对系统内存的使用,使用多少内存的资源需要有一个适当比例,如果超过适当的使用存储访问,将会适得其反,导致整个系统的运行效率低下。
2. 分布式缓存,一般用于分布式的环境,将每台机器上的缓存进行集中化的存储,并且不仅仅用于缓存的使用范畴,还可以作为分布式系统数据同步/传输的一种手段,一般被使用最多的就是Memcached和Redis。
数据存储在不同的介质上读/写得到的效率是不同的,在系统中如何善用缓存,让你的数据更靠近cpu,下面有一张图你需要永远牢记在心里,来自Google的技术大牛Jeff Dean(Ref)的杰作,如图所示:
cache-speed
并发/多线程
在高并发环境下建议开发者使用JDK中自带的并发包(java.util.concurrent),在JDK1.5以后使用java.util.concurrent下的工具类可以简化多线程开发,在java.util.concurrent的工具中主要分为以下几个主要部分:
1.线程池,线程池的接口(Executor、ExecutorService)与实现类(ThreadPoolExecutor、 ScheduledThreadPoolExecutor),利用jdk自带的线程池框架可以管理任务的排队和安排,并允许受控制的关闭。因为运行一个线程需要消耗系统CPU资源,而创建、结束一个线程也对系统CPU资源有开销,使用线程池不仅仅可以有效的管理多线程的使用,还是可以提高线程的运行效率。
2.本地队列,提供了高效的、可伸缩的、线程安全的非阻塞 FIFO 队列。java.util.concurrent 中的五个实现都支持扩展的 BlockingQueue 接口,该接口定义了 put 和 take 的阻塞版本:LinkedBlockingQueue、ArrayBlockingQueue、SynchronousQueue、PriorityBlockingQueue 和 DelayQueue。这些不同的类覆盖了生产者-使用者、消息传递、并行任务执行和相关并发设计的大多数常见使用的上下文。
3.同步器,四个类可协助实现常见的专用同步语句。Semaphore 是一个经典的并发工具。CountDownLatch 是一个极其简单但又极其常用的实用工具,用于在保持给定数目的信号、事件或条件前阻塞执行。CyclicBarrier 是一个可重置的多路同步点,在某些并行编程风格中很有用。Exchanger 允许两个线程在 collection 点交换对象,它在多流水线设计中是有用的。
4.并发包 Collection,此包还提供了设计用于多线程上下文中的 Collection 实现:ConcurrentHashMap、ConcurrentSkipListMap、ConcurrentSkipListSet、CopyOnWriteArrayList 和 CopyOnWriteArraySet。当期望许多线程访问一个给定 collection 时,ConcurrentHashMap 通常优于同步的 HashMap,ConcurrentSkipListMap 通常优于同步的 TreeMap。当期望的读数和遍历远远大于列表的更新数时,CopyOnWriteArrayList 优于同步的 ArrayList。

队列
关于队列可以分为:本地的队列 和 分布式队列 2类
本地队列:一般常见的用于非及时性的数据批量写入,可以将获取的数据缓存在一个数组中等达到一定数量的时候在进行批量的一次写入,可以使用BlockingQueue或者List/Map来实现。
相关资料:Sun Java API.
分布式队列:一般作为消息中间件,构建分布式环境下子系统与子系统之间通信的桥梁,JEE环境中使用最多的就是Apache的AvtiveMQ和Sun公司的OpenMQ。
轻量级的MQ中间件之前也向大家介绍过一些例如:Kestrel和Redis(Ref http://www.javabloger.com/article/mq-kestrel-redis-for-java.html),最近又听说LinkedIn的搜索技术团队推出了一个MQ产品-kaukaf(Ref http://sna-projects.com/kafka ),对此保持关注。
相关资料:
1.ActiveMQ http://activemq.apache.org/getting-started.html
2.OpenMQ  http://mq.java.net/about.html
3.Kafka       http://sna-projects.com/kafka      
4.JMS文章  http://www.javabloger.com/article/category/jms

NIO
NIO是在JDK1.4后的版本中出现的,在Java 1.4之前,Jdk提供的都是面向流的I/O系统,例如读/写文件则是一次一个字节地处理数据,一个输入流产生一个字节的数据,一个输出流消费一个字节的数据, 面向流的I/O速度非常慢,并且一个数据包要么整个数据报已经收到,要么还没有。Java NIO非堵塞技术实际是采取Reactor模式,有内容进来会自动通知,不必死等、死循环,大大的提升了系统性能。在现实场景中NIO技术多数运用两个方面,1是文件的读写操作,2是网络上数据流的操作。在NIO中有几个核心对象需要掌握:1选择器(Selector)、2通道(Channel)、3缓冲区(Buffer)。
我的废话:
1.在Java NIO的技术范畴中内存映射文件是一种高效的做法,可以用于缓存中存储的冷/热数据分离,将缓存中的一部分冷数据进行这样的处理,这种做法上比常规的基于流或者基于通道的I/O快的多,通过使文件中的数据出现为内存数组的内容来完成的,将文件中实际读取或者写入的部分才会映射到内存中,并不是将整个文件读到内存中。
2.在Mysql的jdbc驱动中也可以使用NIO技术对数据库进行操作来提升系统的性能。

长连接/Servlet3.0
这里说的长连接就是长轮询,以前浏览器(客户端)需要关注服务器端发生的数据变化需要不断的访问服务器,这样客户端的数量一多必然会给服务器端造成很大的压力,例如:论坛中的站内消息。现在Servlet3.0规范中提供了一个新的特性:异步IO通信;该特性会保持一个长连接。利用Servlet3异步请求的这项技术可以大大的缓解服务器端的压力。
Servlet3.0的原理就是将request的请求开启一个线程挂起,中间设置等待超时的时间,如果后台事件触发request请求,得到的结果返回给客户端的request请求,如果在设置等待超时的时间内没有任何事件发生也将请求返回给客户端,客户端将再次发起request请求,客户端与服务器端的交互可以与此往复。
就好比,你先过来跟我说如果有人找你,我就立马通知你你来见他,原先你需要不断的问我有没有要找你,而不管有没有人找你,你都需要不断的问我有没有人找你,这样的话不论问的人还是被问的人都会累死。

日志
Log4J是通常被人们使用的工具,系统在刚刚上线的时候日志一般都设置在INFO的级,真正上线后一般设置在ERROR级,但无论在任何时候,日志的输入内容都是需要关注的,开发人员一般可以依靠输出的日志查找出现的问题或者依靠输出的日志对系统的性能进行优化,日志也是系统运行状态的报告和排错的依据。
简单来说日志按照定义的不同策略和等级输出到不同的环境,那样便于我们分析和管理。相反你没有策略的输出,那么机器一多,时间一长,会有一大推乱糟糟的日志,会让你排错的时候无从下手,所以日志的输出策略是使用日志的关键点。
参考资料:http://logging.apache.org/log4j/1.2/manual.html

打包/部署
在代码设计的时候最好能将不同类型的功能模块在IDE环境中粗粒度的分为不同的工程,便于打成不同jar包部署在不同的环境中。有这样的一个应用场景:需要每天定时远程从SP那边获得当天100条新闻和部分城市的天气预报,虽然每天的数据量不多,但是前端访问的并发量很大,显然需要在系统架构上做到读写分离。
如果把web工程和定时抓取的功能模块完全集中在一个工程里打包,将导致需要扩展的时候每台机器上既有web应用也有定时器,因为功能模块没有分开,每台机器上都有定时器工作将会造成数据库里面的数据重复。
如果开发的时候就将web和定时器分为2个工程,打包的时候就可以分开部署,10台web对应一台定期器,分解了前端请求的压力,数据的写入也不会重复。
这样做的另一个好处就是可以共用,在上述的场景中web和定时器都需要对数据库进行读取,那么web和定时器的工程里都有操作数据库的代码,在代码的逻辑上还是感觉乱乱的。如果再抽出一个DAL层的jar,web和定时器的应用模块开发者只需要引用DAL层的jar,开发相关的业务逻辑,面向接口编程,无需考虑具体的数据库操作,具体的对数据库操作由其他开发者完成,可以在开发任务分工上很明确,并且互不干涉。

框架
所谓流行的SSH(Struts/Spring/Hiberanet)轻量级框架,对于很多中小型项目而言一点都不轻量级,开发者不仅需要维护代码,还需要维护繁琐的xml配置文件,而且说不定某个配置文件写的不对就让整个都工程无法运行。无配置文件可以取代SSH(struts/Spring/Hiberanet)框架的产品真的太多了,我之前就向大家介绍过一些个产品(Ref)。
这个我并不是一味的反对使用SSH(Struts/Spring/Hiberanet)框架,在我眼里SSH框架真的作用是做到了规范开发,而并不使用了SSH(Struts/Spring/Hiberanet)框架能提高多少性能。
SSH框架只是对于非常大的项目人数上百人的团队,还需要、继续增加团队规模的公司而言,是需要选择一些市面上大家都认可,并且熟悉的技术,SSH(Struts/Spring/Hiberanet)框架比较成熟所以是首先产品。
但是对于一些小团队中间有个把技术高人的团队而言完全可以选择更加简洁的框架,真正的做到提速你的开发效率,早日抛弃SSH框架选择更简洁的技术在小团队开发中是一种比较明知的选择。

Hive入门篇

目录 apache-hive, hadoop

Hive是Hadoop项目中的一个子项目,由FaceBook向Apache基金会贡献,其中TaoBao也是其中一位使用者和贡献者,Hive被视为一个仓库工具,可以将结构化的数据文件映射为一张数据库表,并可以将sql语句转换为 MapReduce 任务进行运行。 其优点是学习成本低,可以通过类SQL语句快速实现简单的MapReduce统计,不必开发专门的MapReduce应用,十分适合数据仓库的统计分析。
Hive主要分为以下几个部分:
1.用户接口
用户接口主要有三个:命令行(CLI),客户端(Client) 和 Web界面(WUI)。其中最常用的是 CLI,启动的时候,会同时启动一个 Hive 服务。Client 是 Hive 的客户端,用户连接至 Hive Server。在启动 Client 模式的时候,需要指出 Hive Server 所在节点,并且在该节点启动 Hive Server。 WUI 是通过浏览器访问 Hive的Web工具。
2.元数据存储
Hive 将元数据存储在数据库中,如 MySQL或者Derby嵌入式数据库。若将元数据存储在MySQL中,在TBLS中可以看见你建立的所有表信息,Hive 中的元数据包括表的名字,表的列和分区及其属性,表的属性(是否为外部表等),表的数据所在目录等。
3. 执行
解释器、编译器、优化器完成 HQL 查询语句从词法分析、语法分析、编译、优化以及查询计划的生成。生成的查询计划存储在 HDFS 中,并在随后有 MapReduce 调用执行。
4. HDFS存储
Hive 的数据存储在 HDFS 中,大部分的查询由 MapReduce 完成(包含 * 的查询,比如 select * from tbl 不会生成 MapRedcue 任务)。
如图所示:
hive-Architecture
Hive 元数据存储
Hive 将元数据存储在 RDBMS 中,有三种模式可以连接到数据库:

继续阅读 “Hive入门篇”

我的Javabloger从开始到现在

目录 未分类
“Hello World!”
1348814017665
Javabloger的空间再次开启,随着Javabloger的再次开启仿佛时间再次把我带到2010年的时光里,2010年到现在的2016年已经发生了太多太多的事情,这6年里我经历的最多的感受就是创业。因此创业的过程中需要你付出大量的时间和精力,我不仅仅放弃了之前的摄影爱好,同时也放弃了很多与家人共渡的时光。
有时候不是有具体的某个人逼着你干事情,而是你所处的整个环境逼着你向前走,停不下来!
2010年一个非常偶然的机会给我带来了最大转变,让我从2003年一直单纯的从事技术岗位的工作转变成技术+管理的工作。
2010年一直到2016初,我基本上没有办法停下来,你想象不到,整个人每天沸腾起来的感觉是怎么样的?!
2014年,离开我工作7年半的公司。
2014年,我获得1000万美金,开始在020领域创业,将一家公司从无到有的建设。
2016年,随着大批020公司灭亡,我离开了我自己创建的公司。
待续未完

Obtaining Consent

目录 性能, 数据库-Database

Fitbit supports the Authorization Code Grant and Implicit Grant flows as defined in RFC 6749.

The Authorization Code Grant flow is recommended for applications that have a web service. This flow requires server-to-server communication using an application’s client secret.

Note: Never put your client secret in distributed code, such as apps downloaded through an app store or client-side JavaScript.

Applications that do not have a web service should use the Implicit Grant flow.
WARNING – DO NOT embed the Authorization Page

继续阅读 “Obtaining Consent”

Tinder: How Does One Of The Largest Recommendation Engines Decide Who You’ll See Next?

目录 后端架构, 性能

Caching is a common approach for improving performance, yet most implementations use strictly classical techniques. In this article we will explore the modern methods used by Caffeine, an open-source Java caching library, that yield high hit rates and excellent concurrency. These ideas can be translated to your favorite language and hopefully some readers will be inspired to do just that.

Eviction Policy

A cache’s eviction policy tries to predict which entries are most likely to be used again in the near future, thereby maximizing the hit ratio. The Least Recently Used (LRU) policy is perhaps the most popular due to its simplicity, good runtime performance, and a decent hit rate in common workloads. Its ability to predict the future is limited to the history of the entries residing in the cache, preferring to give the last access the highest priority by guessing that it is the most likely to be reused again soon.

Modern caches extend the usage history to include the recent past and give preference to entries based on recency and frequency. One approach for retaining history is to use a popularity sketch (a compact, probabilistic data structure) to identify the “heavy hitters” in a large stream of events. Take for example CountMin Sketch, which uses a matrix of counters and multiple hash functions. The addition of an entry increments a counter in each row and the frequency is estimated by taking the minimum value observed. This approach lets us tradeoff between space, efficiency, and the error rate due to collisions by adjusting the matrix’s width and depth.

Window TinyLFU (W-TinyLFU) uses the sketch as a filter, admitting a new entry if it has a higher frequency than the entry that would have to be evicted to make room for it. Instead of filtering immediately, an admission window gives an entry a chance to build up its popularity. This avoids consecutive misses, especially in cases like sparse bursts where an entry may not be deemed suitable for long-term retention. To keep the history fresh an aging process is performed periodically or incrementally to halve all of the counters.

W-TinyLFU uses the Segmented LRU (SLRU) policy for long term retention. An entry starts in the probationary segment and on a subsequent access it is promoted to the protected segment (capped at 80% capacity). When the protected segment is full it evicts into the probationary segment, which may trigger a probationary entry to be discarded. This ensures that entries with a small reuse interval (the hottest) are retained and those that are less often reused (the coldest) become eligible for eviction.

继续阅读 “Tinder: How Does One Of The Largest Recommendation Engines Decide Who You’ll See Next?”

Why Does Unikernel Systems Joining Docker Make A Lot Of Sense?

目录 JVM, 后端架构, 数据库-MySQL

Unikernel Systems Joins Docker. Now this is an interesting match. The themes are security and low overhead, though they do seem to solve the same sort of problem.

So, what’s going on?

In FLOSS WEEKLY 302 Open Mirage, starting at about 10 minutes in, there are a series of possible clues. Dr. Anil Madhavapeddy, former CTO of Unikernel Systems, explains their motivation behind the creation of unikernels. And it’s a huge and exciting vision.

What they are trying to build is a system to manage personal data. Let’s say you don’t want to store your private data in the cloud because, well, it’s private. We now have lots of really small devices that are more than powerful enough to handle such a task. What you need is a system that can manage the data while bringing it under your personal physical control, in your house or office, for example. The average user doesn’t know how to run a full blown computer system, it needs to just run itself.

The goal is to deploy these environments, trillions of them, everywhere, and have them just work.

IMHO this whole lovely vision requires a lot of infrastructure to manage correctly, the very same kind of infrastructure that’s being built around Docker. So maybe that’s where the marriage makes sense?

继续阅读 “Why Does Unikernel Systems Joining Docker Make A Lot Of Sense?”