Java技术
1.完整描述SOA架构
1.1 什么是web服务(web service)
Web 服务是一个软件接口,它描述了一组可以在网络上通过标准化的 XML 消息传递访问的操作.
Web Service 最基本的组成部分为服务的提供者(Service Provider)和服务的请求者(Service Requester),这两端痛过XML格式进行通信。
1.2 Web服务三要素
WSDL:用于用于描述和定位网络服务。WSDL中主要有如下元素,
<portType> 是最重要的一个元素,用来描述web服务支持的操作及相关信息。可以把该元素比作传统编程语言中的一个函数库(或一个模块、或一个类),而把每个操作比作传统编程语言中的一个函数。
<message> 用来定义一个操作(函数)的具体调用格式(函数名,参数名等等)
<portType>代码片段:

1 <message name="getTermRequest"> 2 <part name="term" type="xs:string"/> 3 </message> 4 5 <message name="getTermResponse"> 6 <part name="value" type="xs:string"/> 7 </message> 8 9 <portType name="glossaryTerms"> 10 <operation name="getTerm"> 11 <input message="getTermRequest"/> 12 <output message="getTermResponse"/> 13 </operation> 14 </portType>
<binding> 描述要使用哪种方式将上面的端口<portType>进行绑定,一般可以绑定到SOA。
如果是绑定到SOA,则需要在<binding>使用<soap:binding>子标签中使用定义SOAP协议内容。
在<soap:binding>中,通过style属性指定rpc或者document, 通过transport 定义了要使用的 SOAP 协议(例如http),在<operator>则定义了每个端口提供的操作符。
一个<binding>代码片段:

1 <message name="getTermRequest"> 2 <part name="term" type="xs:string" /> 3 </message> 4 5 <message name="getTermResponse"> 6 <part name="value" type="xs:string" /> 7 </message> 8 9 <portType name="glossaryTerms"> 10 <operation name="getTerm"> 11 <input message="getTermRequest" /> 12 <output message="getTermResponse" /> 13 </operation> 14 </portType> 15 16 <binding type="glossaryTerms" name="b1"> 17 <soap:binding style="document" 18 transport="http://schemas.xmlsoap.org/soap/http" /> 19 <operation> 20 <soap:operation 21 soapAction="http://example.com/getTerm" /> 22 <input> 23 <soap:body use="literal" /> 24 </input> 25 <output> 26 <soap:body use="literal" /> 27 </output> 28 </operation> 29 </binding>
UDDI(Universal Description, Discovery and Integration)即“通用描述、发现与集成服, 是一种目录服务,企业可以使用它对 Web services 进行注册和搜索
1.3 SOAP
按照 Web Service 的相关标准描述,服务的提供者应该首先通过 WSDL(Web Service Definition Language)和 UDDI (Universal Description, Discovery, and Integration)发布它所提供的服务到一个统注册这些服务信息的存储库中去。这样,服务的请求者就也可以通过 WSDL 和 UDDI 发现到服务提供者提供的服务,并可以通过应用的调用方法来使用这个服务了。
SOA的重点在于集成,重用,分布式。
面向服务的体系结构(Service-Oriented Architecture,SOA)是一种 IT 体系结构风格,支持将您的业务转换为一组相互链接的服务或可重复业务任务,可在需要时通过网络访问这些服务和任务。
SOA 描述了服务的整个系统如何动态地相互查找,如何聚集在一起执行某些应用程序,以及如何按照多种方式进行组合。该模型鼓励技术和软件的重用,以及使用SOA模型实现分布式系统。
2.设计秒杀,考虑分布式事务和数据库连接数限制, 说明应用程序级别的分布式事务控制。
优化方向:
a.将请求尽量拦截在系统上游。
主要是为了不要让锁冲突落到数据库上面去。
这里需要在各个层次进行优化。
第一层是在客户端优化,例如对浏览器,APP等,不应该将每一次提交都真正提交到应用程序,而是应该设置一些防作弊机制,拦截部分请求(例如提交完button就变灰,5分钟才能提交一次等等)
第二层是在MVC层或者业务层,如果有攻击者拥有大量动态IP进行for循环秒杀,应该按UID进行有效识别和拦截。但是如果攻击者拥有大量肉鸡(即,不仅有动态IP,而且有不同UID),用UID过滤就不起作用了。
第三层是在服务层拦截,对于上面挟持肉鸡的攻击是看作正常用户的,这里不讨论攻击,只讨论拦截,对于这种大访问量,在服务层可以用队列进行串行化访问(分批),根据商品存量每次放出适当访问请求就能有效控制服务层压力。
对于第三层,可以用来确保写请求不超过数据库的连接限制。
第四层是利用缓存缓解读请求(秒杀基本都是读多写少),让大部分请求都能读到混存,能有效缓解数据库压力。
第五层是异步操作,抢票成功后的付款采用异步方式返回。
通过上面一些列优化之后,能够有效控制真正读和写数据库的请求数量。当然也可以在业务规则层面先进行优化,例如12306分时分段售票。。。而此时对于数据库来说,因为前面的大量工作拦截了大量请求,数据库的压力可以控制在安全范围进行事务操作了。
3.设计单点登录,说明令牌生成机制及安全保障
单点登录的一般设计思路是,使用统一授权模块生成token,写入客户端cookie,客户端在登录其他子站点时,将包含token的cookie发送至子站点,子站点再与统一授权模块校验合法性,合法则在子站点为用户生成session表明授权成功,进行后续操作。
基于这种方式实现的单点登录,cookie的安全性是一个很大问题。
有的系统会设计预登录方式,即用户第一次通过统一模块进行授权时,如果授权通过,统一模块再强制将客户端重定向到各个子站点,即预先登录各个子站点,各个子站点都会写入session。
预登录不仅可以简化客户端登陆流程,而且安全性更高,因为预登录的时候,用的是统一模块第一次发给客户端的原始session-cookie在各个子站点进行授权(写session),而不是各个子站点临时为客户端生成的session-cookie,
统一授权模块在第一次发送sesion-cookie给客户端的时候,完全可以在cookie中加入服务器端特有信息,达到难以伪造的目的,同时通过SSL通道进行cookie传输,保证cookie不会被拦截偷取。
另外,采用预登录的方式,如果一个用户已经登录,则在各个子站点存在session[hash(uid+timestame+服务器数字签名),],且在数据库中也是登录状态。如果此时有人伪造用户id和cookie去登录,由于伪造的cookie与统一授权模块分配的session-cookie并不相同,那么各个子站点就不会存在这个session[hash(uid+timestame+服务器数字签名)],然而数据库却显示此用户一登陆,那么此时可以判断次用户异常(有恶意破解嫌疑)。
另外,即使hash(uid+timestame+服务器数字签名),即使被盗取,也无法篡改,这是数字签名的特征,基于这一点,让timestame尽快失效可以提高安全性。
签名过程
“发送报文时,发送方用一个哈希函数从报文文本中生成报文摘要,然后用自己的私人密钥对这个摘要进行加密,这个加密后的摘要将作为报文的数字签名和报文一起发送给接收方,接收方首先用与发送方一样的哈希函数从接收到的原始报文中计算出报文摘要,接着再用发送方的公用密钥来对报文附加的数字签名进行解密,如果这两个摘要相同、那么接收方就能确认该数字签名是发送方的。
数字签名有两种功效:一是能确定消息确实是由发送方签名并发出来的,因为别人假冒不了发送方的签名。二是数字签名能确定消息的完整性。因为数字签名的特点是它代表了文件的特征,文件如果发生改变,数字摘要的值也将发生变化。不同的文件将得到不同的数字摘要。 一次数字签名涉及到一个哈希函数、发送者的公钥、发送者的私钥。”
关于数字签名和数字证书,可以参考 http://justjavac.iteye.com/blog/1144151
算法
1. 树的按层次遍历
思路,用一个FIFO队列辅助,初始状态是将树的根节点放进队列,
然后进行循环操作,跳出条件是队列是否为空。
每次从队列弹出(poll())一个元素,首先打印出这个节点,然后判断是否有左孩子,如果有就将左孩子入队列,接着判断是否有右孩子,如果有也入队列,如此循环,当队列为空的时候,也就完成了层次遍历。
1 public void levelTravel() { 2 LinkedList<Node> queul = new LinkedList<>(); 3 queul.push(root); 4 while (!queul.isEmpty()) { 5 Node tmpNode = queul.poll(); 6 System.out.print(tmpNode.value+"#"); 7 if(tmpNode.left != null) { 8 queul.push(tmpNode.left); 9 } 10 if(tmpNode.right != null) { 11 queul.push(tmpNode.right); 12 } 13 } 14 }
2. 单链表,在不知道前一个节点地址的情况(但是知道后一个节点),如何删除后一个节点。
把将要删除节点的内存数据直接拷贝到后一个节点位置,然后释放内存。
3.0~999,如何用数学方法快速计算有多少个数字里含有7
1+10+9+100+90+90 = 300