- 浏览: 497364 次
- 性别:
- 来自: 深圳
文章分类
- 全部博客 (200)
- java基础 (30)
- ajax (19)
- 乱写 (5)
- groovy (2)
- db (8)
- gwt (0)
- jee (2)
- 我关注的开源 (1)
- RIA AIR (1)
- spring (11)
- lucene (0)
- 工具 (10)
- 百科 (2)
- linux (6)
- android (40)
- 移动开发 (21)
- 代码片断 (15)
- tomcat (1)
- css (1)
- html5 (2)
- jquery (2)
- playframework (3)
- web (2)
- nio (3)
- design (1)
- nosql (3)
- 日志 (12)
- mysql (4)
- 图表 (1)
- python (3)
- ruby (1)
- git (0)
- hibernate (1)
- springboot (1)
- guava (1)
- mybatis (0)
- 工作问题 (3)
- php (1)
最新评论
-
linzm1990:
踩了很多坑啊。。。。
hibernate @Nofound 与@ManyToOne fetch lazy的问题 -
Ccccrrrrrr:
...
转: Spring boot 文件上传 -
rmzdb:
兄弟,你这个东西,在ie内核的浏览器,貌似不识别 文件名
工作问题:http下载文件,中文文件名在firefox下乱码问题 -
107x:
问题解决了,谢谢!
工作问题:http下载文件,中文文件名在firefox下乱码问题 -
klxqljq:
额鹅鹅鹅
android布局实现头尾固定, 中间多余内容可以滚动
处理tomcat的session
NoSql Sessions with Jetty7 and Jetty8
转 http://www.jamesward.com/2011/11/30/using-mongodb-for-a-java-web-apps-httpsession
Since the web’s inception we’ve been using it as a glorified green screen. In this model all web application interactions and the state associated with those interactions, is handled by the server. This model is a real pain to scale. Luckily the model is shifting to more of a Client/Server approach where the UI state moves to the client (where it should be). But for many of today’s applications we still have to deal with server-side state. Typically that state is just stored in memory. It’s fast but if we need more than one server (for failover or load-balancing) then we usually need to replicate that state across our servers. To keep web clients talking to the same server (usually for performance and consistency) our load-balancers have implemented sticky sessions. Session replication and sticky sessions are really just a by-product of putting client state information in memory. Until we all move to stateless web architectures we need to find more scalable and maintainable ways to handle session state.
Jetty has recently added support for a pluggable session state manager. This allows us to move away from sticky sessions and session replication and instead use external systems to store session state. Jetty provides a MongoDB implementation out-of-the-box but presumably it wouldn’t be very hard to add other implementations like Memcached. Jetty has some good documentation on how to configure this with XML. Lets walk through a sample application using Jetty and MongoDB for session state and then deploy that application on the cloud with Heroku.
First lets cover some Heroku basics. Heroku runs applications on “dynos”. You can think of dynos as isolated execution environments for your application. An application on Heroku can have web dynos and non-web dynos. Web dynos will be used for handling HTTP requests for your application. Non-web dynos can be used for background processing, one-off processes, scheduled jobs, etc. HTTP (or HTTPS) requests to your application are automatically load balanced across your web dynos. Heroku does not use sticky sessions so it is up to you to insure that if you have more than one web dyno or if a dyno is restarted, that your users’ sessions will not be lost.
Heroku does not have any special/custom APIs and does not dictate which app server you use. This means you have to bring your app server with you. There are a variety of ways to do that but the preferred approach is to specify your app server as a dependency in your application build descriptor (Maven, sbt, etc).
You must tell Heroku what process needs to be run when a new dyno is started. This is defined in a file called “Procfile” that must be in the root directory of your project.
Heroku provides a really nifty and simple way to provision new external systems that you can use in your application. These are called “add-ons”. There are tons of Heroku add-ons but for this example we will be using the MongoHQ add-on that provides a MongoDB instance.
With that in mind lets walk through a simple application that uses Jetty’s MongoDB-backed sessions. You can get all of this code from github or just clone the github repo:
First lets setup a Maven build that will include the Jetty and MongoDB driver dependencies. We will use “appassembler-maven-plugin” to generate a script that starts the Jetty server. Here is the pom.xml Maven build descriptor:
The “appassembler-maven-plugin” references a class “com.heroku.test.Main” that hasn’t been created yet. We will get to that in a minute. First lets create a simple servlet that will store an object in the session. Here is the servlet from the “src/main/java/com/heroku/test/servlet/TestServlet.java” file:
As you can see there is nothing special here. We are using the regular HttpSession normally, storing and retrieving a Serializable object named CountHolder. The application simply displays the number or times the servlet has been accessed by a user (where “user” really means a request that passes the same JSESSIONID cookie as a previous request).
Now lets map that servlet to the “/” URL pattern in the web app descriptor (src/main/webapp/WEB-INF/web.xml):
I put a servlet mapping in for “.ico” because some browsers automatically request “favicon.ico”, and those requests if not mapped to something will map to our servlet and make the count appear to jump.
Now lets create that “com.heroku.test.Main” class that will configure Jetty and start it. One reason we are using a Java class to start Jetty is because we are trying to avoid putting the MongoDB connection information in a text file. Heroku add-ons place their connection information for the external systems in environment variables. We could copy that information into a plain XML Jetty config file but that is an anti-pattern because if the add-on provider needs to change the connection information (perhaps for failover purposes) then our application would stop working until we manually updated the config file. So our simple Main class will just read the connection information from an environment variable and configure Jetty at runtime. Here is the source for the “src/main/java/com/heroku/test/Main.java” file:
As you can see the MongoSessionManager is being configured based on the MONGOHQ_URL environment variable, the Jetty server is being configured to use the MongoSessionManager and pointed to the web app location, and then Jetty is started.
Now lets give it a try! If you want to run everything locally then you will need to have Maven 3 and MongoDB installed and started. Then run the Maven build
This will use the appassembler-maven-plugin to generate the start script which sets up the CLASSPATH and then runs the com.heroku.test.Main class. Before we run we need to set the environment variable to point to our local MongoDB:
On Windows:
On Linux/Mac:
Now run the generated start script:
On Windows:
On Linux/Mac:
Now in your browser make a few requests to:
http://localhost:9090/
Verify that the session is consistent between the two servers.
Now lets deploy this app on the cloud with Heroku. As mentioned earlier we need a file named “Procfile” in the root directory that will tell Heroku what process to run when a dyno is started. Here is the Procfile for this application:
To create and deploy the application you will need to install git & the Heroku Toolbelt, create an Heroku, and since we will be using add-ons you will need to verify your Heroku account. Each application your create on Heroku gets 750 free dyno hours per month. So as long as you don’t go above that and you stick with the free tier of the MongoHQ add-on, then you won’t be billed for anything.
Login to Heroku using the heroku command line interface:
If you haven’t already setup an SSH key for Heroku then the login process will walk you through that.
In the root directory of this project create the app on Heroku with the “cedar” stack and the free MongoHQ add-on:
Upload your application to Heroku using git:
Open the application in your browser:
If you want to add more dynos handling web requests then run:
To see what is running on Heroku run:
If you want to turn off all of the dynos for your application just scale to 0:
To see the logging information for your application run:
To see a live version of this demo visit:
http://young-wind-7462.herokuapp.com/
Well, there you go. You’ve learned how to avoid sticky sessions and session replication by moving session state to an external MongoDB system that can be scaled independently of the web tier. You’ve also learned how to run this on the cloud with Heroku. Let me know if you have any questions.
BTW: I’d like to thank John Simone from Heroku for writing most of the code for this demo.
NoSql Sessions with Jetty7 and Jetty8
转 http://www.jamesward.com/2011/11/30/using-mongodb-for-a-java-web-apps-httpsession
Since the web’s inception we’ve been using it as a glorified green screen. In this model all web application interactions and the state associated with those interactions, is handled by the server. This model is a real pain to scale. Luckily the model is shifting to more of a Client/Server approach where the UI state moves to the client (where it should be). But for many of today’s applications we still have to deal with server-side state. Typically that state is just stored in memory. It’s fast but if we need more than one server (for failover or load-balancing) then we usually need to replicate that state across our servers. To keep web clients talking to the same server (usually for performance and consistency) our load-balancers have implemented sticky sessions. Session replication and sticky sessions are really just a by-product of putting client state information in memory. Until we all move to stateless web architectures we need to find more scalable and maintainable ways to handle session state.
Jetty has recently added support for a pluggable session state manager. This allows us to move away from sticky sessions and session replication and instead use external systems to store session state. Jetty provides a MongoDB implementation out-of-the-box but presumably it wouldn’t be very hard to add other implementations like Memcached. Jetty has some good documentation on how to configure this with XML. Lets walk through a sample application using Jetty and MongoDB for session state and then deploy that application on the cloud with Heroku.
First lets cover some Heroku basics. Heroku runs applications on “dynos”. You can think of dynos as isolated execution environments for your application. An application on Heroku can have web dynos and non-web dynos. Web dynos will be used for handling HTTP requests for your application. Non-web dynos can be used for background processing, one-off processes, scheduled jobs, etc. HTTP (or HTTPS) requests to your application are automatically load balanced across your web dynos. Heroku does not use sticky sessions so it is up to you to insure that if you have more than one web dyno or if a dyno is restarted, that your users’ sessions will not be lost.
Heroku does not have any special/custom APIs and does not dictate which app server you use. This means you have to bring your app server with you. There are a variety of ways to do that but the preferred approach is to specify your app server as a dependency in your application build descriptor (Maven, sbt, etc).
You must tell Heroku what process needs to be run when a new dyno is started. This is defined in a file called “Procfile” that must be in the root directory of your project.
Heroku provides a really nifty and simple way to provision new external systems that you can use in your application. These are called “add-ons”. There are tons of Heroku add-ons but for this example we will be using the MongoHQ add-on that provides a MongoDB instance.
With that in mind lets walk through a simple application that uses Jetty’s MongoDB-backed sessions. You can get all of this code from github or just clone the github repo:
git clone git://github.com/jamesward/jetty-mongo-session-test.git
First lets setup a Maven build that will include the Jetty and MongoDB driver dependencies. We will use “appassembler-maven-plugin” to generate a script that starts the Jetty server. Here is the pom.xml Maven build descriptor:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.heroku.test</groupId> <version>1.0-SNAPSHOT</version> <name>jettySessionTest</name> <artifactId>jettySessionTest</artifactId> <packaging>jar</packaging> <dependencies> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-webapp</artifactId> <version>8.0.3.v20111011</version> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-nosql</artifactId> <version>8.0.3.v20111011</version> </dependency> <dependency> <groupId>org.mongodb</groupId> <artifactId>mongo-java-driver</artifactId> <version>2.6.5</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>appassembler-maven-plugin</artifactId> <version>1.1.1</version> <executions> <execution> <phase>package</phase> <goals> <goal>assemble</goal> </goals> <configuration> <assembleDirectory>target</assembleDirectory> <programs> <program> <mainClass>com.heroku.test.Main</mainClass> <name>webapp</name> </program> </programs> </configuration> </execution> </executions> </plugin> </plugins> </build> </project>
The “appassembler-maven-plugin” references a class “com.heroku.test.Main” that hasn’t been created yet. We will get to that in a minute. First lets create a simple servlet that will store an object in the session. Here is the servlet from the “src/main/java/com/heroku/test/servlet/TestServlet.java” file:
package com.heroku.test.servlet; import java.io.IOException; import java.io.Serializable; import java.util.Date; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; public class TestServlet extends HttpServlet { private class CountHolder implements Serializable { private static final long serialVersionUID = 1L; private Integer count; private Date time; public CountHolder() { count = 0; time = new Date(); } public Integer getCount() { return count; } public void plusPlus() { count++; } public void setTime(Date time) { this.time = time; } } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { HttpSession session = req.getSession(); CountHolder count; if(session.getAttribute("count") != null) { count = (CountHolder) session.getAttribute("count"); } else { count = new CountHolder(); } count.setTime(new Date()); count.plusPlus(); System.out.println("Count: " + count.getCount()); session.setAttribute("count", count); resp.getWriter().print("count = " + count.getCount()); } }
As you can see there is nothing special here. We are using the regular HttpSession normally, storing and retrieving a Serializable object named CountHolder. The application simply displays the number or times the servlet has been accessed by a user (where “user” really means a request that passes the same JSESSIONID cookie as a previous request).
Now lets map that servlet to the “/” URL pattern in the web app descriptor (src/main/webapp/WEB-INF/web.xml):
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <servlet> <servlet-name>Test Servlet</servlet-name> <servlet-class>com.heroku.test.servlet.TestServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.ico</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>Test Servlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
I put a servlet mapping in for “.ico” because some browsers automatically request “favicon.ico”, and those requests if not mapped to something will map to our servlet and make the count appear to jump.
Now lets create that “com.heroku.test.Main” class that will configure Jetty and start it. One reason we are using a Java class to start Jetty is because we are trying to avoid putting the MongoDB connection information in a text file. Heroku add-ons place their connection information for the external systems in environment variables. We could copy that information into a plain XML Jetty config file but that is an anti-pattern because if the add-on provider needs to change the connection information (perhaps for failover purposes) then our application would stop working until we manually updated the config file. So our simple Main class will just read the connection information from an environment variable and configure Jetty at runtime. Here is the source for the “src/main/java/com/heroku/test/Main.java” file:
package com.heroku.test; import java.util.Date; import java.util.Random; import org.eclipse.jetty.nosql.mongodb.MongoSessionIdManager; import org.eclipse.jetty.nosql.mongodb.MongoSessionManager; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.session.SessionHandler; import org.eclipse.jetty.webapp.WebAppContext; import com.mongodb.DB; import com.mongodb.MongoURI; public class Main { public static void main(String[] args) throws Exception{ String webappDirLocation = "src/main/webapp/"; String webPort = System.getenv("PORT"); if(webPort == null || webPort.isEmpty()) { webPort = "8080"; } Server server = new Server(Integer.valueOf(webPort)); WebAppContext root = new WebAppContext(); MongoURI mongoURI = new MongoURI(System.getenv("MONGOHQ_URL")); DB connectedDB = mongoURI.connectDB(); if (mongoURI.getUsername() != null) { connectedDB.authenticate(mongoURI.getUsername(), mongoURI.getPassword()); } MongoSessionIdManager idMgr = new MongoSessionIdManager(server, connectedDB.getCollection("sessions")); Random rand = new Random((new Date()).getTime()); int workerNum = 1000 + rand.nextInt(8999); idMgr.setWorkerName(String.valueOf(workerNum)); server.setSessionIdManager(idMgr); SessionHandler sessionHandler = new SessionHandler(); MongoSessionManager mongoMgr = new MongoSessionManager(); mongoMgr.setSessionIdManager(server.getSessionIdManager()); sessionHandler.setSessionManager(mongoMgr); root.setSessionHandler(sessionHandler); root.setContextPath("/"); root.setDescriptor(webappDirLocation+"/WEB-INF/web.xml"); root.setResourceBase(webappDirLocation); root.setParentLoaderPriority(true); server.setHandler(root); server.start(); server.join(); } }
As you can see the MongoSessionManager is being configured based on the MONGOHQ_URL environment variable, the Jetty server is being configured to use the MongoSessionManager and pointed to the web app location, and then Jetty is started.
Now lets give it a try! If you want to run everything locally then you will need to have Maven 3 and MongoDB installed and started. Then run the Maven build
mvn package
This will use the appassembler-maven-plugin to generate the start script which sets up the CLASSPATH and then runs the com.heroku.test.Main class. Before we run we need to set the environment variable to point to our local MongoDB:
On Windows:
set MONGOHQ_URL=mongodb://127.0.0.1:27017/test
On Linux/Mac:
export MONGOHQ_URL=mongodb://127.0.0.1:27017/test
Now run the generated start script:
On Windows:
target\bin\webapp.bat
On Linux/Mac:
export MONGOHQ_URL=mongodb://127.0.0.1:27017/test export PORT=9090 sh target/bin/webapp
Now in your browser make a few requests to:
http://localhost:9090/
Verify that the session is consistent between the two servers.
Now lets deploy this app on the cloud with Heroku. As mentioned earlier we need a file named “Procfile” in the root directory that will tell Heroku what process to run when a dyno is started. Here is the Procfile for this application:
web: sh target/bin/webapp
To create and deploy the application you will need to install git & the Heroku Toolbelt, create an Heroku, and since we will be using add-ons you will need to verify your Heroku account. Each application your create on Heroku gets 750 free dyno hours per month. So as long as you don’t go above that and you stick with the free tier of the MongoHQ add-on, then you won’t be billed for anything.
Login to Heroku using the heroku command line interface:
heroku login
If you haven’t already setup an SSH key for Heroku then the login process will walk you through that.
In the root directory of this project create the app on Heroku with the “cedar” stack and the free MongoHQ add-on:
heroku create --stack cedar --addons mongohq:free
Upload your application to Heroku using git:
git push heroku master
Open the application in your browser:
heroku open
If you want to add more dynos handling web requests then run:
heroku scale web=2
To see what is running on Heroku run:
heroku ps
If you want to turn off all of the dynos for your application just scale to 0:
heroku scale web=0
To see the logging information for your application run:
heroku logs
To see a live version of this demo visit:
http://young-wind-7462.herokuapp.com/
Well, there you go. You’ve learned how to avoid sticky sessions and session replication by moving session state to an external MongoDB system that can be scaled independently of the web tier. You’ve also learned how to run this on the cloud with Heroku. Let me know if you have any questions.
BTW: I’d like to thank John Simone from Heroku for writing most of the code for this demo.
相关推荐
MongoDB for Java Developers Design, build, and deliver efficient Java applications using the most advanced NoSQL database
mongodb driver java 源码 2.5.3 版本
mongodb for java api 英文版
MongoDB Java操作大全 源代码 实例
MongoDB实现增删改查,java程序驱动,复杂查询,源代码示例
MongoDB spring hibernate java 集成demo
MongoDB for Java Developers的随书阅读代码,记录了整本书的大部分案例代码,下载即可运行!
The NoSQL movement is growing in relevance, attracting more and more developers....By the end of this book, you will know everything you need to integrate MongoDB in your Java applications
MongoDBjava各版本驱动下载
This book is designed for JavaScript developers of any skill level that want to get up and running using Node.js and MongoDB to build full-featured web applications. A basic understanding of ...
mongodb-java-driver-4.4.0.jar
MongoDB应用 Java应用 纯java mongodb操作 mongodb 通用dao
MongoDB、Java与对象关系映射 MongoDB、Java与对象关系映射
php MongoDB for CI,ci框架的mongodb扩展应用,还是非常好用的,封装的好的
mongodb官网下载速度非常慢,故上传一个windows系统64bit的安装包及java的api文档
MongoDB Java Driver 简单操作
mongodb Java连接池配置 用于避免Java连接mongodb数据库数过高引起的一系列问题
mongoDB java 驱动 mongoDB java 驱动 mongoDB java 驱动 mongoDB java 驱动
使用java向mongodb中插入数据 一、Linux安装mongodb 二、MongoDB客户端工具(MongoVUE)访问mongodb 三、通过Java操作MongoDB
解决连接池不够的问题,多连接的问题。适用于mongoDB项目开发,感兴趣可以下载使用,记得好评哦。欢迎在下方留言