What is Playframework
Playframework是一个基于JVM进行Java和Scala的WEB开发的全栈式开发框架,里面集成了许多开发模式的最佳实践,以及当下流行的开发技术。
对高可扩展性的应用,Play提供了可控的最小化的资源消耗(CPU, memory, threads)
Why is Playframework
以下是我对框架优势的总结
- 对程序员更加友好
- 开发流程的改变:不需要重新编译再启动服务。取而代之的,只需要更改代码后刷新页面,框架会自动做这些事情
- 强大的命令行,新建工程、编译、运行、测试、打包、发布等常用功能都有对应的命令来执行。
- 以上两点也意味着,框架装好后,只需要一个编辑器就可以开工了。(对于eclipse等IDE框架支持但不是必须)
- 性能
- play内在就是一个异步的框架,它会异步的非阻塞的处理所有请求(NIO基于netty、异步模型建立于akka之上)。无阻塞和异步解决了并发数目的瓶颈,最大化发挥系统的能力,也可以更好的计划后续的扩展。
- 无论是选用Java还是Scala,都运行于JVM之上,可靠且稳定
How to use
安装
- 下载 :http://downloads.typesafe.com/play/2.2.3/play-2.2.3.zip
- 安装:解压后 将play加入环境变量
first app
- 命令行模式下输入 play new youappname, 然后再选择一下语言,工程就创建好了
- 切换目录到你的工程所在,输入play,会弹出play的交互式命令行,输入run启动工程,run [port]指定端口,默认是9000.启动后在浏览器中输入localhost:9000,可以看到欢迎页面
- 如果你用的eclipse,在命令行执行:eclipse,创建工程文件
- 打开工程,我们来浏览一下工程的结构
- app/:包含应用的核心代码,内部拆分为models、controllers、views三个目录,这里是放置源码的地方
- conf/: 包含应用所有的配置文件,特别是主配置文件application.conf、路由定义文件、和国际化文件
- project/: 包含构建脚本,构建系统基于sbt
- public/ :包含所有公开资源,包括js,样式和图片的目录。
- test/ :包含测试代码
- 添加自己的请求和action:
- 在conf下的route 添加对应路由,配置到自己的action
- 实现这个action
Why play is highly-scalable
Play从上到下都是异步的,使用iteratees异步的处理流。因为play的核心从不阻塞,相对于传统的web框架线程池被调整的很小。 因此,如果你打算写一些阻塞IO的代码,或是CPU密集型的处理代码,你需要知道是哪个线程池在承受运行压力,然后相应的调整它。做阻塞IO的时候不去考虑这些很可能导致Play框架的性能非常低下。例如:每秒只能处理很少的请求,CPU却只用了5%。对应的,如果调整得当,在普通硬件(比如MACPRO)条件下的测试表明Play可以毫不费力的每秒钟处理成百上千次请求。
注意:以下类型的IO是完全不会阻塞的 (意味着没有任何线程在阻塞等待)
- The Play WS API:Play内置的webservice调用lib
- 异步的数据库驱动如ReactiveMongo
- 从Akka的actor中发送、收取消息
- Play 的线程池
Play使用不同的线程池实现不同的目的:
- Netty boss/worker thread pools - 这些线程是Netty用来处理Netty IO的,应用代码不可以使用此线程池中的线程执行代码。
- Play Internal Thread Pool - 这是Play内部的线程池,线程数量默认与可用处理器数量相同,可在application.conf中配置这个数量。同上,不要用它。
- Play default thread pool - 这是所有应用代码执行时默认使用的线程池,它是Akka调度的,可以通过配置Akka的方式来配置它。默认每个处理器一个线程。
- Akka thread pool - 这是Play的Akka插件使用的,可以通过配置Akka的方式配置它。
针对不同的需求的常见配置如下:
- 纯异步的
- 意味着每个操作都没有阻塞的情形发生,使用默认的配置就可以了
- 高同步的
- 如果你的大部分action都是阻塞IO(比如读数据库),这种情况下,Play与传统的web框架差不多,需要大量的线程处理阻塞,所以得把默认使用的线程池调大
- 指定多个线程池
- 同上,大部分action都是阻塞的,但你想要控制同一时刻系统执行哪部分action多一些,哪部分action少一些,你可以配置多个线程池,并制定他们的权重。