石建 | Fat Mind

题记:一个cookie,整个下午都没有找到解决的办法。

 

一、遇到的问题

1. 情景:访问http://list.mall.daily.taobao.net/50024400/xxx,当前页面通过ajax请求广告,请求的域为http://tmatch.simba.taobao.com/xxx;广告引擎向页面种seesion范围的cookie_back,用于标识翻页;

      2. 问题:

点击当前页面的翻页,IE下广告不翻页?通过firebughttpwatch对比,发现IEcookie“_back”不正确。开始猜测是引擎种cookie的逻辑存在问题,但很多地方都在使用此接口,均没有问题。

且有人的机器翻页正常,此时怀疑是浏览器设置问题?再用httpwatch观察“http请求头,发现_back没有回传给引擎(其实httpwatchcookies也可以观察到,如果发送cookie的话,会显示为Sent;之前只观察到Received)? 确认是浏览器的问题。

3. 解决:打开IE隐私设计,通常默认设置为,拒绝没有隐私政策的第三方cookie ...”,意味着_back并没有成功写入客户端,所有请求引擎导致不能正确回传_back,翻页失败。

         这么说淘宝所有的广告的翻页都是不可用的 ?肯定不是。问题在第一方 Cookie 来自您正浏览的网站,它们可以是永久的或临时的;第三方 Cookie 来自您正浏览的网站上的其他网站的广告”,对于浏览器“taobao.nettaobao.com”就是不同的两个网站,所以引擎的_back是无法种在客户端。此情景是daliy环境,线上的环境访问的是list.mall.daily.taobao.com,所以不存在第三方cookie”的概念,广告是可以正确显示。

 

二、关于cookie小知识

 

1.IE Cookie的格式

第一行名称,第二行,第三行所属域” ...比如“.taobao.com”存在cna,此cookie会被浏览器自动发送到任何属于此域的子域;www.taobao.com\taobao.com,后面的是根域,前一个是二级域。xp存放目录为:C:\Documents and Settings\<username>\Cookies\,文件命名:你的用户名@生成COOKIEdomain[COOKIE改变的次数].txt

  参考:http://blog.csdn.net/zhangxinrun/archive/2010/07/31/5779574.aspx

 

2.Js Cookie跨域访

 http://blog.csdn.net/tongdoudpj/archive/2009/05/10/4166096.aspx

 

3.cookiesession的关系

根本的原因:http协议的无状态性,cookie的出现就是为了解决这个问题。

session是一种在客户端与服务器之间保持状态的解决方案。服务端存储内容,返回对应的key给客户端,当下次访问时,带上此key,实现状态的维持。

session实现:

1.依赖cookieThe session cookie is stored in temporary memory and is not retained after the browser is closed。(实际测试:IE8,未在1描述的位置找到session级别cookie对应的文件,猜测‘临时存储在浏览器内存’,当关闭浏览器时则丢失key)

2.url重写。Servlet规范定义此功能。当浏览器禁用cookie时,就算session级别的内容也不会被存储。resp.encodeRedirectURL(url),且仅当禁用cookie时有效,重写结果如:http://www.demo.com/cookie.do;jsessionid=19gfy1sg740dl1whwd72lbqlhb

疑问:server如何判断,是否需要重写呢?从实验现象看,判断是否收到name=JSESSIONID cookie,若无,则进行url重写。

           最好的方式,翻翻tomcatjetty的源码实现,但未找到对应的代码。

关于cookie的详细信息参见: http://en.wikipedia.org/wiki/HTTP_cookie

 

posted @ 2010-11-08 21:41 石建 | Fat Mind 阅读(679) | 评论 (0)编辑 收藏
题记:老大开始在团队推行敏捷。记录目前自己理解的优点,还有敏捷不适应问题。

一、自己理解的敏捷

1.风险分散。这点,我是非常肯定的。亲身的体会,jim负责A模块,以前做法:项目经理pety,在A模块快提交的前期去和jim沟通模块的完成情况。现在做法:每天jim向prty汇报自己的进度情况和问题。帮助pety对项目的可控性提高很多,风险也能尽早的暴露出来。带来的问题:必须对A模块进行更细的任务分解,如何分解?时间如何评估?谁来评估?(团队做法:由jim自己细分A模块,再与pety确认计划,此时pety可以给出自己的意见,共同来评估时间。)

2.可视化。同意这点。之前做法:每天发邮件周知大家进度情况;团队目前做法:看板(贴每个人具体细分的任务),每天汇报具体的进度和遇到的问题。其实两种做法的目的是一样,都是想让别人知道自己的进度和问题。但第二种方法优点:a.阅读邮件,是每个人独立的行为,是分散的,看板上任务的汇报是大家在一起的,此时面对面的沟通是更高效的;b.对于我的感觉,看板比邮件更加可视化;c.基于看板,后期的后顾和总结也更加方便。

3.团队化。jim负责A模块,jeny负责B模块,当A模块jim可能存在跟多问题(前期没有评估到),希望jeny可以帮jim完成其中的部分。问题:jeny根本不熟悉A模块,熟悉A模块所花费的时间,以及对B模块的影响,都是需要评估的。自己的理解:对于多人同时开发的项目,此方法还是可以试用的;但是对于单兵作战的日常,大家的精力都是有限的,很难说A做大一半的时候,让B来帮忙。这也是目前大家争论的焦点。

二、团队目前的做法

1.细粒度的任务分解。比如:搜索页面智能导航,分解的任务:a.了解接口需要的参数,以及返回的结果的格式 b.请求参数处理  c.返回xml结果解析 d.后期根据业务逻辑的处理。整个任务肢解的力度非常细,对项目风险的把控更加有好处。
2.看板。分为:任务、开发中、done(三部分)。根据每天大家反馈的情况,更新项目剩余需要的工时(细粒度到时间)。
3.晨会。早晨站在看板前,每个对着看板,说自己“昨天干了什么&是否遇到什么问题、今天准备做什么”,对应的调整看板的内容和任务所需时间。
4.总结。这点目前做的不够好,不是大家都来提建议,可能整个团队还是“一个大脑”,只是一个人在想问题(当然这与团队的氛围是有关系的)。

三、难点

1.个人的积极性和参与度
  敏捷是需要团队的每个人都以主人公的态度参与进来的,当然团队也要能够给予他认同,这是软实力的问题;比如:相互提建议,但是这首先需要团队安全的环境,对老大说的话,大家可以提出不同的意见,否则始终是“一个脑袋”在思考,大家习惯于去服从;同时也要克服养成的“中庸之道”,当然也要注意提建议的方式。
2.任务的细分和工时的评估
  需要项目经理对团队成员有很熟悉的了解,才能合理的安排任务。根据不同的人确定不同的工时,大家都能在一种被尊重和快乐的氛围中工作,此时的效率肯定是高。
3.团队的成就感
  需要自下而上的,获得的成就是每一个人的,而不是简单是他的或者我的。每个人都能找到被认同的感觉,乐于分享自己的收获,此时整个团队的每个人都会成长,团队的战斗力肯定也会大大提高。


总结:发现难点的地方,还是团队软实力的建设。
posted @ 2010-11-07 18:47 石建 | Fat Mind 阅读(178) | 评论 (0)编辑 收藏
题记:主要记录同学分享的关于数据库设计方面的内容,思考过一点,记录下来。

一、从需求开始,考虑数据库的设计,且结合具体数据库特性

  一个论坛,要求显示帖子的总条数,对于mysql、innodb引擎;上线前期完全没有问题,当人气积累,帖子达到千万级别时,此时性能的问题就会显现出来。好的设计,是需求阶段就要考虑的。对于我,这是一个思想概念上的转变。
  但引擎如果换成myisam,就算数据达到亿的级别,“统计总数”这样的问题还会存在吗 ?不会,myisam自身就会维护总数信息。因此设计,必须结合具体的数据库的特性来做,不能以一概全。

二、应该遵循原则 (未验证)

  1.小结果集驱动大结果集。理由:mysql的连接查询原理 ?
  2.尽可能在索引中完成排序。理由:索引本身就是有序的
  3.只取自己需要的column ?
  4.避免复杂的连接查询和子查询。
  5.适当的数据冗余.理由:帖子表&用户表,如果帖子表拥有username,则每次帖子的显示是不需要连接查询获取username。 
  6.应用层的cahce机制 ?

三、概念

  1.垂直拆分:按列进行分割,即把一条记录分开多个地方保存,每个子表的行数相同。帖子表,id、userid、username、content、xxx ...前面4个字段很常用,但是后面xxx等很多字段,不常用,数据量很大。进行垂直拆分,table1字段包含“id、userid、username、content”,table2包含“xxx、...”等不常用字段。优点:减少io的操作。缺点:如果需要不常用字段信息,需要连表查询。
  2.水平拆分:
按记录进分分割,不同的记录分开保存,每个子表的列数相同。比如:淘宝的用户交易数据,根据用户id取模,确定具体的数据存放在那个数据库。水平拆分会给应用带来复杂性。
  3.集群:提高系统的可用性。分库的节点引入多台机器,每台机器保 存的数据是一样,负载均衡在多台机器。如何均衡、探测机器的可用性,是新的问题 ?
  4.主备:一般的互联网应用中,经过一些数据调查得出结论,读/写的比例大概在 10:1左右。为什么要读写分离:写操作涉及到锁的问题,不管是行锁还是表锁还是块锁,在大并发的情况下,效率很低。写操作集中在一个节点上,而读操作其其他 的N个节点上进行。读写分离引入的新问题:比如我的Master上的数据怎样和集群中其它Slave机器保持数据的同步和一致呢?




posted @ 2010-11-07 17:53 石建 | Fat Mind 阅读(456) | 评论 (0)编辑 收藏
请参考:http://en.wikipedia.org/wiki/Join_(SQL)#Sample_tables

inner JOINS

  An inner join is the most common join operation used in applications and can be regarded as the default join-type. Inner join creates a new result table by combining column values of two tables (A and B) based upon the join-predicate. The query compares each row of A with each row of B to find all pairs of rows which satisfy the join-predicate. When the join-predicate is satisfied, column values for each matched pair of rows of A and B are combined into a result row. The result of the join can be defined as the outcome of first taking the Cartesian product (or cross-join) of all records in the tables (combining every record in table A with every record in table B)—then return all records which satisfy the join predicate. Actual SQL implementations normally use other approaches like a Hash join or a Sort-merge join where possible, since computing the Cartesian product is very inefficient.

  注意:innner查询(默认的连接查询方式),是先查询“Cartesian”生成中间表,再根据where条件筛选结果;但此方法非常低效,SQL具体的实现可能是 
Hash join or a Sort-merge join 。
        
One can further classify inner joins as equi-joins, as natural joins, or as cross-joins.

SELECT *
FROM employee INNER JOIN department
ON employee.DepartmentID = department.DepartmentID;
The following example shows a query which is equivalent to the one from the previous example.

SELECT *
FROM   employee, department
WHERE  employee.DepartmentID = department.DepartmentID;

Outer joins

  An outer join does not require each record in the two joined tables to have a matching record. The joined table retains each record—even if no other matching record exists. Outer joins subdivide further into left outer joins, right outer joins, and full outer joins, depending on which table(s) one retains the rows from (left, right, or both).

Example of a left outer join, with the additional result row italicized:

SELECT *
FROM   employee  LEFT OUTER JOIN department
ON employee.DepartmentID = department.DepartmentID;
Employee.LastNameEmployee.DepartmentIDDepartment.DepartmentNameDepartment.DepartmentID
Jones 33 Engineering 33
Rafferty 31 Sales 31
Robinson 34 Clerical 34
Smith 34 Clerical 34
John NULL NULL NULL
Steinberg 33 Engineering 33


Example right outer join, with the additional result row italicized:

SELECT *
FROM   employee RIGHT OUTER JOIN department
ON employee.DepartmentID = department.DepartmentID;
Employee.LastNameEmployee.DepartmentIDDepartment.DepartmentNameDepartment.DepartmentID
Smith 34 Clerical 34
Jones 33 Engineering 33
Robinson 34 Clerical 34
Steinberg 33 Engineering 33
Rafferty 31 Sales 31
NULL NULL Marketing 35


Example full outer join: (mysql is not support)

SELECT *
FROM   employee
FULL OUTER JOIN department
ON employee.DepartmentID = department.DepartmentID;
Employee.LastNameEmployee.DepartmentIDDepartment.DepartmentNameDepartment.DepartmentID
Smith 34 Clerical 34
Jones 33 Engineering 33
Robinson 34 Clerical 34
John NULL NULL NULL
Steinberg 33 Engineering 33
Rafferty 31 Sales 31
NULL NULL Marketing 35


Self-join

A query to find all pairings of two employees in the same country is desired.

An example solution query could be as follows:

SELECT F.EmployeeID, F.LastName, S.EmployeeID, S.LastName, F.Country
FROM Employee F, Employee S
WHERE F.Country = S.Country
AND F.EmployeeID < S.EmployeeID
ORDER BY F.EmployeeID, S.EmployeeID;

Which results in the following table being generated.

Employee Table after Self-join by Country
EmployeeIDLastNameEmployeeIDLastNameCountry
123 Rafferty 124 Jones Australia
123 Rafferty 145 Steinberg Australia
124 Jones 145 Steinberg Australia
305 Smith 306 John Germany










Join algorithms

Three fundamental algorithms exist for performing a join operation: Nested loop joinSort-merge join and Hash join.




 

posted @ 2010-11-03 15:36 石建 | Fat Mind 阅读(278) | 评论 (0)编辑 收藏
题记:新同学分享了“测试驱动”,第一次感觉测试驱动离自己那么近。因此开始尝试。记下自己的一小点想法。

1.一切从测试开始
  不管在写复杂的代码,还是简单的代码,一切从测试开始。练习成自己编码的习惯。
  自己的做法只能算是“伪测试驱动”,因为还是有详细的设计,但遵循此做法,对于需求的变更、代码存在的bug,导致编码修改的时候,心里是踏实的。
  目前自己还不能感觉到对后期的维护会带来什么样的结果?
  推荐《测试驱动开始》。

2.工具
  junit、mockito、emma

  junit,这是大家熟知的,学到新点:a。参数化测试  b。private方法测试(反射) c。runwith & Unite,组织测试单元
  mockito,轻量的mock工具。测试中很麻烦的一个问题是:环境依赖,比如:web中依赖容器生成request对象。mockito很好的解决大部分问题(static类与private方法未能解决)。
  emma,代码覆盖率检查工具,eclipse插件。效果:红色=未测试;黄色=测试不完整,只是部分逻辑;绿色=测试完整。(注意:不能绝对的追求覆盖率,一定要记住2/8原则,将主要的精力关注主要的逻辑)。

3.习惯
  a。代码结构,3部分:prepare(包含mock)准备数据、action执行、assert验证
  b。方法命名:被测试方法名$测试目的,如:run$ParameterIsNull
  c。测试A类,有两个方法run()和prepare(),run方法调用prepare,且prepare执行非常耗时间。想要单独测试run()方法 ?
     答案:B extends A,复写prepare方法(等于是mock prepare方法),单独的测试run方法逻辑。
  d。持续写测试代码的习惯



  

posted @ 2010-11-02 21:31 石建 | Fat Mind 阅读(235) | 评论 (0)编辑 收藏
请参见官网:http://androidappdocs.appspot.com/sdk/installing.html

1. preparing your development computer

  检查系统环境是否满足要求(基本忽略)

2.下载sdk

  path 增加 %android_home%/tools

3. eclipse开发环境

  eclipse3.5在线安装地址 :https://dl-ssl.google.com/android/eclipse/
4. 安装 android平台和其它组件

  之前下载的包,仅是一个工具包。The starter package is not a full development environment — it includes only the core SDK Tools, which you can use to download the rest of the SDK components.

  我的选择 :android platform、document、samples、google api、martket lience(请注意选择的版本要一致)

  Android USB驱动只有Windows才需要安装,作用:Contains driver files that you can install on your Windows computer, so that you can run and debug your applications on an actual device. 可以直接在你的android手机上,进行程序的调试、运行等。linux、mac是不需要安装。

5. hello world 

   http://developer.android.com/training/basics/firstapp/index.html

6. eclipse查看android源码

  http://log4think.com/browsing-android-source-in-eclipse/ 已验证:<sdk-home>/platforms/android-8,建立source文件夹,将源码放入。重启eclipse,即可看到源码。




今天发现,之前的url也不能访问;安装方式也不同,重新整理。

1. 安装sdk
http://developer.android.com/sdk/installing/index.html 
  下载sdk(windows下竟然是exe)
  It includes only the core SDK tools, which you can use to download the rest of the SDK packages, using the Android SDK Manager. 
  To develop an Android app, you also need to download at least one Android platform and the latest SDK Platform-tools。
  选择其它组件:tools、选择对应版本api、usb driver(请务必记住:选择使用http,而不是https,tools->options)

2.安装eclipse adt plugin
  http://developer.android.com/sdk/installing/installing-adt.html 
  select the checkbox next to Developer Tools and click Next.
 
config the adt plugin.



posted @ 2010-10-24 20:40 石建 | Fat Mind 阅读(224) | 评论 (0)编辑 收藏

已迁往 http://fatmind.iteye.com

题记:.java源文件是如何被找到的?.class字节码文件是如何被找到的?内容:全部借鉴《Java深度历险》

Package:命名空间的问题,隔离类之间的关系。

Import:声明引入的类的路径(仅在编译时有作用,编译后的文件,类的声明已经为全路径);好处“明晰的代码结构,分离在多个文件;帮助实现动态链接的功能”。

一、编译

package edu.nctu;

 

import com.taobao.Test;

import edu.nctu.*;

 

public class C

{

public void print() {

              System.out.println("package test") ;

       }

}

 

步骤:

1. 根据classpath建立,“类相对路径参考表”

如:javac –cp .;d:/test/,在d:/下执行,结果:d:/d:/test/

2. 以“类相对路径参考表”作为相对起始路径,验证能够找到所有要用的package

根据import引入的package或全限定类名,import packagename.classnamepackagename之中的“.”“/”取代.

       2.1 com.taobao.*形式,验证在d:/目录下是否存在com/taobao/目录,若不存在,依次检查d:/test/

       2.2 com.taobao.Test形式,验证是否存在com/taobao/Test,与上相同。

3. 建立“类参考表”和“相对类参考表”

       3.1 类参考表:com.taobao.Test

       3.2 类相对参考表:com.taobao.*

4. 解析class{} 包含的代码

是否全限定类名

       4.1 是,绝对路径 =“类相对路径参考表”+全限定类名,查找,不存在为错误;

       4.2 否,绝对路径 =“类相对路径参考表”,查找;

              4.2.1是,编译

              4.2.2否,解析package

                     4.2.2.1 在类参考表,是否存在1以上的同名类,出错;否则,绝对路径 =“类相对路径参考表”+ “类参考表”,正确。

                     4.2.2.2 在类参考表找不到,绝对路径 = “类相对路径参考表”+ “相对类参考表”,若存在一个以上的类,出错;否则,正确。

提醒:

1.       如果已经存在A .class文件,A .java不是必须的;

2.       编译器在找到源码或字节码,对会验证是否属于此package,但没有通过make机制的编译,是不会验证的;make机制,即编译器自动维护具有相互依赖关系的文件;javac命令直接编译文件,如:javac -cp d:/test com.edu.C.java,编译器角度:com.edu.C.java 是一个文件名,且没有通过make机制,所以-cp指定的路径建立的“类相对路径参考表”也不会使用,编译器直接在当前目录下查找com.edu.C.java,结果 ClassNotFoundException 。

二、运行

1、 编译结束后,import指令已经不存在,类被替换为“全限定类名”

2、 运行时类的加载,都是通过classloader进行,所以必须遵循正确的“包目录”结构,不管是否直接通过命令行执行。

步骤:

1.       建立“字节码路径参考表”,根据classpath

2.       绝对路径 = “字节码路径参考表”+ 全限定类名,查找;加载;找不到,报错。




posted @ 2010-10-17 01:29 石建 | Fat Mind 阅读(1366) | 评论 (0)编辑 收藏
题记:日志记录,对一个应用非常重要,不仅仅只为定位线上bug(exception日志),还有业务日志,比如:统计用户的搜索词、响应时间等。

一、
日志级别

众所周知,在log4j中定义5个最常用日志级别:debug、info、warn、error、fatal,级别依次严重。
可大家思考过,什么时候应该记info,exception时是应该记warn,还是error呢 ?下面是今天小团队讨论后,自己的一些理解。

debug:程序内部的信息,对于外部使用的人是没有意义。比如:函数的执行时间。(fine-grained information events that are most useful to debug an application)debug记录的是细粒度的事件信息,对于调式程序是非常有用的。

info:informational messages that highlight the progress of the application at coarse-grained level.(强调应用的执行的进度,关键分支的记录)。比如:关键分支记录(输入参数等),
对运维工程师来说这些信息也是有价值的,info指明程序的运行是否符合正确的业务逻辑。

对于warn与error级别,是我自己最困惑的 ?

先讲个形象的例子 :

         有一天,李三说请你帮个忙,帮他收拾一下自行车,但是他的自行车是放在他自己家里的,房屋上锁。
         1、李三:给你钥匙,此时你没有工具,但是你可以用你自家的工具修理自行车。结果:完成任务;过程:存在问题,内部可以处理此问题。
         2、李三:没给你钥匙,但给你工具或者没给你工具,此时你不能接触到自行车。结果:无法完成任务;过程:存在问题,无法处理此问题。

结论:1情况,记warn;2情况,记error。观点:关注的是最小单元的业务是否能够完成,而对于应用来说,最小单元的业务就是“method方法”,每个方法去完成的任务都是一个独立的、最小单元的业务。

提醒:必须结合具体场景来判断,比如:dao从数据库获取数据失败,对自身来说是error,没有完成获取数据的任务;但对业务层来说,或者有其它方法修复此异常,如通过http重新获取等,此时业务层是完成自身任务的,所以为warn。

warn:potentially harmful situations.(潜在的有害状态)。比如:广告投放,淘宝搜索右侧p4p广告会根据地域展现,但某次用户搜素,ip地址获取失败,可能会用默认值替代或者为空,但是并不影响右侧广告的展现。所以展现广告的任务是完成的,对于业务来说是执行成功的,尽管过程中出现问题。

error:error events that might still allow the application to continue running.(错误事件发生,程序或许依然能够运行)。比如:广告前段展现,通过http从引擎获取数据时,因为引擎的机器连接数达到上限或者临时网络原因,timeout,但程序能正常运行,next请求引擎则成功。从函数角度看,此函数任务没有完成,记error。

fatal:very severe error events that will presumably lead the application to abort.(错误可能会导致应用崩溃)。


对于日志级别,或许大家也会有自己的理解(如有不同意见,请大家指点)


二、记录信息

这个话题简单一点,三点:
1、做什么操作
2、输入内容
3、堆栈信息(有堆栈信息的情况下)


posted @ 2010-10-09 23:26 石建 | Fat Mind 阅读(1800) | 评论 (0)编辑 收藏
     摘要: 已迁往  http://fatmind.iteye.com主要参考: 1.宝宝的文章《中文化和国际化问题浅析》    2.阮一峰的网络日志       http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html  ...  阅读全文
posted @ 2010-10-05 21:12 石建 | Fat Mind 阅读(376) | 评论 (0)编辑 收藏
前话:之前看过贝叶斯的东西,想记录自己的理解。

     每个人身边发生的事情可能都是一个“概率性”事件。从抽签、买彩票,站在古典概率的角度,这些事对于每个人都是公平的,阐述不确定事件的规律性。统计概率:在一个事件空间中,进行n次的随机试验,某个事件的发生会趋于一点。这就是“大数定理”,在统计的基础上得到的结果是不是能从之前

发生的事件的规律,预测某件事之后发生的概率呢?这就是贝叶斯公式的目的。

     根据条件概率的定义。在事件B发生的条件下事件A发生的概率是:

     同样地,在事件A发生的条件下事件B发生的概率:

     整理与合并这两个方程式,我们可以找到:

     这个引理有时称作概率乘法规则。上式两边同除以P(B),若P(B)是非零的,我们可以得到贝叶斯定理:

参考资料:

http://zh.wikipedia.org/zh-cn/贝叶斯定理

http://mindhacks.cn/2008/09/21/the-magical-bayesian-method/ 平凡而又神奇的贝叶斯

posted @ 2010-07-12 23:41 石建 | Fat Mind 阅读(270) | 评论 (0)编辑 收藏
仅列出标题
共4页: 上一页 1 2 3 4 下一页 

导航

<2024年11月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

统计

常用链接

留言簿

随笔分类

随笔档案

搜索

最新评论

What 、How、Why,从细节中寻找不断的成长点