Archive for the ‘程序’ category

GroovyServlet的缺陷

August 7th, 2009

原本希望groovy能以php那种方式工作,但是现在看来不太可能。Groovy发行包里自带的TemplateServlet太弱,GroovyServlet也有致命的缺陷。

GroovyServlet使用GroovyScriptEngine(后面简称GSE)解析groovy文件,解析过程中GSE会智能的自动的到类路径中寻找被引用到的groovy类文件。如果被用作groovyServlet的文件被更新了,GSE会重新解析它,不需要重启服务器,就可以看到效果。可惜的是,如果被引用到的类路径中的其它的文件被更新了,GSE还在使用原来的文件,必须重启服务器才能看到效果,这是在是太令人失望了。据说groovy 1.7 里GSE会这方面增强,很期待呀。TemplateServlet干脆就连GSE也没有用,所以自动引用其他的groovy文件也不可能了。无论是GroovyServlet还是TemplateServlet都不能够像php那样通过include别的php文件来获得别的文件里定义的类,方法和闭包。

看开,在目前,如果不用grails,是没有什么好办法直接用groovy文件写网络程序的,只好把它编译成class文件,就像java生成的class一样来使用。很可气的是,我试用了几个IDE,eclipse, netbeans和idea,其中只有idea支持得还可以,但都是不算很好。看来groovy还有一段路要走。

  • Share/Bookmark

web服务器集群

August 3rd, 2009

什么是集群

计算机集群(以下简称集群)在维基百科上被定义为一组相互连接的计算机,紧密的工作在一起,以至于在很多方面看来,它们都像是一台机器。

集群的好处

集群可能能给我们带来很多好处,其中负载均衡(loadbalance)和故障恢复(failover)一般是最常用的。负载均衡是将系统的负载分派到集群内不同的计算机上,让每个节点都不至于太忙或太闲,通过增加集群中计算机的数量,可以提升整体的负载能力。故障恢复是指在集群中某个节点发生故障时,其它的节点代替它们继续工作,这样整个系统依旧能对外提供服务。

web服务器集群的特点

对于web服务器来说,集群就是让一组计算机对外像一台web服务器一样运行。web服务器的特点是它通过http协议与客户端交互,而http协议的工作机制是请求响应模式的。web服务器的集群要能把客户端的http请求发送到集群内各个节点上,实现loadbalance,并能探测到各节点的工作情况,在某个节点失效的时候,不再把http请求发送到该节点上。

有状态与无状态

web程序本身是否有状态对实现集群的方法和难以度有很大的影响。如果web程序和客户端交互的记录下了一些状态信息,并在处理之后的请求时需要知道这样的信息,那么这个程序就是有状态的。比如,登录功能,当用户正确登录后,web程序会记录下用户的登录状态,当用户访问其它的页面时,web程序会参照用户的登录信息做不同的处理。在实现集群的时候,有状态的程序要复杂些,因为必须保证处理请求的节点上能有该用户的状态信息。对于无状态的程序,则没有这个问题,请求被分发到任何节点都是一样的,没有额外的维护状态的工作。

为了保证处理请求的节点上能有状态信息,要么在多个节点上复制程序的状态,要么采用否种策略保证将请求正确的发送到具有相应状态的节点上。如上面的例子,要么把用户登录的信息复制到集群的所有节点上,以保证无论之后请求发送到哪个节点上,都能够找得到登录信息,要么每次都把这个用户的请求发送到同一个节点上,就像mod_jk的sticky_session那样。

多线程与多进程

php,ruby,python等脚本语言往往采用无状态的结构,而java往往采用有状态的结构。并非语言决定了它们的工作方式,更多的是一种习惯。

java web服务在运行时是一个常驻内存的进程,用不同的线程处理用户请求。当处理一个http请求的线程结束后,保留在该进程内的信息并没有消失,因为进程还在。因此,可以很方便的把一些交互信息放到java进程的内存中,在多个线程间共享。在加上又有好用的HttpSession类,这样在java ee里把用户信息保存到session中,是一件非常容易的事,程序员们也自然的就采用的,导致了java web程序成了有状态的。如果完全不用session等,java web程序也能做到无状态。

和java的单进程,多线程工作方式不同,php等脚本语言采用了多进程的工作方式。当有一个http请求到来时,web服务器开启一个新的进程,这个进程调用脚本语言的解释器来运行脚本处理请求,处理结束后进程退出。如果要在多个进程间共享信息,就得采用外部的介质,DB就成了最好的选择。

本质上来说,只要需要记录会话的状态,就肯定有状态,差别只是把状态放到什么地方。java ee里往往把它放到应用程序的内存里,而php等则往往放到db里。

  • Share/Bookmark

groovy+spring全动态web开发方案

July 14th, 2009

为什么java开发没有php容易?,我在那篇文章了提出了三点原因,利用groovy,我们能在一定程度上做到那三点,从而加快了java web的开发。jsp本身以具有不需要重启就可以生效的能力,但是没有好用的map和动态类型的能力,用在前文 用groovyServlet和TemplateServlet快速开发网页中的方法,可以通过groovy让页面具有好用的map和动态类型的能力,但是 TemplateServlet的局限性 还是很难让我们单凭在页面里编程来构建规模稍大些的应用。引入spring,利用spring对动态语言的支持,我们可以将可重用的逻辑封装到由groovy编写的spring的bean里,这样,就可以最终实现从页面到后台全groovy的效果了,让java的web开发可以达到近似于php的易用度。

看看详细的做法。
把最新版的groovy-all.jar和spring.jar以及spring所依赖的相关包放到/WEB-INF/lib/目录下。

首先,在web.xml里配置好对groovyServlet, TemplateServlet和spring的支持

代码如下:

  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/applicationContext.xml</param-value>
  </context-param>
   
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
 
  <servlet>
    <servlet-name>groovlet</servlet-name>
    <servlet-class>groovy.servlet.GroovyServlet</servlet-class>
  </servlet>
 
  <servlet>
    <servlet-name>gsp</servlet-name>
    <servlet-class>groovy.servlet.TemplateServlet</servlet-class>
  </servlet>
 
  <servlet-mapping>
    <servlet-name>groovlet</servlet-name>
    <url-pattern>*.groovy</url-pattern>
  </servlet-mapping>  
 
  <servlet-mapping>
    <servlet-name>gsp</servlet-name>
    <url-pattern>*.gsp</url-pattern>
  </servlet-mapping>

然后,配置用groovy写spring的bean

如果你要写一个id为foo的bean, 那么要先用java写一个接口,然后用groovy写Bean实现接口,这样不但可以让你以后可以更容易用java重写groovy的bean,也可以避免和spring aop的冲突。

interface Foo.java 代码:

public interface Foo {
    public String shout(String name);
}

groovy实现类 FooImpl.groovy代码:

public class FooImpl implements Foo {
    def sampleProp
    public String shout(String name) {
        def c = {"Groovy : ${sampleProp} ${it}"}
        return c(name)
    }
}

然后在applicationContext中配置

    <lang:groovy id="foo" refresh-check-delay="5000" script-source="classpath:FooImpl.groovy">
        <lang:property name="sampleProp" value="Hello" />
    </lang:groovy>

注意上面的refresh-check-delay=”5000″是让spring每过五秒钟就刷新一下groovy代码,重新编译,当最终部署的时候,可以把它去掉,这样就不会重复刷新了。但是在开发时,我们因此获得了不重启就生效能里。

最后,可以在页面groovy文件中使用这个bean了

使用这个bean和使用其他的spring bean没有什么区别。

import org.springframework.web.context.support.WebApplicationContextUtils;

def spring = WebApplicationContextUtils.getWebApplicationContext(context)
Foo foo = spring.getBean("foo")
foo.shout("sulong")

只要不修改applicationConfig.xml,修改其他的部分都不需要重启或重新部署,这样,你可以通过groovy和spring来达到类似于php那种快速开发的目的。并且在后期,如果有必要,你还可以通过用java重写的bean的方式,来做性能优化。

  • Share/Bookmark

TemplateServlet的局限性

July 10th, 2009

我想利用TemplateServlet,像使用php那样使用groovy。只要设置好了,就可以在web目录下写gsp文件,就像写php那样,即时写即时看到效果。

但是我错了,目前的TemplateServlet非常简陋,远不能达到要求。问题主要发生在include功能。php的inclue require等功能,可以把页面变成方法库,或类库,但是在TemplateServlet的gsp里不行。我无法访问被包含的页面里的方法,闭包等。想想也很自然,每个gsp文件都有自己的名称空间。

另外,不能在gsp里定义类,这个太伤了~~~

如果能解决以上两个问题,TemplateServlet就可以让groovy像php那样使用了。唉,那些做grails的家伙真的应该先把这块搞好,再搞重量级的东西,毕竟不是所有人都想用spring hibernate的。

看了看gails的roadmap,今年9月的1.2版本里将有standalone gsp module,那是真正的gsp,而不是现在的简单的TemplateServlet。Grails里的gsp支持页面片段和非常方便的自定义标签,前者便于共享页面展示,后者便于共享页面行为,那么处理页面的是什么呢?还要写controller吗?到时候看吧,还是很令人期待的。

  • Share/Bookmark