mizuno 0.5.1 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +7 -11
- data/Rakefile +6 -4
- data/lib/java/{jetty-continuation-8.0.4.v20111024.jar → jetty-continuation-8.1.2.v20120308.jar} +0 -0
- data/lib/java/jetty-http-8.1.2.v20120308.jar +0 -0
- data/lib/java/jetty-io-8.1.2.v20120308.jar +0 -0
- data/lib/java/jetty-jmx-8.1.2.v20120308.jar +0 -0
- data/lib/java/jetty-security-8.1.2.v20120308.jar +0 -0
- data/lib/java/jetty-server-8.1.2.v20120308.jar +0 -0
- data/lib/java/jetty-servlet-8.1.2.v20120308.jar +0 -0
- data/lib/java/jetty-servlets-8.1.2.v20120308.jar +0 -0
- data/lib/java/jetty-util-8.1.2.v20120308.jar +0 -0
- data/lib/java/rewindable-input-stream.jar +0 -0
- data/lib/java/servlet-api-3.0.jar +0 -0
- data/lib/mizuno/choices.rb +8 -2
- data/lib/mizuno/http_server.rb +6 -3
- data/lib/mizuno/reloader.rb +147 -0
- data/lib/mizuno/runner.rb +56 -30
- data/lib/mizuno/version.rb +1 -1
- data/lib/rack/handler/mizuno.rb +4 -0
- data/mizuno.gemspec +2 -0
- metadata +13 -11
- data/lib/java/jetty-http-8.0.4.v20111024.jar +0 -0
- data/lib/java/jetty-io-8.0.4.v20111024.jar +0 -0
- data/lib/java/jetty-jmx-8.0.4.v20111024.jar +0 -0
- data/lib/java/jetty-security-8.0.4.v20111024.jar +0 -0
- data/lib/java/jetty-server-8.0.4.v20111024.jar +0 -0
- data/lib/java/jetty-servlet-8.0.4.v20111024.jar +0 -0
- data/lib/java/jetty-servlets-8.0.4.v20111024.jar +0 -0
- data/lib/java/jetty-util-8.0.4.v20111024.jar +0 -0
data/README.markdown
CHANGED
@@ -11,27 +11,23 @@ container for your Rack application to run under JRuby, because Mizuno
|
|
11
11
|
works just like Mongrel, WEBRick, Thin, or any other standard Rack
|
12
12
|
handler.
|
13
13
|
|
14
|
-
Mizuno is the fastest option for Rack applications on JRuby:
|
15
|
-
|
16
|
-
Mizuno: 6106.66 req/s (mean)
|
17
|
-
Jetty (via jruby-rack): 2011.67 req/s (mean)
|
18
|
-
Mongrel: 1479.15 req/sec (mean)
|
19
|
-
|
20
14
|
Mizuno also supports asynchronous request handling, via the Java Servlet
|
21
15
|
3.0 asynchronous processing mechanism
|
22
16
|
|
23
|
-
All the speed comes from Jetty
|
17
|
+
All the speed comes from Jetty 8; Mizuno just ties it to Rack through
|
24
18
|
JRuby's Ruby/Java integration layer.
|
25
19
|
|
26
20
|
Note that Mizuno is NOT a direct replacement for jruby-rack or Warbler,
|
27
21
|
because it doesn't produce WAR files or make any attempt to package a
|
28
22
|
Rack application for installation in a Java web container.
|
29
23
|
|
30
|
-
|
24
|
+
You can also run Mizuno via rackup:
|
25
|
+
|
26
|
+
rackup -s mizuno
|
27
|
+
|
28
|
+
Or with live reloading support:
|
31
29
|
|
32
|
-
|
33
|
-
2. Add hooks for realtime monitoring of server performance.
|
34
|
-
3. Fast restarts of the Rack application.
|
30
|
+
mizuno --reloadable
|
35
31
|
|
36
32
|
Mizuno is licensed under the Apache Public License, version 2.0; see
|
37
33
|
the LICENSE file for details, and was developed on behalf of
|
data/Rakefile
CHANGED
@@ -6,6 +6,8 @@ RSpec::Core::RakeTask.new(:spec)
|
|
6
6
|
|
7
7
|
task :default => :spec
|
8
8
|
|
9
|
+
# http://rubydoc.info/gems/pompompom/1.1.3/frames
|
10
|
+
|
9
11
|
namespace :jetty do
|
10
12
|
desc "Grab the latest Jetty from its Maven repository."
|
11
13
|
task :update do
|
@@ -40,15 +42,15 @@ namespace :jetty do
|
|
40
42
|
# Inventory contents of the tarball we picked up.
|
41
43
|
inventory = `tar tzf #{tempfile}`.split(/\n/)
|
42
44
|
|
43
|
-
#
|
45
|
+
# Figure out which JARs we should replce with tarball contents.
|
44
46
|
replacements = {}
|
45
47
|
Dir.entries(jar_path).each do |entry|
|
46
|
-
next unless (entry =~
|
48
|
+
next unless ((entry =~ /^jetty-\w.*\d\.jar$/) \
|
49
|
+
or (entry =~ /^servlet-api.*\d\.jar$/))
|
47
50
|
name = entry.sub(/\-\d.*$/, '')
|
48
51
|
matcher = /\/#{name}\-[^\/]+\d\.jar$/
|
49
52
|
archive_file = inventory.find { |i| i =~ matcher }
|
50
|
-
|
51
|
-
unless archive_file
|
53
|
+
next unless archive_file
|
52
54
|
replacements[entry] = archive_file
|
53
55
|
end
|
54
56
|
|
data/lib/java/{jetty-continuation-8.0.4.v20111024.jar → jetty-continuation-8.1.2.v20120308.jar}
RENAMED
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/lib/mizuno/choices.rb
CHANGED
@@ -76,7 +76,7 @@ Choice.options do
|
|
76
76
|
end
|
77
77
|
|
78
78
|
separator ''
|
79
|
-
separator '
|
79
|
+
separator 'Mizuno-specific options: '
|
80
80
|
|
81
81
|
option :daemonize do
|
82
82
|
short '-D'
|
@@ -105,7 +105,13 @@ Choice.options do
|
|
105
105
|
|
106
106
|
option :reload do
|
107
107
|
long '--reload'
|
108
|
-
desc '
|
108
|
+
desc 'reloads a running mizuno instance'
|
109
|
+
default false
|
110
|
+
end
|
111
|
+
|
112
|
+
option :reloadable do
|
113
|
+
long '--reloadable'
|
114
|
+
desc 'sets up live reloading via mizuno/reloader'
|
109
115
|
default false
|
110
116
|
end
|
111
117
|
|
data/lib/mizuno/http_server.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'mizuno/version'
|
2
2
|
require 'mizuno/java_logger'
|
3
|
+
require 'mizuno/reloader'
|
3
4
|
|
4
5
|
module Mizuno
|
5
6
|
class HttpServer
|
@@ -73,6 +74,11 @@ module Mizuno
|
|
73
74
|
app_handler = ServletContextHandler.new(nil, "/",
|
74
75
|
ServletContextHandler::NO_SESSIONS)
|
75
76
|
|
77
|
+
# Optionally wrap with Mizuno::Reloader.
|
78
|
+
threshold = (ENV['RACK_ENV'] == 'production' ? 10 : 1)
|
79
|
+
app = Mizuno::Reloader.new(app, threshold) \
|
80
|
+
if options[:reloadable]
|
81
|
+
|
76
82
|
# The servlet itself.
|
77
83
|
rack_servlet = RackServlet.new
|
78
84
|
rack_servlet.rackup(app)
|
@@ -175,8 +181,5 @@ module Mizuno
|
|
175
181
|
end
|
176
182
|
end
|
177
183
|
|
178
|
-
# Register ourselves with Rack when this file gets loaded.
|
179
|
-
Rack::Handler.register 'mizuno', 'Mizuno::HttpServer'
|
180
|
-
|
181
184
|
# Ensure that we shutdown the server on exit.
|
182
185
|
at_exit { Mizuno::HttpServer.stop }
|
@@ -0,0 +1,147 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require 'thread'
|
3
|
+
|
4
|
+
#:nodoc:
|
5
|
+
module Mizuno
|
6
|
+
#
|
7
|
+
# Middleware for reloading production applications; works exactly
|
8
|
+
# like Rack::Reloader, but rather than checking for any changed
|
9
|
+
# file, only looks at one specific file.
|
10
|
+
#
|
11
|
+
# Also allows for explicit reloading via a class method, as well as
|
12
|
+
# by sending a SIGHUP to the process.
|
13
|
+
#
|
14
|
+
class Reloader
|
15
|
+
class << self
|
16
|
+
attr_accessor :logger, :trigger, :reloaders
|
17
|
+
end
|
18
|
+
|
19
|
+
def Reloader.reload!
|
20
|
+
reloaders.each { |r| r.reload!(true) }
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize(app, interval = 1)
|
24
|
+
Thread.exclusive do
|
25
|
+
self.class.reloaders ||= []
|
26
|
+
self.class.reloaders << self
|
27
|
+
self.class.logger ||= Mizuno::HttpServer.logger
|
28
|
+
self.class.trigger ||= "tmp/restart.txt"
|
29
|
+
end
|
30
|
+
|
31
|
+
@app = app
|
32
|
+
@interval = interval
|
33
|
+
@trigger = self.class.trigger
|
34
|
+
@logger = self.class.logger
|
35
|
+
@updated = @threshold = Time.now.to_i
|
36
|
+
end
|
37
|
+
|
38
|
+
#
|
39
|
+
# Reload @app on request.
|
40
|
+
#
|
41
|
+
def call(env)
|
42
|
+
Thread.exclusive { reload! }
|
43
|
+
@app.call(env)
|
44
|
+
end
|
45
|
+
|
46
|
+
#
|
47
|
+
# Reloads the application if (a) we haven't reloaded in
|
48
|
+
# @interval seconds, (b) the trigger file has been touched
|
49
|
+
# since our last check, and (c) some other thread hasn't handled
|
50
|
+
# the update.
|
51
|
+
#
|
52
|
+
def reload!(force = false)
|
53
|
+
return unless (Time.now.to_i > @threshold)
|
54
|
+
@threshold = Time.now.to_i + @interval
|
55
|
+
return unless (force or \
|
56
|
+
((timestamp = mtime(@trigger)).to_i > @updated))
|
57
|
+
timestamp ||= Time.now.to_i
|
58
|
+
|
59
|
+
# Check updated files to ensure they're loadable.
|
60
|
+
missing, errors = 0, 0
|
61
|
+
files = find_files_for_reload do |file, file_mtime|
|
62
|
+
next(missing += 1 and nil) unless file_mtime
|
63
|
+
next unless (file_mtime >= @updated)
|
64
|
+
next(errors += 1 and nil) unless verify(file)
|
65
|
+
file
|
66
|
+
end
|
67
|
+
|
68
|
+
# Cowardly fail if we can't load something.
|
69
|
+
@logger.debug("#{missing} files missing during reload.") \
|
70
|
+
if (missing > 0)
|
71
|
+
return(@logger.error("#{errors} errors, not reloading.")) \
|
72
|
+
if (errors > 0)
|
73
|
+
|
74
|
+
# Reload everything that's changed.
|
75
|
+
files.each do |file|
|
76
|
+
next unless file
|
77
|
+
@logger.info("Reloading #{file}")
|
78
|
+
load(file)
|
79
|
+
end
|
80
|
+
@updated = timestamp
|
81
|
+
end
|
82
|
+
|
83
|
+
#
|
84
|
+
# Walk through the list of every file we've loaded.
|
85
|
+
#
|
86
|
+
def find_files_for_reload
|
87
|
+
paths = [ './', *$LOAD_PATH ].uniq
|
88
|
+
[ $0, *$LOADED_FEATURES ].uniq.map do |file|
|
89
|
+
next if file =~ /\.(so|bundle)$/
|
90
|
+
yield(find(file, paths))
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
#
|
95
|
+
# Returns true if the file is loadable; uses the wrapper
|
96
|
+
# functionality of Kernel#load to protect the global namespace.
|
97
|
+
#
|
98
|
+
def verify(file)
|
99
|
+
begin
|
100
|
+
@logger.debug("Verifying #{file}")
|
101
|
+
load(file, true)
|
102
|
+
return(true)
|
103
|
+
rescue => error
|
104
|
+
@logger.error("Failed to verify #{file}: #{error.to_s}")
|
105
|
+
error.backtrace.each { |l| @logger.error(" #{l}") }
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
#
|
110
|
+
# Takes a relative or absolute +file+ name, a couple possible
|
111
|
+
# +paths+ that the +file+ might reside in. Returns a tuple of
|
112
|
+
# the full path where the file was found and its modification
|
113
|
+
# time, or nil if not found.
|
114
|
+
#
|
115
|
+
def find(file, paths)
|
116
|
+
if(Pathname.new(file).absolute?)
|
117
|
+
return unless (timestamp = mtime(file))
|
118
|
+
@logger.debug("Found #{file}")
|
119
|
+
[ file, timestamp ]
|
120
|
+
else
|
121
|
+
paths.each do |path|
|
122
|
+
fullpath = File.expand_path((File.join(path, file)))
|
123
|
+
next unless (timestamp = mtime(fullpath))
|
124
|
+
@logger.debug("Found #{file} in #{fullpath}")
|
125
|
+
return([ fullpath, timestamp ])
|
126
|
+
end
|
127
|
+
return(nil)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
#
|
132
|
+
# Returns the modification time of _file_.
|
133
|
+
#
|
134
|
+
def mtime(file)
|
135
|
+
begin
|
136
|
+
return unless file
|
137
|
+
stat = File.stat(file)
|
138
|
+
stat.file? ? stat.mtime.to_i : nil
|
139
|
+
rescue Errno::ENOENT, Errno::ENOTDIR
|
140
|
+
nil
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# Reload on SIGHUP.
|
147
|
+
trap("SIGHUP") { Mizuno::Reloader.reload! }
|
data/lib/mizuno/runner.rb
CHANGED
@@ -8,6 +8,59 @@ require 'etc'
|
|
8
8
|
require 'rack'
|
9
9
|
|
10
10
|
module Mizuno
|
11
|
+
require 'rbconfig'
|
12
|
+
|
13
|
+
module Daemonizer
|
14
|
+
def self.included?(base)
|
15
|
+
if(Config::CONFIG['host_os'] =~ /mswin|mingw/)
|
16
|
+
base.send(:extend, StubbedClassMethods)
|
17
|
+
else
|
18
|
+
base.send(:extend, UnixClassMethods)
|
19
|
+
base.send(:class_eval) do
|
20
|
+
extend FFI::Library
|
21
|
+
ffi_lib 'c'
|
22
|
+
attach_function :_setuid, :setuid, [ :uint ], :int
|
23
|
+
attach_function :_setgid, :setgid, [ :uint ], :int
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
module UnixClassMethods
|
30
|
+
#
|
31
|
+
# Switch the process over to a new user id; will abort the
|
32
|
+
# process if it fails. _options_ is the full list of options
|
33
|
+
# passed to a server.
|
34
|
+
#
|
35
|
+
def setuid(options)
|
36
|
+
entry = Etc.getpwnam(options[:user])
|
37
|
+
die("Can't find --user named '#{options[:user]}'") \
|
38
|
+
unless entry
|
39
|
+
return unless (_setuid(entry.uid) != 0)
|
40
|
+
die("Can't switch to user '#{options[:user]}'")
|
41
|
+
end
|
42
|
+
|
43
|
+
#
|
44
|
+
# Like setuid, but for groups.
|
45
|
+
#
|
46
|
+
def setgid(options)
|
47
|
+
entry = Etc.getgrnam(options[:group])
|
48
|
+
die("Can't find --group named '#{options[:group]}'") \
|
49
|
+
unless entry
|
50
|
+
return unless (_setgid(entry.gid) != 0)
|
51
|
+
die("Can't switch to group '#{options[:group]}'")
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
module StubbedClassMethods
|
56
|
+
def setuid(options)
|
57
|
+
end
|
58
|
+
|
59
|
+
def setgid(options)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
11
64
|
#
|
12
65
|
# Launches Mizuno when called from the command-line, and handles
|
13
66
|
# damonization via FFI.
|
@@ -15,35 +68,7 @@ module Mizuno
|
|
15
68
|
# Daemonization code based on Spoon.
|
16
69
|
#
|
17
70
|
class Runner
|
18
|
-
|
19
|
-
|
20
|
-
ffi_lib 'c'
|
21
|
-
|
22
|
-
attach_function :_setuid, :setuid, [ :uint ], :int
|
23
|
-
|
24
|
-
attach_function :_setgid, :setgid, [ :uint ], :int
|
25
|
-
|
26
|
-
#
|
27
|
-
# Switch the process over to a new user id; will abort the
|
28
|
-
# process if it fails. _options_ is the full list of options
|
29
|
-
# passed to a server.
|
30
|
-
#
|
31
|
-
def Runner.setuid(options)
|
32
|
-
entry = Etc.getpwnam(options[:user])
|
33
|
-
die("Can't find --user named '#{options[:user]}'") unless entry
|
34
|
-
return unless (_setuid(entry.uid) != 0)
|
35
|
-
die("Can't switch to user '#{options[:user]}'")
|
36
|
-
end
|
37
|
-
|
38
|
-
#
|
39
|
-
# Like setuid, but for groups.
|
40
|
-
#
|
41
|
-
def Runner.setgid(options)
|
42
|
-
entry = Etc.getgrnam(options[:group])
|
43
|
-
die("Can't find --group named '#{options[:group]}'") unless entry
|
44
|
-
return unless (_setgid(entry.gid) != 0)
|
45
|
-
die("Can't switch to group '#{options[:group]}'")
|
46
|
-
end
|
71
|
+
include Daemonizer
|
47
72
|
|
48
73
|
#
|
49
74
|
# Launch Jetty, optionally as a daemon.
|
@@ -75,6 +100,7 @@ module Mizuno
|
|
75
100
|
# Fire up Mizuno as if it was called from Rackup.
|
76
101
|
Dir.chdir(options[:root])
|
77
102
|
HttpServer.configure_logging(options)
|
103
|
+
ENV['RACK_ENV'] = options[:env]
|
78
104
|
server = Rack::Server.new
|
79
105
|
server.options = options.merge(:server => 'mizuno',
|
80
106
|
:environment => options[:env])
|
@@ -105,7 +131,7 @@ module Mizuno
|
|
105
131
|
File.open(options[:pidfile], 'w') { |f| f.puts(child.pid) }
|
106
132
|
|
107
133
|
# Wait until the server starts or we time out waiting for it.
|
108
|
-
exit if wait_for_server(options)
|
134
|
+
exit if wait_for_server(options, 60)
|
109
135
|
child.stop
|
110
136
|
die("Failed to start Mizuno.")
|
111
137
|
end
|
data/lib/mizuno/version.rb
CHANGED
data/mizuno.gemspec
CHANGED
@@ -23,9 +23,11 @@ Gem::Specification.new do |spec|
|
|
23
23
|
lib/mizuno/java_logger.rb
|
24
24
|
lib/mizuno/rack/chunked.rb
|
25
25
|
lib/mizuno/rack_servlet.rb
|
26
|
+
lib/mizuno/reloader.rb
|
26
27
|
lib/mizuno/runner.rb
|
27
28
|
lib/mizuno/version.rb
|
28
29
|
lib/mizuno.rb
|
30
|
+
lib/rack/handler/mizuno.rb
|
29
31
|
bin/mizuno)
|
30
32
|
jars = Dir.entries("lib/java").grep(/\.jar$/)
|
31
33
|
spec.files.concat(jars.map { |j| "lib/java/#{j}" })
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: mizuno
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.
|
5
|
+
version: 0.6.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Don Werve
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2012-
|
13
|
+
date: 2012-04-09 00:00:00 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rack
|
@@ -120,19 +120,21 @@ files:
|
|
120
120
|
- lib/mizuno/java_logger.rb
|
121
121
|
- lib/mizuno/rack/chunked.rb
|
122
122
|
- lib/mizuno/rack_servlet.rb
|
123
|
+
- lib/mizuno/reloader.rb
|
123
124
|
- lib/mizuno/runner.rb
|
124
125
|
- lib/mizuno/version.rb
|
125
126
|
- lib/mizuno.rb
|
127
|
+
- lib/rack/handler/mizuno.rb
|
126
128
|
- bin/mizuno
|
127
|
-
- lib/java/jetty-continuation-8.
|
128
|
-
- lib/java/jetty-http-8.
|
129
|
-
- lib/java/jetty-io-8.
|
130
|
-
- lib/java/jetty-jmx-8.
|
131
|
-
- lib/java/jetty-security-8.
|
132
|
-
- lib/java/jetty-server-8.
|
133
|
-
- lib/java/jetty-servlet-8.
|
134
|
-
- lib/java/jetty-servlets-8.
|
135
|
-
- lib/java/jetty-util-8.
|
129
|
+
- lib/java/jetty-continuation-8.1.2.v20120308.jar
|
130
|
+
- lib/java/jetty-http-8.1.2.v20120308.jar
|
131
|
+
- lib/java/jetty-io-8.1.2.v20120308.jar
|
132
|
+
- lib/java/jetty-jmx-8.1.2.v20120308.jar
|
133
|
+
- lib/java/jetty-security-8.1.2.v20120308.jar
|
134
|
+
- lib/java/jetty-server-8.1.2.v20120308.jar
|
135
|
+
- lib/java/jetty-servlet-8.1.2.v20120308.jar
|
136
|
+
- lib/java/jetty-servlets-8.1.2.v20120308.jar
|
137
|
+
- lib/java/jetty-util-8.1.2.v20120308.jar
|
136
138
|
- lib/java/log4j-1.2.16.jar
|
137
139
|
- lib/java/rewindable-input-stream.jar
|
138
140
|
- lib/java/servlet-api-3.0.jar
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|