iodine 0.7.40 → 0.7.41
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +6 -5
- data/CHANGELOG.md +6 -0
- data/README.md +34 -37
- data/exe/iodine +1 -0
- data/ext/iodine/fio.c +20 -5
- data/lib/iodine.rb +1 -1
- data/lib/iodine/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 03af29c680fee3cd7b70b4a9fbc0f370b42a763f83f4422cc0f1cae296b95f1c
|
4
|
+
data.tar.gz: b6e25d8cc33dd955989ae6c8f6bf18d45f84dad42887eff22f39c68aada56f02
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b4eab8d5f7309dd8845d4f6c8052935dbd8145201c4820786ae000e895277883765c1dd628c1e053816b50a1d7c002180f6b4e0a5833e60d76277dab8ecf81b1
|
7
|
+
data.tar.gz: f90eb620cf2a9aaf7c943fe981e829f698cb1e8fc176ad8ad778df2c36c5eb026314522d428bee8058915e95f9ed3750ed078931193b81b0dec062e27eb569c2
|
data/.travis.yml
CHANGED
@@ -1,4 +1,7 @@
|
|
1
1
|
language: ruby
|
2
|
+
arch:
|
3
|
+
- amd64
|
4
|
+
- arm64
|
2
5
|
os:
|
3
6
|
- linux
|
4
7
|
# - osx
|
@@ -6,6 +9,7 @@ before_install:
|
|
6
9
|
- gem install bundler -v 1.10.6
|
7
10
|
- bundle install
|
8
11
|
rvm:
|
12
|
+
- 2.7.1
|
9
13
|
- 2.6.5
|
10
14
|
- 2.5.7
|
11
15
|
- 2.4.9
|
@@ -14,7 +18,7 @@ rvm:
|
|
14
18
|
notifications:
|
15
19
|
email: false
|
16
20
|
sudo: required
|
17
|
-
dist:
|
21
|
+
dist: xenial
|
18
22
|
addons:
|
19
23
|
apt:
|
20
24
|
sources:
|
@@ -24,8 +28,5 @@ addons:
|
|
24
28
|
script:
|
25
29
|
- echo CFLAGS = $CFLAGS
|
26
30
|
- echo cflags = $cflags
|
27
|
-
- bundle exec rake
|
31
|
+
- bundle exec rake install
|
28
32
|
- env VERBOSE=1 bundle exec rspec --format documentation
|
29
|
-
- gem uninstall -x iodine
|
30
|
-
- rake build
|
31
|
-
- find pkg/iodine-*.gem -exec gem install -V {} +
|
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,12 @@ Please notice that this change log contains changes for upcoming releases as wel
|
|
6
6
|
|
7
7
|
## Changes:
|
8
8
|
|
9
|
+
#### Change log v.0.7.41 (2020-07-24)
|
10
|
+
|
11
|
+
**Fix**: Hot Restart failed because listening sockets were cleared away. Credit to Néstor Coppi (@Shelvak) for exposing issue #97.
|
12
|
+
|
13
|
+
**Fix**: CLI argument parsing is now only active when using the iodine CLI (or if defining `IODINE_PARSE_CLI` before requiring `iodine`). Credit to Aldis Berjoza (@graudeejs) for exposing issue #96.
|
14
|
+
|
9
15
|
#### Change log v.0.7.40 (2020-05-23)
|
10
16
|
|
11
17
|
**Fix**: fixed TLS logging and performance issues exposed by Franck Gille (@fgi) in issue #93.
|
data/README.md
CHANGED
@@ -19,14 +19,15 @@ Iodine includes native support for:
|
|
19
19
|
* Pub/Sub (with optional Redis Pub/Sub scaling);
|
20
20
|
* Fast(!) builtin Mustache template engine.
|
21
21
|
* Static file service (with automatic `gzip` support for pre-compressed assets);
|
22
|
+
* Optimized Logging to `stderr`.
|
22
23
|
* Asynchronous event scheduling and timers;
|
23
24
|
* HTTP/1.1 keep-alive and pipelining;
|
25
|
+
* Heap Fragmentation Protection.
|
24
26
|
* TLS 1.2 and above (Requires OpenSSL >= 1.1.0);
|
25
27
|
* TCP/IP server and client connectivity;
|
26
28
|
* Unix Socket server and client connectivity;
|
27
|
-
* Hot Restart (using the USR1 signal);
|
29
|
+
* Hot Restart (using the USR1 signal and without hot deployment);
|
28
30
|
* Custom protocol authoring;
|
29
|
-
* Optimized Logging to `stderr`.
|
30
31
|
* [Sequel](https://github.com/jeremyevans/sequel) and ActiveRecord forking protection.
|
31
32
|
* and more!
|
32
33
|
|
@@ -48,6 +49,10 @@ With `Iodine.listen service: :http` it's possible to run multiple HTTP applicati
|
|
48
49
|
|
49
50
|
Iodine also supports native process cluster Pub/Sub and a native RedisEngine to easily scale iodine's Pub/Sub horizontally.
|
50
51
|
|
52
|
+
### Known Issues and Reporting Issues
|
53
|
+
|
54
|
+
See the [GitHub Open Issues](https://github.com/boazsegev/iodine/issues) list for known issues and to report new issues.
|
55
|
+
|
51
56
|
### Installing and Running Iodine
|
52
57
|
|
53
58
|
Install iodine on any Linux / BSD / macOS system using:
|
@@ -70,6 +75,8 @@ bundler exec iodine
|
|
70
75
|
|
71
76
|
#### Installing with SSL/TLS
|
72
77
|
|
78
|
+
**Note**: iodine has known issues with the TLS/SSL support. TLS/SSL should **NOT** be used in production (see issues #95 and #94).
|
79
|
+
|
73
80
|
Make sure to update OpenSSL to the latest version **before installing Ruby** (`rbenv` should do this automatically).
|
74
81
|
|
75
82
|
To avoid name resolution conflicts, iodine will bind to the same OpenSSL version Ruby is bound to. To use SSL/TLS this should be OpenSSL >= 1.1.0 or LibreSSL >= 2.7.4.
|
@@ -87,9 +94,7 @@ Confirmed OpenSSL to be version 1.1.0 or above (OpenSSL 1.1.0j 20 Nov 2018)...
|
|
87
94
|
...
|
88
95
|
```
|
89
96
|
|
90
|
-
**
|
91
|
-
|
92
|
-
The installation script tests for OpenSSL 1.1.0 and above. However, this testing approach sometimes provides false positives. If TLS isn't required, install with `NO_SSL=1`. i.e.:
|
97
|
+
The installation script tests for OpenSSL 1.1.0 and above. However, this testing approach sometimes provides false positives. **If TLS isn't required, install with `NO_SSL=1`**. i.e.:
|
93
98
|
|
94
99
|
```bash
|
95
100
|
NO_SSL=1 bundler exec iodine
|
@@ -110,17 +115,19 @@ On Rails:
|
|
110
115
|
if(defined?(Iodine))
|
111
116
|
Iodine.threads = ENV.fetch("RAILS_MAX_THREADS", 5).to_i if Iodine.threads.zero?
|
112
117
|
Iodine.workers = ENV.fetch("WEB_CONCURRENCY", 2).to_i if Iodine.workers.zero?
|
113
|
-
Iodine::DEFAULT_SETTINGS[:port]
|
118
|
+
Iodine::DEFAULT_SETTINGS[:port] ||= ENV.fetch("PORT") if ENV.fetch("PORT")
|
114
119
|
end
|
115
120
|
```
|
116
121
|
|
117
122
|
When using native WebSockets with Rails, middle-ware is probably the best approach. A guide for this approach will, hopefully, get published in the future.
|
118
123
|
|
124
|
+
**Note**: command-line instructions (CLI) should be the preferred way for configuring iodine, allowing for code-less configuration updates.
|
125
|
+
|
119
126
|
### Optimizing Iodine's Concurrency
|
120
127
|
|
121
128
|
To get the most out of iodine, consider the amount of CPU cores available and the concurrency level the application requires.
|
122
129
|
|
123
|
-
Iodine will calculate, when possible, a good enough default concurrency model. See if this works for your application or customize according to the application's needs.
|
130
|
+
Iodine will calculate, when possible, a good enough default concurrency model for fast applications. See if this works for your application or customize according to the application's needs.
|
124
131
|
|
125
132
|
Command line arguments allow easy access to different options, including concurrency levels. i.e., to set up 16 threads and 4 processes:
|
126
133
|
|
@@ -136,13 +143,19 @@ export WORKERS=-1 # negative values are fractions of CPU cores.
|
|
136
143
|
bundler exec iodine -p $PORT
|
137
144
|
```
|
138
145
|
|
146
|
+
Negative values are evaluated as "CPU Cores / abs(Value)". i.e., on an 8 core CPU machine, this will produce 4 worker processes with 2 threads per worker:
|
147
|
+
|
148
|
+
```bash
|
149
|
+
bundler exec iodine -p $PORT -t 2 -w -2
|
150
|
+
```
|
151
|
+
|
139
152
|
### Heap Fragmentation Protection
|
140
153
|
|
141
154
|
Iodine includes a fast, network oriented, custom memory allocator, optimizing away some of the work usually placed on the Ruby Garbage Collector (GC).
|
142
155
|
|
143
156
|
This approach helps to minimize heap fragmentation for long running processes, by grouping many short-lived objects into a common memory space.
|
144
157
|
|
145
|
-
It
|
158
|
+
It is still recommended to consider [jemalloc](http://jemalloc.net) or other allocators that also help mitigate heap fragmentation issues.
|
146
159
|
|
147
160
|
### Static file serving support
|
148
161
|
|
@@ -435,11 +448,11 @@ Iodine.connect url: "wss://echo.websocket.org", handler: EchoClient.new, ping: 4
|
|
435
448
|
Iodine.start
|
436
449
|
```
|
437
450
|
|
438
|
-
### TLS 1.2 support
|
451
|
+
### TLS >= 1.2 support
|
439
452
|
|
440
453
|
> Requires OpenSSL >= `1.1.0`. On Heroku, requires `heroku-18`.
|
441
454
|
|
442
|
-
Iodine supports secure connections fore TLS version 1.2 and up (depending on the OpenSSL version).
|
455
|
+
Iodine supports secure connections fore TLS version 1.2 **and up** (depending on the OpenSSL version).
|
443
456
|
|
444
457
|
A self signed certificate is available using the `-tls` flag from the command-line.
|
445
458
|
|
@@ -480,31 +493,11 @@ run APP
|
|
480
493
|
|
481
494
|
### How does it compare to other servers?
|
482
495
|
|
483
|
-
|
484
|
-
|
485
|
-
In my tests, pitching Iodine against Puma, Iodine was anywhere between x1.5 and x7 faster than Puma (depending on use-case). such a big difference is suspect and I recommend that you test it yourself.
|
496
|
+
In my tests, pitching Iodine against Puma, Iodine was anywhere between x1.5 and more than x10 faster than Puma (depending on use-case and settings).
|
486
497
|
|
487
|
-
|
498
|
+
Such a big difference is suspect and I recommend that you test it yourself - even better if you test performance using your own application and a number of possible different settings (how many threads per CPU core? how many worker processes? middleware vs. server request logging, etc').
|
488
499
|
|
489
|
-
|
490
|
-
|
491
|
-
* Iodine performed at 74,786.27 req/sec, consuming ~68.4Mb of memory.
|
492
|
-
|
493
|
-
* Puma performed at 48,994.59 req/sec, consuming ~79.6Mb of memory.
|
494
|
-
|
495
|
-
When benchmarking using a VM (crossing machine boundaries, 16 threads, 4 workers, 200 concurrent connections), I calculated Iodine to be x2.3 faster:
|
496
|
-
|
497
|
-
* Iodine performed at 23,559.56 req/sec, consuming ~88.8Mb of memory.
|
498
|
-
|
499
|
-
* Puma performed at 9,935.31 req/sec, consuming ~84.0Mb of memory.
|
500
|
-
|
501
|
-
When benchmarking using a VM (crossing machine boundaries, single thread, single worker, 200 concurrent connections), I calculated Iodine to be x7.3 faster:
|
502
|
-
|
503
|
-
* Iodine performed at 18,444.31 req/sec, consuming ~25.6Mb of memory.
|
504
|
-
|
505
|
-
* Puma performed at 2,521.56 req/sec, consuming ~27.5Mb of memory.
|
506
|
-
|
507
|
-
I have doubts about my own benchmarks and I recommend benchmarking the performance for yourself using `wrk` or `ab`:
|
500
|
+
I recommend benchmarking the performance for yourself using `wrk` or `ab`:
|
508
501
|
|
509
502
|
```bash
|
510
503
|
$ wrk -c200 -d4 -t2 http://localhost:3000/
|
@@ -512,7 +505,7 @@ $ wrk -c200 -d4 -t2 http://localhost:3000/
|
|
512
505
|
$ ab -n 100000 -c 200 -k http://127.0.0.1:3000/
|
513
506
|
```
|
514
507
|
|
515
|
-
|
508
|
+
The best application to use for benchmarking is your actual application. Or, you could create a simple `config.ru` file with a __hello world__ app:
|
516
509
|
|
517
510
|
```ruby
|
518
511
|
App = Proc.new do |env|
|
@@ -525,17 +518,21 @@ end
|
|
525
518
|
run App
|
526
519
|
```
|
527
520
|
|
528
|
-
Then start comparing servers. Here are the settings I used to compare iodine and Puma (4 processes,
|
521
|
+
Then start comparing servers. Here are the settings I used to compare iodine and Puma (4 processes, 4 threads):
|
529
522
|
|
530
523
|
```bash
|
531
|
-
$ RACK_ENV=production iodine -p 3000 -t
|
524
|
+
$ RACK_ENV=production iodine -p 3000 -t 4 -w 4
|
532
525
|
# vs.
|
533
|
-
$ RACK_ENV=production puma -p 3000 -t
|
526
|
+
$ RACK_ENV=production puma -p 3000 -t 4 -w 4
|
534
527
|
# Review the `iodine -?` help for more command line options.
|
535
528
|
```
|
536
529
|
|
537
530
|
It's recommended that the servers (Iodine/Puma) and the client (`wrk`/`ab`) run on separate machines.
|
538
531
|
|
532
|
+
It is worth noting that iodine can also speed up logging by replacing the logging middleware with `iodine -v`. This approach uses less memory and improves performance at the expense of fuzzy timing and some string caching.
|
533
|
+
|
534
|
+
On my machine, testing with the logging functionality enabled, iodine was more then 10 times faster than puma (60.9K req/sec vs. 5.3K req/sec)
|
535
|
+
|
539
536
|
### A few notes
|
540
537
|
|
541
538
|
Iodine's upgrade / callback design has a number of benefits, some of them related to better IO handling, resource optimization (no need for two IO polling systems), etc. This also allows us to use middleware without interfering with connection upgrades and provides backwards compatibility.
|
data/exe/iodine
CHANGED
data/ext/iodine/fio.c
CHANGED
@@ -36,6 +36,12 @@ Feel free to copy, use and enjoy according to the license provided.
|
|
36
36
|
|
37
37
|
#include <arpa/inet.h>
|
38
38
|
|
39
|
+
#if HAVE_OPENSSL
|
40
|
+
#include <openssl/bio.h>
|
41
|
+
#include <openssl/err.h>
|
42
|
+
#include <openssl/ssl.h>
|
43
|
+
#endif
|
44
|
+
|
39
45
|
/* force poll for testing? */
|
40
46
|
#ifndef FIO_ENGINE_POLL
|
41
47
|
#define FIO_ENGINE_POLL 0
|
@@ -3492,11 +3498,13 @@ static void fio_on_fork(void) {
|
|
3492
3498
|
fio_poll_init();
|
3493
3499
|
fio_state_callback_on_fork();
|
3494
3500
|
|
3501
|
+
/* don't pass open connections belonging to the parent onto the child. */
|
3495
3502
|
const size_t limit = fio_data->capa;
|
3496
3503
|
for (size_t i = 0; i < limit; ++i) {
|
3497
3504
|
fd_data(i).sock_lock = FIO_LOCK_INIT;
|
3498
3505
|
fd_data(i).protocol_lock = FIO_LOCK_INIT;
|
3499
|
-
if (fd_data(i).protocol) {
|
3506
|
+
if (fd_data(i).protocol && fd_data(i).open) {
|
3507
|
+
/* open without protocol might be waiting for the child (listening) */
|
3500
3508
|
fd_data(i).protocol->rsv = 0;
|
3501
3509
|
fio_force_close(fd2uuid(i));
|
3502
3510
|
}
|
@@ -3678,8 +3686,9 @@ static void fio_review_timeout(void *arg, void *ignr) {
|
|
3678
3686
|
unlock:
|
3679
3687
|
protocol_unlock(tmp, FIO_PR_LOCK_STATE);
|
3680
3688
|
} else {
|
3681
|
-
/* open FD but no protocol? */
|
3682
|
-
|
3689
|
+
/* open FD but no protocol? RW hook thing or listening sockets? */
|
3690
|
+
if (fd_data(fd).rw_hooks != &FIO_DEFAULT_RW_HOOKS)
|
3691
|
+
fio_close(fd2uuid(fd));
|
3683
3692
|
}
|
3684
3693
|
finish:
|
3685
3694
|
do {
|
@@ -3908,16 +3917,22 @@ void fio_start FIO_IGNORE_MACRO(struct fio_start_args args) {
|
|
3908
3917
|
fio_data->is_worker = 0;
|
3909
3918
|
|
3910
3919
|
fio_state_callback_force(FIO_CALL_PRE_START);
|
3911
|
-
|
3912
3920
|
FIO_LOG_INFO(
|
3913
3921
|
"Server is running %u %s X %u %s with facil.io " FIO_VERSION_STRING
|
3914
3922
|
" (%s)\n"
|
3923
|
+
#if HAVE_OPENSSL
|
3924
|
+
"* Linked to %s\n"
|
3925
|
+
#endif
|
3915
3926
|
"* Detected capacity: %d open file limit\n"
|
3916
3927
|
"* Root pid: %d\n"
|
3917
3928
|
"* Press ^C to stop\n",
|
3918
3929
|
fio_data->workers, fio_data->workers > 1 ? "workers" : "worker",
|
3919
3930
|
fio_data->threads, fio_data->threads > 1 ? "threads" : "thread",
|
3920
|
-
fio_engine(),
|
3931
|
+
fio_engine(),
|
3932
|
+
#if HAVE_OPENSSL
|
3933
|
+
OpenSSL_version(0),
|
3934
|
+
#endif
|
3935
|
+
fio_data->capa, (int)fio_data->parent);
|
3921
3936
|
|
3922
3937
|
if (args.workers > 1) {
|
3923
3938
|
for (int i = 0; i < args.workers && fio_data->active; ++i) {
|
data/lib/iodine.rb
CHANGED
@@ -178,7 +178,7 @@ Iodine.on_state(:after_fork) do
|
|
178
178
|
end
|
179
179
|
|
180
180
|
### Parse CLI for default HTTP settings
|
181
|
-
Iodine::Base::CLI.parse
|
181
|
+
Iodine::Base::CLI.parse if defined?(IODINE_PARSE_CLI) && IODINE_PARSE_CLI
|
182
182
|
|
183
183
|
### Set default port (if missing)
|
184
184
|
Iodine::DEFAULT_SETTINGS[:port] ||= (ENV["PORT"] || "3000")
|
data/lib/iodine/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: iodine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.41
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Boaz Segev
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-07-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -243,7 +243,7 @@ licenses:
|
|
243
243
|
metadata:
|
244
244
|
allowed_push_host: https://rubygems.org
|
245
245
|
post_install_message: |-
|
246
|
-
Thank you for installing Iodine 0.7.
|
246
|
+
Thank you for installing Iodine 0.7.41.
|
247
247
|
Remember: if iodine supports your business, it's only fair to give value back (code contributions / donations).
|
248
248
|
rdoc_options: []
|
249
249
|
require_paths:
|