新浪微博短URL的意义和实现

作者 : admin 于 2010年01月03日, 00:40:59
2010
01-3

新浪微博,就是迷你博客(废话)。我关心的不是博客,是url。里边的url全部使用了一种很短的url,比如 http://sinaurl.cn/**** 这里猜测了这种url的实现意义:

1:减少url所占的字数,优化排版。微博就是一个小,如果我贴了一个地址就占一半的字数,那作者很不爽,读者很不爽,做页面那哥们(MM)肯定跟不爽。所以,咱弄个短的url,岂不皆大欢喜。

2:排挤灌水广告者。众所周知,很多广告者为了广告,或者为了页面优化,得群发垃圾消息增加反向链接数。而短url跳转这种方式根本无法增加反向链接数。也就是这种方式从根本上掐断了垃圾群发者的命根子,这样也就减少了垃圾信息的量,节约了信息审核的人工成本(这项成本随着严打是越来越高啊)。

3:暂时没想出来。

实现,其实很简单,就是接收个id,然后找到对应记录就行。根据新浪信息的量,不可能用mysql的,成本高(负载和硬件消耗)。不可能用oracle,凭我的了解,不可能用。

新浪在小日本那个ttserver的基础上开发了个支持分布式的key->value型的数据库,这玩意正好用上,支持高并发大负载,逻辑简单还支持分布式,这么实现貌似最好不过。

吃饱没事,大半夜写文章。欢迎大家来讨论。

单点登录sso粗解+示例

作者 : admin 于 2009年12月31日, 10:56:46
2009
12-31

用户中心代码 sso
跨域测试脚本 cookie

单点登录,英语为 Single Sign-On,粗俗点讲,就是登录一次,全站适用。

单点登录在应用中的实际意义,就是减少开发量,增强用户体验。

减少开发量,指的是:只要开发一套用户系统, 各个系统统一调用。用户系统尽量优化接口,通用性,安全性,达到一次开发, 全站适用。

增强用户体验,指的是:用户一次登录,全站登录。而不是切换一个模块,就登录一次。

web方面单点登录主要是用cookie传递令牌进行身份认证。简单说下令牌。

我这里用散列值来作为令牌,当然散列值之中有我的的密钥,防止别人伪造我的令牌。

环境:sso.sunboyu.cn 用户中心 vps.sunboyu.cn/cookie.php 跨子域不同脚本访问测试。 令牌密钥: $key

具体规则: sso.sunboyu.cn 用户登录,登录信息写到cookie,cookie做用域为 sunboyu.cn。并且生成令牌sso_key=md5(uid+username+key)。

登陆后,其他子域站点调用此cookie信息,并且验证此令牌是否是合法的令牌,if( md5( cookie[uid]+cookie[username] )==cookie[key] )

这样既可判断,此令牌合法性而确认此用户为登录。

具体demo:http://sso.sunboyu.cn

延伸:一个简单的md5似乎很容易让别人猜解加密的算法,来暴力一翻也不是没有可能,因此,除了加密外,算法的安全性和密钥的安全性也是需要考虑的。

如果安全级别要求高之又高,可以考虑rsa算法,不过速度就是问题了。其中又参考了一些朋友的意见,用对称加密,比如php中的Mcrypt 函数。

扩展开发:对于大多数网站,跨子域的单点登录就能满足应用。但对于一些域名复杂的网站,比如sohu,显然多个域名不能用此方法实现。这时就得搞出跨跨的单点登录系统。等年后继续得瑟。

使用无模式数据库来改造dz的session

作者 : admin 于 2009年12月29日, 09:26:58
2009
12-29

前两天还不知道啥是无模式数据库,不过最近迫切需要修改discuz bbs的session表,所以研究了一下相关的资料,发现了无模式这个名字。

具体无模式是啥,这里找了两篇文章:

关系数据库的末日是否已经来临
关系数据库的根本问题分析及数据库革命之走向

关于无模式的应用案例,很典型的一个,就是康盛uchome的feed表。

这里简单介绍几个无模式数据库,供大家参考:

mongodb : http://www.mongodb.org/display/DOCS/Home

mongodb的php扩展 http://www.mongodb.org/display/DOCS/Installing+the+PHP+Driver#InstallingthePHPDriver-PECL

这个数据库已经在淘宝上配合10gen做了云计算的session(名字很操蛋),具体资料在这里 http://rdc.taobao.com/blog/dw/archives/410。具有了实际应用的东西应该很不错,不过我没尝试过。

Tokyo Tyrant:http://1978th.net/

tt的php扩展 http://www.php.net/manual/en/book.tokyo-tyrant.php

这个大家就比较熟悉了,SB日本鬼子写的东西,应用很广,sina,qq等公司里都在大量应用,sina的研发团队在此基础上还做了个分布式的东东,很是不错。据说这玩意还得到了很多公司的赞助,shit。

TCSQL:张宴基于tt开发的一套东西,内部做了很多算法优化,具体可参考此文章 http://blog.s135.com/tcsql/

总结:康盛使用mysql来存储session,不能说是一种错,但对于dz的负载绝对是第一个瓶颈。用这种方式,在线人数5w对数据库绝对是个坎。很多负载比较大的论坛,都做了此方面的优化,比如,给session表单独一个数据库,或者干脆阉割此功能。不错,独立的session表,或者分库,访问量大的时候,瓶颈依然在mysql上;阉割此功能,有些心疼,而且很多运营数据会丢失。所以,保持原功能而平滑提升性能,是一个不错的解决方向。

改变exec的阻塞模式

作者 : admin 于 2009年12月25日, 10:19:41
2009
12-25

很多操作时间会很长,不能让用户在页面上执行PHP脚本,否则页面会被拖死。

一个不错的方案,就是提交到后台去执行。

linux有个命令 nohup command & 这样就会提交到后台,而终端的用户体会不到程序执行的过程。

原来我使用这种方式 shell_exec( “nohuo php file.php &” ) 进行后台提交,后来发现速度依然不快, 还是被挂起了。查看手册,exec函数有如下提示:

Note: 如果用本函数启动一个程序并希望保持在后台运行,必须确保该程序的输出被重定向到一个文件或者其它输出流去,否则 PHP 会在程序执行结束前挂起。

因此,这样修改就达到了目的:

exec( “nohuo php file.php >> /dev/null &” )

康盛,这么做是不是有点过火了-2

作者 : admin 于 2009年12月24日, 20:15:57
2009
12-24

自打上篇文章 康盛,这么做是不是有点过火了发表后,引起很多朋友讨论。有些朋友从技术上抨击了这种做法,有些朋友从商业上去理解这种做法。当然,我们是搞技术的,单纯从程序安全和数据安全上来分析一下。

老样子,后台有个get提交:
http://u.discuz.net/customer/update.php?get=a%3A16%3A%7Bs%3A7%3A%22sitekey%22%3Bs%3A16%3A%22f270e28a8b0Qv1Y8%22%3Bs%3A7%3A%22version%22%3Bs%3A3%3A%222.0%22%3Bs%3A7%3A%22release%22%3Bs%3A8%3A%2220090825%22%3Bs%3A3%3A%22php%22%3Bs%3A5%3A%225.2.6%22%3Bs%3A5%3A%22mysql%22%3Bs%3A6%3A%225.0.22%22%3Bs%3A6%3A%22dbsize%22%3Bi%3A1298163%3Bs%3A7%3A%22charset%22%3Bs%3A5%3A%22utf-8%22%3Bs%3A8%3A%22sitename%22%3Bs%3A12%3A%22%E6%88%91%E7%9A%84%E7%A9%BA%E9%97%B4%22%3Bs%3A7%3A%22feednum%22%3Bs%3A2%3A%2210%22%3Bs%3A7%3A%22blognum%22%3Bs%3A1%3A%220%22%3Bs%3A8%3A%22albumnum%22%3Bs%3A1%3A%220%22%3Bs%3A9%3A%22threadnum%22%3Bs%3A1%3A%220%22%3Bs%3A8%3A%22sharenum%22%3Bs%3A1%3A%220%22%3Bs%3A10%3A%22commentnum%22%3Bs%3A1%3A%220%22%3Bs%3A8%3A%22myappnum%22%3Bs%3A1%3A%224%22%3Bs%3A8%3A%22spacenum%22%3Bs%3A1%3A%223%22%3B%7D&h=aa380aa3

urldecode并且反序列化,得出这么一堆东西

  1. Array
  2. (
  3.     [sitekey] => f270e28a8b0Qv1Y8
  4.     [version] => 2.0
  5.     [release] => 20090825
  6.     [php] => 5.2.6
  7.     [mysql] => 5.0.22
  8.     [dbsize] => 1298163
  9.     [charset] => utf-8
  10.     [sitename] => 我的空间
  11.     [feednum] => 10
  12.     [blognum] => 0
  13.     [albumnum] => 0
  14.     [threadnum] => 0
  15.     [sharenum] => 0
  16.     [commentnum] => 0
  17.     [myappnum] => 4
  18.     [spacenum] => 3
  19. )

sitekey是什么?通过阅读代码,sitekey是pre_config表里一个字段,跟以下代码配合工作

  1. $hash = $_SCONFIG['my_siteid'].'|'.$_SGLOBAL['supe_uid'].'|'.$appid.'|'.$current_url.'|'.$extra.'|'.$timestamp.'|'.$_SCONFIG['my_sitekey'];

它跟manyou服务器配合,才有权从你的服务器上拉取你数据库中的某些信息。

其他字段,我们看字面意思基本也能知道是干啥用的。

继续运行程序,我们看当一个用户第一次安装应用的时候做了什么。

这个信息要从服务器上截取,我是根据nginx日志和程序中截取反馈信息获得的。

服务器日志:

  1. 124.238.249.171 - - [24/Dec/2009:20:02:40 +0800] "POST /uhome/api/my.php HTTP/1.0" 200 192 "-" "myop/1.0" "-"

manyou服务器发来post请求。post信息不会在日志里,底下是我抓取来的信息:

  1. [post] => Array
  2.                 (
  3.                     [module] => Users
  4.                     [method] => getInfo
  5.                     [sign] => 271ce9942c94fc4f4d39445e133105bc
  6.                     [params] => a:1:{s:4:\"uIds\";a:1:{i:0;s:1:\"3\";}}
  7.                 )

做过sns网站应用开发的应该很容易看懂底大概是什么意思。
看看我们的程序给manyou平台返回了什么信息:

  1. [result] => Array
  2.                 (
  3.                     [0] => Array
  4.                         (
  5.                             [uId] => 3
  6.                             [handle] => sunboyu1
  7.                             [action] =>
  8.                             [realName] =>
  9.                             [realNameChecked] =>
  10.                             [gender] => unknown
  11.                             [email] => dfafdasf@123.fdsafds
  12.                             [qq] =>
  13.                             [msn] =>
  14.                             [birthday] => 0000-00-00
  15.                             [bloodType] => unknown
  16.                             [relationshipStatus] => unknown
  17.                             [birthProvince] =>
  18.                             [birthCity] =>
  19.                             [resideProvince] =>
  20.                             [resideCity] =>
  21.                             [viewNum] => 0
  22.                             [friendNum] => 0
  23.                             [myStatus] =>
  24.                             [lastActivity] => 0
  25.                             [created] => 1261655045
  26.                             [credit] => 25
  27.                             [isUploadAvatar] =>
  28.                             [adminLevel] => none
  29.                             [homepagePrivacy] => public
  30.                             [profilePrivacyList] => Array
  31.                                 (
  32.                                 )
  33.  
  34.                             [friendListPrivacy] => public
  35.                         )
  36.  
  37.                 )
  38.  
  39.             [mode] =>

有了这些数据,我又注册了一个号码,把资料填全,看看是不是都被抓走:

  1. [result] => Array
  2.                 (
  3.                     [totalNum] => 0
  4.                     [friends] => Array
  5.                         (
  6.                         )
  7.  
  8.                     [me] => Array
  9.                         (
  10.                             [uId] => 4
  11.                             [handle] => sunboyu2
  12.                             [action] =>
  13.                             [realName] => 一个程序猿
  14.                             [realNameChecked] => 1
  15.                             [gender] => male
  16.                             [email] => 1231231@fdsfdsa.com
  17.                             [qq] => 176300676
  18.                             [msn] => sunboyu@gmail.com
  19.                             [birthday] => 2004-02-01
  20.                             [bloodType] => B
  21.                             [relationshipStatus] => single
  22.                             [birthProvince] => 北京
  23.                             [birthCity] => 东城
  24.                             [resideProvince] => 黑龙江
  25.                             [resideCity] => 佳木斯
  26.                             [viewNum] => 0
  27.                             [friendNum] => 0
  28.                             [myStatus] =>
  29.                             [lastActivity] => 1261657227
  30.                             [created] => 1261657100
  31.                             [credit] => 40
  32.                             [isUploadAvatar] => 1
  33.                             [adminLevel] => none
  34.                             [homepagePrivacy] => friends
  35.                             [profilePrivacyList] => Array
  36.                                 (
  37.                                     [relationshipStatus] => friends
  38.                                     [birthday] => friends
  39.                                     [bloodType] => me
  40.                                     [birthPlace] => public
  41.                                     [residePlace] => public
  42.                                     [qq] => me
  43.                                     [mobile] => public
  44.                                     [msn] => public
  45.                                 )
  46.  
  47.                             [friendListPrivacy] => me
  48.                         )
  49.  
  50.                 )
  51.  
  52.             [mode] =>
  53.         )

差不多基本资料都过去了。

这样,可以看出,康盛的服务器不断得在抓取用户的信息。这个事情是不是过火,从商业的角度,是应该很过火的。他把用户产品内的账号信息等关键东西都抓走,这些信息到他们手里,难免会交易给竞争对手。
但是,从技术上讲,康盛的manyou服务器还有个缓存的功能。如果拉取用户信息这个请求都放在网站的服务器上,我相信大多数虚拟主机的用户会不堪重负,而康盛其实为这些负载买单了。买单的结果,就是你得把用户的信息提供给康盛。就这么简单。

从程序安全上讲,你的数据库信息,尤其用户信息,在你的网站和manyou之间共享,而康盛没有拉走用户或者管理员资料,也没有发现其他信息的提取,所以,两者之间是安全的。第三方网站是无法获得这些资料的。

但从商业安全上讲,康盛的服务器是否可信?康盛是否会拿这些信息作一些站长不希望做的事情?这个只能由官方来解释了。

睡一觉,研究其他产品去。

企业的效率,谁是榜样

作者 : admin 于 2009年12月21日, 20:42:23
2009
12-21

想到这个话题,还得从我的医保蓝本说起。

医保这东西,是员工就应该有。当然,我也得有。可我经历了三年多才拿到。

第一个公司,就是我刚来北京任职的公司,创业公司,吃够了苦,最后离开的时候,我两手空空,老板同意为我上保险,直到下一个公司开始为我上为止。

不过老板的确很仁义,为了上了几个月的保险,等我得知我上的是农民工那种集体户的标准的时候,已经不是气愤,变成了羞辱。当然,我也有个编号,仅是编号证明。第二个公司按照正常员工的标准给上了,不过那个编号始终没有变成一个蓝本。人力让我找原单位,原单位让我找现单位,热线电话让我找劳动局,劳动局让我找现在会计去办理即可。我的弱点就是不坚强,我妥协放弃了。农民工没啥,该咋过咋过。

到第三个公司,也就是现在的公司,入职后又提起了这事,人力惊讶,居然没蓝本,我详细解释了整个过程,人力无语。问之:能办否;答曰:申请一下。上午十一点问完,下午一点把一个崭新的蓝本送到了我的手里。我怀疑劳动局在我们楼里。

当要求别人尽职、效率的时候,首先问问自己做到没。效率是生命,不仅指的是员工,而是指整个队伍的效率。

nginx做反向代理的配置

作者 : admin 于 2009年12月16日, 18:39:13
2009
12-16

感谢铎哥的配置,感谢宴哥解决ssl连接的问题。

  1. server
  2.  {
  3.         listen      8181;
  4.         resolver 202.96.64.68;
  5.         location /
  6.         {
  7.             proxy_pass http://$http_host$request_uri;
  8.             proxy_redirect          off;
  9.             proxy_set_header        Host            $host;
  10.             proxy_set_header        X-Real-IP       $remote_addr;
  11.             proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
  12.             client_max_body_size    10m;
  13.             client_body_buffer_size 128k;
  14.             proxy_connect_timeout   90;
  15.             proxy_send_timeout      90;
  16.             proxy_read_timeout      90;
  17.             proxy_buffers           32 4k;
  18.         }
  19.         access_log /home/proxy.log;
  20.  }

django进程管理器

作者 : admin 于 2009年12月16日, 16:42:49
2009
12-16

nginx+php,php有个进程管理器,为php-fpm,Django没有,网上大概看了看,找出了几段,小改一下,能用了。

  1. #!/bin/bash
  2. siteroot="/home/project/sun"
  3. sitename="http://python.sunboyu.cn"
  4. cd $siteroot
  5. if [ $# -lt 1 ];then
  6.     echo "Usages: server.sh [start|stop|restart]"
  7.     exit 0
  8. fi
  9.  
  10. if [ $1 = start ];then
  11.     isrun=`ps aux|grep "manage.py runfcgi"|grep -v "grep"|wc -l`
  12.     if [ $isrun -eq 1 ];then
  13.         echo $sitename" has running!"
  14.         exit 0
  15.     else
  16.         python manage.py runfcgi method=threaded host=127.0.0.1 port=8000 --settings=settings
  17.         echo $sitename"is running!!"
  18.     fi
  19. elif [ $1 = stop ];then
  20.     djid=`ps aux|grep "manage.py runfcgi"|grep -v "grep"|awk '{print $2}'`
  21.     kill -9 $djid
  22.     echo $sitename" is stop!"
  23. elif [ $1 = restart ];then
  24.     djid=`ps aux|grep "manage.py runfcgi"|grep -v "grep"|awk '{print $2}'`
  25.     kill -9 $djid
  26.     echo $sitename" is stop!!"
  27.     python manage.py runfcgi method=threaded host=127.0.0.1 port=8000 --settings=settings
  28.     echo $sitename" is start!!"
  29. else
  30.     echo "Usages: server.sh [start|stop|restart]"
  31. fi

django+nginx的部分配置

作者 : admin 于 2009年12月16日, 11:26:55
2009
12-16

nginx的配置,特别感谢爱词霸吕同学,发扬了开源共享的精神,大大缩短了我的调试成本。

  1. server {
  2.     listen 80;
  3.     server_name python.sunboyu.cn;
  4.     location / {
  5.           fastcgi_pass 127.0.0.1:8000;
  6.           fastcgi_buffers      16  128k;
  7.           fastcgi_ignore_client_abort  on;
  8.           fastcgi_read_timeout 60;
  9.  
  10.           fastcgi_param PATH_INFO $fastcgi_script_name;
  11.           fastcgi_param REQUEST_METHOD $request_method;
  12.           fastcgi_param QUERY_STRING $query_string;
  13.           fastcgi_param CONTENT_TYPE $content_type;
  14.           fastcgi_param CONTENT_LENGTH $content_length;
  15.           fastcgi_param SERVER_PROTOCOL  $server_protocol;
  16.           fastcgi_param SERVER_PORT      $server_port;
  17.           fastcgi_param SERVER_NAME  $server_name;
  18.  
  19.           fastcgi_pass_header Authorization;
  20.           fastcgi_intercept_errors off;
  21.  
  22.     }
  23. }

同时附上一个额外的文档,nginx变量跟cgi协议的对应关系。
注:在配置中,并不是所有的变量必须加上,而是根据环境选择其中应该有的变量,至于具体加哪些变量,得求助高人了。

  1. #    Fast CGI param reference
  2. #    fastcgi_param    SCRIPT_FILENAME  $document_root$fastcgi_script_name;
  3. #    fastcgi_param    QUERY_STRING  $query_string;
  4. #    fastcgi_param    REQUEST_METHOD  $request_method;
  5. #    fastcgi_param    CONTENT_TYPE  $content_type;
  6. #    fastcgi_param    CONTENT_LENGTH  $content_length;
  7. #    fastcgi_param    GATEWAY_INTERFACE  CGI/1.1;
  8. #    fastcgi_param    SERVER_SOFTWARE  nginx;
  9. #    fastcgi_param    SCRIPT_NAME  $fastcgi_script_name;
  10. #    fastcgi_param    REQUEST_URI  $request_uri;
  11. #    fastcgi_param    DOCUMENT_URI  $document_uri;
  12. #    fastcgi_param    DOCUMENT_ROOT  $document_root;
  13. #    fastcgi_param    SERVER_PROTOCOL  $server_protocol;
  14. #    fastcgi_param    REMOTE_ADDR  $remote_addr;
  15. #    fastcgi_param    REMOTE_PORT  $remote_port;
  16. #    fastcgi_param    SERVER_ADDR  $server_addr;
  17. #    fastcgi_param    SERVER_PORT  $server_port;
  18. #    fastcgi_param    SERVER_NAME  $server_name;

django笔记3-DEMO篇

作者 : admin 于 2009年12月15日, 21:06:11
2009
12-15

1、创建一个project(可理解为站点)

django-admin.py startproject project1

发现新建了一个文件夹 project1

2、创建一个app(可理解为一个……)

python manage.py app1

发现多了一个文件夹 app1

3 、vi ./app1/views.py 增加代码

  1. from django.http import HttpResponse
  2. def index(self,request):
  3.     return HttpResponse('hello test')

4、vi ./urls.py 增加代码
( r’^tests/’ , ‘project1.app1.views.index’ ),

5、启动服务

python manage.py runserver domain.com:8000

然后在浏览器打 domain.com:8000/tests

如果能看到 hello test则证明配置成功。

如果不成功,看debug信息吧,debug默认是开启的。

另外我自己配置使用fastcgi方式运行python,python manage.py runfcgi host=127.0.0.1 port=8000,然后用nginx代理访问。两种方式还有所不同,具体的不同点暂时还不知道,希望知道这些差别的大大们多加提示,继续研究中。

 Page 2 of 43 « 1  2  3  4  5 » ...  Last »