thrift 0.22.0 → 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +175 -17
  3. data/benchmark/benchmark.rb +22 -8
  4. data/benchmark/client.rb +49 -6
  5. data/benchmark/server.rb +45 -7
  6. data/benchmark/thin_server.rb +1 -0
  7. data/ext/binary_protocol_accelerated.c +76 -19
  8. data/ext/compact_protocol.c +80 -15
  9. data/ext/constants.h +12 -0
  10. data/ext/extconf.rb +10 -9
  11. data/ext/memory_buffer.c +7 -7
  12. data/ext/protocol.c +29 -0
  13. data/ext/protocol.h +35 -0
  14. data/ext/struct.c +36 -5
  15. data/ext/thrift_native.c +27 -3
  16. data/lib/thrift/bytes.rb +68 -101
  17. data/lib/thrift/client.rb +61 -9
  18. data/lib/thrift/exceptions.rb +5 -5
  19. data/lib/thrift/multiplexed_processor.rb +6 -6
  20. data/lib/thrift/processor.rb +6 -6
  21. data/lib/thrift/protocol/base_protocol.rb +37 -15
  22. data/lib/thrift/protocol/binary_protocol.rb +25 -9
  23. data/lib/thrift/protocol/binary_protocol_accelerated.rb +5 -5
  24. data/lib/thrift/protocol/compact_protocol.rb +61 -37
  25. data/lib/thrift/protocol/header_protocol.rb +320 -0
  26. data/lib/thrift/protocol/json_protocol.rb +26 -16
  27. data/lib/thrift/protocol/multiplexed_protocol.rb +5 -5
  28. data/lib/thrift/protocol/protocol_decorator.rb +12 -4
  29. data/lib/thrift/serializer/deserializer.rb +5 -5
  30. data/lib/thrift/serializer/serializer.rb +4 -5
  31. data/lib/thrift/server/base_server.rb +4 -4
  32. data/lib/thrift/server/mongrel_http_server.rb +6 -6
  33. data/lib/thrift/server/nonblocking_server.rb +8 -8
  34. data/lib/thrift/server/simple_server.rb +4 -4
  35. data/lib/thrift/server/thin_http_server.rb +3 -3
  36. data/lib/thrift/server/thread_pool_server.rb +6 -6
  37. data/lib/thrift/server/threaded_server.rb +4 -4
  38. data/lib/thrift/struct.rb +11 -11
  39. data/lib/thrift/struct_union.rb +19 -9
  40. data/lib/thrift/thrift_native.rb +1 -1
  41. data/lib/thrift/transport/base_server_transport.rb +5 -5
  42. data/lib/thrift/transport/base_transport.rb +12 -12
  43. data/lib/thrift/transport/buffered_transport.rb +6 -6
  44. data/lib/thrift/transport/framed_transport.rb +7 -7
  45. data/lib/thrift/transport/header_transport.rb +516 -0
  46. data/lib/thrift/transport/http_client_transport.rb +1 -1
  47. data/lib/thrift/transport/io_stream_transport.rb +3 -3
  48. data/lib/thrift/transport/memory_buffer_transport.rb +6 -6
  49. data/lib/thrift/transport/server_socket.rb +8 -5
  50. data/lib/thrift/transport/socket.rb +58 -31
  51. data/lib/thrift/transport/ssl_server_socket.rb +1 -1
  52. data/lib/thrift/transport/ssl_socket.rb +2 -2
  53. data/lib/thrift/transport/unix_server_socket.rb +4 -4
  54. data/lib/thrift/transport/unix_socket.rb +6 -6
  55. data/lib/thrift/types.rb +9 -6
  56. data/lib/thrift/union.rb +14 -8
  57. data/lib/thrift/uuid.rb +49 -0
  58. data/lib/thrift.rb +3 -1
  59. data/spec/ThriftSpec.thrift +5 -1
  60. data/spec/base_protocol_spec.rb +1 -2
  61. data/spec/base_transport_spec.rb +6 -7
  62. data/spec/binary_protocol_spec.rb +0 -2
  63. data/spec/binary_protocol_spec_shared.rb +129 -142
  64. data/spec/bytes_spec.rb +57 -118
  65. data/spec/client_spec.rb +85 -19
  66. data/spec/compact_protocol_spec.rb +54 -16
  67. data/spec/constants_demo_spec.rb +101 -0
  68. data/spec/exception_spec.rb +0 -1
  69. data/spec/header_protocol_spec.rb +475 -0
  70. data/spec/header_transport_spec.rb +386 -0
  71. data/spec/http_client_spec.rb +4 -6
  72. data/spec/json_protocol_spec.rb +47 -47
  73. data/spec/namespaced_spec.rb +0 -1
  74. data/spec/nonblocking_server_spec.rb +102 -4
  75. data/spec/processor_spec.rb +0 -1
  76. data/spec/serializer_spec.rb +0 -1
  77. data/spec/server_socket_spec.rb +1 -1
  78. data/spec/server_spec.rb +8 -9
  79. data/spec/socket_spec.rb +0 -1
  80. data/spec/socket_spec_shared.rb +72 -9
  81. data/spec/spec_helper.rb +1 -1
  82. data/spec/ssl_server_socket_spec.rb +12 -1
  83. data/spec/ssl_socket_spec.rb +10 -1
  84. data/spec/struct_nested_containers_spec.rb +1 -2
  85. data/spec/struct_spec.rb +113 -9
  86. data/spec/support/header_protocol_helper.rb +54 -0
  87. data/spec/thin_http_server_spec.rb +3 -18
  88. data/spec/types_spec.rb +25 -26
  89. data/spec/union_spec.rb +69 -11
  90. data/spec/unix_socket_spec.rb +1 -2
  91. data/spec/uuid_validation_spec.rb +238 -0
  92. data/test/fuzz/Makefile.am +173 -0
  93. data/test/fuzz/README.md +149 -0
  94. data/test/fuzz/fuzz_common.rb +95 -0
  95. data/{lib/thrift/core_ext.rb → test/fuzz/fuzz_parse_binary_protocol.rb} +3 -4
  96. data/{lib/thrift/core_ext/fixnum.rb → test/fuzz/fuzz_parse_binary_protocol_accelerated.rb} +6 -13
  97. data/test/fuzz/fuzz_parse_binary_protocol_accelerated_harness.rb +22 -0
  98. data/test/fuzz/fuzz_parse_binary_protocol_harness.rb +22 -0
  99. data/test/fuzz/fuzz_parse_compact_protocol.rb +22 -0
  100. data/test/fuzz/fuzz_parse_compact_protocol_harness.rb +22 -0
  101. data/test/fuzz/fuzz_parse_json_protocol.rb +22 -0
  102. data/test/fuzz/fuzz_parse_json_protocol_harness.rb +22 -0
  103. data/test/fuzz/fuzz_roundtrip_binary_protocol.rb +22 -0
  104. data/test/fuzz/fuzz_roundtrip_binary_protocol_accelerated.rb +22 -0
  105. data/test/fuzz/fuzz_roundtrip_binary_protocol_accelerated_harness.rb +22 -0
  106. data/test/fuzz/fuzz_roundtrip_binary_protocol_harness.rb +22 -0
  107. data/test/fuzz/fuzz_roundtrip_compact_protocol.rb +22 -0
  108. data/test/fuzz/fuzz_roundtrip_compact_protocol_harness.rb +22 -0
  109. data/test/fuzz/fuzz_roundtrip_json_protocol.rb +22 -0
  110. data/test/fuzz/fuzz_roundtrip_json_protocol_harness.rb +22 -0
  111. data/test/fuzz/fuzz_tracer.rb +28 -0
  112. metadata +106 -37
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fe32174805f7e6b9801ebf00500fad76c1922c3f5e816fba597dfc0aae195c5d
4
- data.tar.gz: b908a7a66b4bff7fc95728778240d2583d685f2fdcdf563edb125dc571cb0040
3
+ metadata.gz: 97c9f50f4cf15be35eb546b5762d7625e3c2b3f8b97765217962409ba66acb99
4
+ data.tar.gz: 92ebb46420c41a9aaa1db0a78cbb7e513d43898c3064283a0b521d4037e63d22
5
5
  SHA512:
6
- metadata.gz: cd8377282c40257b9d4bd2e95633584a04f27609118a8694d9a0037cbf9affc4d9f42aa4647c4dcd43ed64668a77f7abb375f77ca6e5bef8aaae03db8702dcd8
7
- data.tar.gz: 31637b8001126ee81c9a74803e2cbb942cb57dfbc529a72ceb121a28a2614695689d55bd0204dc12429d82ce38a7c0057c18420a872921f376e20e178b213c5e
6
+ metadata.gz: 4d5bcb6f79e7625989ff71e4693de7a0ba19babddb01c7727f4820343947af84ee0fef2a916d836c6a8343a4516670fae8af8f7a35bf8b3c94ab001000615baf
7
+ data.tar.gz: 6216728eb0196480044992e42c8896f82d6e84314aa530bcc438ee50fa636d690a8bd9196868312cc70263ac3e53f99887001cd3073577573baf63f95142f504
data/README.md CHANGED
@@ -1,7 +1,6 @@
1
- Thrift Ruby Software Library
2
- http://thrift.apache.org
1
+ # Thrift Ruby Software Library
3
2
 
4
- == LICENSE:
3
+ ## License
5
4
 
6
5
  Licensed to the Apache Software Foundation (ASF) under one
7
6
  or more contributor license agreements. See the NOTICE file
@@ -20,24 +19,183 @@ KIND, either express or implied. See the License for the
20
19
  specific language governing permissions and limitations
21
20
  under the License.
22
21
 
23
- == DESCRIPTION:
22
+ # Using Thrift with Ruby
24
23
 
25
- Thrift is a strongly-typed language-agnostic RPC system.
26
- This library is the ruby implementation for both clients and servers.
24
+ Ruby bindings for the Apache Thrift RPC system. The gem contains the runtime
25
+ types, transports, protocols, and servers used by generated Ruby code for both
26
+ clients and services.
27
27
 
28
- == INSTALL:
28
+ ## Compatibility
29
29
 
30
- $ gem install thrift
30
+ - Ruby MRI >= 2.7 (tested against current supported releases).
31
+ - JRuby works with the pure-Ruby implementation; the native extension is
32
+ skipped automatically.
33
+ - For the repo-wide transport, protocol, and server support matrix, see
34
+ [Language Feature Matrix](https://github.com/apache/thrift/blob/master/LANGUAGES.md). This README focuses on Ruby-specific
35
+ behavior and migration notes.
31
36
 
32
- == CAVEATS:
37
+ ## Installation
33
38
 
34
- This library provides the client and server implementations of thrift.
35
- It does <em>not</em> provide the compiler for the .thrift files. To compile
36
- .thrift files into language-specific implementations, please download the full
37
- thrift software package.
39
+ - Requirements: Ruby >= 2.7.
40
+ - From RubyGems: `gem install thrift`
41
+ - From source: `bundle install`, `gem build thrift.gemspec`, then install the
42
+ resulting `thrift-*.gem`. The native accelerator is built when the gem is
43
+ installed on supported runtimes.
38
44
 
39
- == USAGE:
45
+ ## Generating Ruby Code
40
46
 
41
- This section should get written by someone with the time and inclination.
42
- In the meantime, look at existing code, such as the benchmark or the tutorial
43
- in the full thrift distribution.
47
+ The Ruby library does not include the Thrift compiler. Use a compiler built
48
+ from the root of this repository to generate Ruby bindings:
49
+
50
+ thrift --gen rb path/to/service.thrift
51
+ # with namespaced modules
52
+ thrift --gen rb:namespaced --recurse path/to/service.thrift
53
+
54
+ Generated files are typically written to `gen-rb/` and can be required
55
+ directly from your application.
56
+
57
+ ## Basic Client Usage
58
+
59
+ $:.push File.expand_path('gen-rb', __dir__)
60
+ require 'thrift'
61
+ require 'calculator'
62
+
63
+ socket = Thrift::Socket.new('localhost', 9090)
64
+ transport = Thrift::BufferedTransport.new(socket)
65
+ protocol = Thrift::BinaryProtocol.new(transport)
66
+ client = Calculator::Client.new(protocol)
67
+
68
+ transport.open
69
+ puts client.add(1, 1)
70
+ transport.close
71
+
72
+ ## Basic Server Usage
73
+
74
+ $:.push File.expand_path('gen-rb', __dir__)
75
+ require 'thrift'
76
+ require 'calculator'
77
+
78
+ class CalculatorHandler
79
+ def add(a, b)
80
+ a + b
81
+ end
82
+ end
83
+
84
+ handler = CalculatorHandler.new
85
+ processor = Calculator::Processor.new(handler)
86
+ server_transport = Thrift::ServerSocket.new(9090)
87
+ transport_factory = Thrift::BufferedTransportFactory.new
88
+ protocol_factory = Thrift::BinaryProtocolFactory.new
89
+
90
+ server = Thrift::ThreadedServer.new(processor, server_transport,
91
+ transport_factory, protocol_factory)
92
+ server.serve
93
+
94
+ ## Development and Tests
95
+
96
+ - `bundle exec rake spec` runs the Ruby specs. It expects a built Thrift
97
+ compiler at `../../compiler/cpp/thrift`.
98
+ - `bundle exec rake test` runs the cross-language test suite; it must be
99
+ executed from a full Thrift checkout.
100
+ - `bundle exec rake build_ext` (implicit in the tasks above) compiles the
101
+ optional native extension that accelerates protocols and buffers.
102
+
103
+ ## More Ruby Code
104
+
105
+ - Tutorial client and server: `tutorial/rb/RubyClient.rb` and `tutorial/rb/RubyServer.rb`
106
+ - Runtime benchmarks: `lib/rb/benchmark`
107
+ - Protocol benchmark: `test/rb/benchmarks/protocol_benchmark.rb`
108
+ - Library specs: `lib/rb/spec`
109
+ - Fuzzing harnesses and notes: `lib/rb/test/fuzz`
110
+ - Cross-language and integration tests: `test/rb`
111
+
112
+ ## Breaking Changes
113
+
114
+ ### 0.23.0
115
+
116
+ The documented source-build flow now effectively requires Ruby `2.7+`.
117
+ The committed development bundle no longer resolves on Ruby `2.6`
118
+ (`json-2.18.1 requires ruby version >= 2.7`), so building and testing this
119
+ library from source should be treated as `2.7+`.
120
+
121
+ Generated structs and unions now consistently raise
122
+ `Thrift::ProtocolException::INVALID_DATA` for invalid payloads such as unset
123
+ required fields, invalid enum values, or invalid union state. If your
124
+ application or tests matched older exception types or messages, update them.
125
+
126
+ Regenerated Ruby clients now validate replies more strictly. Mismatched reply
127
+ message types, method names, or sequence IDs raise
128
+ `Thrift::ApplicationException::INVALID_MESSAGE_TYPE`,
129
+ `Thrift::ApplicationException::WRONG_METHOD_NAME`, or
130
+ `Thrift::ApplicationException::BAD_SEQUENCE_ID`. If you relied on older,
131
+ looser reply handling in servers, proxies, or tests, regenerate and update
132
+ those call paths together.
133
+
134
+ Generated Ruby clients have never been safe to share across concurrent
135
+ threads. A client tracks pending sequence IDs on a single reply stream, so use
136
+ one client/transport pair per thread or serialize access yourself.
137
+
138
+ Treat `Thrift::ApplicationException::BAD_SEQUENCE_ID` as a correctness bug
139
+ that needs immediate attention. It means the client read a reply whose
140
+ sequence ID did not match the next pending request, so the connection may
141
+ already be out of sync and you may be reading a reply intended for a
142
+ different call. The most common cause is sharing one client across threads,
143
+ but a buggy proxy or server can also cause it.
144
+
145
+ ### 0.13.0
146
+
147
+ Ruby development and CI moved to Ruby `2.4+`, but the runtime still claimed
148
+ support for older interpreters. Treat Ruby `< 2.4` on the `0.13.x` line as
149
+ best-effort, not guaranteed.
150
+
151
+ - Historical note for very old releases: the Ruby runtime was rearranged to use
152
+ more Ruby-like names, and generated files switched to underscored filenames.
153
+ If you are upgrading very old code, regenerate your Ruby bindings and update
154
+ any old `T*` constants or legacy require paths such as
155
+ `TBinaryProtocol` -> `Thrift::BinaryProtocol`.
156
+ - `rb:namespaced` changes the generated file layout. Flat output from
157
+ `thrift --gen rb` and namespaced output from `thrift --gen rb:namespaced`
158
+ use different require paths, so switch them atomically with regenerated code.
159
+
160
+ # --gen rb
161
+ require 'calculator'
162
+
163
+ # --gen rb:namespaced
164
+ require 'my_namespace/calculator'
165
+
166
+ ## Migration Notes
167
+
168
+ - If you upgrade across the stricter reply-validation changes, regenerate all
169
+ Ruby stubs and deploy them with the matching Ruby runtime. Do not mix old
170
+ generated code, new generated code, and new runtime code on the same client
171
+ path without testing that combination.
172
+ - If you receive `Thrift::ApplicationException::BAD_SEQUENCE_ID`, treat the
173
+ connection as out of sync. Close it, create a new client/transport pair, and
174
+ investigate the root cause before retrying.
175
+ - Do not share one generated Ruby client across concurrent threads. Use one
176
+ client/transport pair per thread, or serialize access to a shared client.
177
+ - If you switch between `thrift --gen rb` and `thrift --gen rb:namespaced`,
178
+ regenerate all Ruby output and update `require` paths in the same change.
179
+
180
+ ## Runtime Notes
181
+
182
+ - Loading the `thrift_native` extension changes which implementation you are
183
+ running. It replaces
184
+ `Thrift::Struct`, `Thrift::Union`, and `Thrift::CompactProtocol` methods
185
+ with C implementations in place. `Thrift::BinaryProtocol` remains available
186
+ in pure Ruby, and the C-backed binary protocol is opt-in through
187
+ `Thrift::BinaryProtocolAcceleratedFactory` or
188
+ `Thrift::BinaryProtocolAccelerated` when that class is available.
189
+ - The native extension is optional. If it cannot be built or loaded, Thrift
190
+ falls back to the pure-Ruby implementation. This mainly changes performance
191
+ and implementation details.
192
+ - JRuby skips the native extension automatically and uses the pure-Ruby path.
193
+ - Do not share one client instance across concurrent threads. A client tracks
194
+ request and reply state on a single transport stream.
195
+ - `Thrift::NonblockingServer` expects framed input. Use
196
+ `Thrift::FramedTransport` with it on the wire.
197
+ - Client and server must agree on transport and protocol choices. If you
198
+ switch to SSL, HTTP, header transport, compact protocol, or namespaced
199
+ generated code, update both ends together.
200
+ - HTTPS client transport verifies peers by default, and `Thrift::SSLSocket`
201
+ performs a hostname check against the host you pass in.
@@ -19,6 +19,7 @@
19
19
 
20
20
  require 'rubygems'
21
21
  $:.unshift File.dirname(__FILE__) + '/../lib'
22
+ $:.unshift File.dirname(__FILE__) + '/../ext'
22
23
  require 'thrift'
23
24
  require 'stringio'
24
25
 
@@ -34,18 +35,21 @@ class Server
34
35
  attr_accessor :interpreter
35
36
  attr_accessor :host
36
37
  attr_accessor :port
38
+ attr_accessor :protocol_type
37
39
 
38
40
  def initialize(opts)
39
41
  @serverclass = opts.fetch(:class, Thrift::NonblockingServer)
40
42
  @interpreter = opts.fetch(:interpreter, "ruby")
41
43
  @host = opts.fetch(:host, ::HOST)
42
44
  @port = opts.fetch(:port, ::PORT)
45
+ @protocol_type = opts.fetch(:protocol_type, 'binary')
46
+ @tls = opts.fetch(:tls, false)
43
47
  end
44
48
 
45
49
  def start
46
50
  return if @serverclass == Object
47
51
  args = (File.basename(@interpreter) == "jruby" ? "-J-server" : "")
48
- @pipe = IO.popen("#{@interpreter} #{args} #{File.dirname(__FILE__)}/server.rb #{@host} #{@port} #{@serverclass.name}", "r+")
52
+ @pipe = IO.popen("#{@interpreter} #{args} #{File.dirname(__FILE__)}/server.rb #{"-tls" if @tls} #{@host} #{@port} #{@serverclass.name} #{@protocol_type}", "r+")
49
53
  Marshal.load(@pipe) # wait until the server has started
50
54
  sleep 0.4 # give the server time to actually start spawning sockets
51
55
  end
@@ -75,6 +79,8 @@ class BenchmarkManager
75
79
  @interpreter = opts.fetch(:interpreter, "ruby")
76
80
  @server = server
77
81
  @log_exceptions = opts.fetch(:log_exceptions, false)
82
+ @protocol_type = opts.fetch(:protocol_type, 'binary')
83
+ @tls = opts.fetch(:tls, false)
78
84
  end
79
85
 
80
86
  def run
@@ -93,13 +99,15 @@ class BenchmarkManager
93
99
  end
94
100
 
95
101
  def spawn
96
- pipe = IO.popen("#{@interpreter} #{File.dirname(__FILE__)}/client.rb #{"-log-exceptions" if @log_exceptions} #{@host} #{@port} #{@clients_per_process} #{@calls_per_client}")
102
+ pipe = IO.popen("#{@interpreter} #{File.dirname(__FILE__)}/client.rb #{"-log-exceptions" if @log_exceptions} #{"-tls" if @tls} #{@host} #{@port} #{@clients_per_process} #{@calls_per_client} #{@protocol_type}")
97
103
  @pool << pipe
98
104
  end
99
105
 
100
106
  def socket_class
101
107
  if @socket
102
108
  Thrift::UNIXSocket
109
+ elsif @tls
110
+ Thrift::SSLSocket
103
111
  else
104
112
  Thrift::Socket
105
113
  end
@@ -108,7 +116,7 @@ class BenchmarkManager
108
116
  def collect_output
109
117
  puts "Collecting output..."
110
118
  # read from @pool until all sockets are closed
111
- @buffers = Hash.new { |h,k| h[k] = '' }
119
+ @buffers = Hash.new { |h, k| h[k] = '' }
112
120
  until @pool.empty?
113
121
  rd, = select(@pool)
114
122
  next if rd.nil?
@@ -176,9 +184,9 @@ class BenchmarkManager
176
184
  end
177
185
  end
178
186
  @report = {}
179
- @report[:total_calls] = call_times.inject(0.0) { |a,t| a += t }
187
+ @report[:total_calls] = call_times.inject(0.0) { |a, t| a += t }
180
188
  @report[:avg_calls] = @report[:total_calls] / call_times.size
181
- @report[:total_clients] = client_times.inject(0.0) { |a,t| a += t }
189
+ @report[:total_clients] = client_times.inject(0.0) { |a, t| a += t }
182
190
  @report[:avg_clients] = @report[:total_clients] / client_times.size
183
191
  @report[:connection_failures] = connection_failures.size
184
192
  @report[:connection_errors] = connection_errors.size
@@ -197,6 +205,7 @@ class BenchmarkManager
197
205
  [["Server class", "%s"], @server.serverclass == Object ? "" : @server.serverclass],
198
206
  [["Server interpreter", "%s"], @server.interpreter],
199
207
  [["Client interpreter", "%s"], @interpreter],
208
+ [["Protocol type", "%s"], @protocol_type],
200
209
  [["Socket class", "%s"], socket_class],
201
210
  ["Number of processes", @num_processes],
202
211
  ["Clients per process", @clients_per_process],
@@ -232,8 +241,8 @@ class BenchmarkManager
232
241
 
233
242
  def tabulate(fmt, *labels_and_values)
234
243
  labels = labels_and_values.map { |l| Array === l ? l.first : l }
235
- label_width = labels.inject(0) { |w,l| l.size > w ? l.size : w }
236
- labels_and_values.each do |(l,v)|
244
+ label_width = labels.inject(0) { |w, l| l.size > w ? l.size : w }
245
+ labels_and_values.each do |(l, v)|
237
246
  f = fmt
238
247
  l, f, c = l if Array === l
239
248
  fmtstr = "%-#{label_width+1}s #{f}"
@@ -246,26 +255,31 @@ class BenchmarkManager
246
255
  end
247
256
 
248
257
  def resolve_const(const)
249
- const and const.split('::').inject(Object) { |k,c| k.const_get(c) }
258
+ const and const.split('::').inject(Object) { |k, c| k.const_get(c) }
250
259
  end
251
260
 
252
261
  puts "Starting server..."
262
+ protocol_type = ENV['THRIFT_PROTOCOL'] || 'binary'
253
263
  args = {}
254
264
  args[:interpreter] = ENV['THRIFT_SERVER_INTERPRETER'] || ENV['THRIFT_INTERPRETER'] || "ruby"
255
265
  args[:class] = resolve_const(ENV['THRIFT_SERVER']) || Thrift::NonblockingServer
256
266
  args[:host] = ENV['THRIFT_HOST'] || HOST
257
267
  args[:port] = (ENV['THRIFT_PORT'] || PORT).to_i
268
+ args[:tls] = ENV['THRIFT_TLS'] == 'true'
269
+ args[:protocol_type] = protocol_type
258
270
  server = Server.new(args)
259
271
  server.start
260
272
 
261
273
  args = {}
262
274
  args[:host] = ENV['THRIFT_HOST'] || HOST
263
275
  args[:port] = (ENV['THRIFT_PORT'] || PORT).to_i
276
+ args[:tls] = ENV['THRIFT_TLS'] == 'true'
264
277
  args[:num_processes] = (ENV['THRIFT_NUM_PROCESSES'] || 40).to_i
265
278
  args[:clients_per_process] = (ENV['THRIFT_NUM_CLIENTS'] || 5).to_i
266
279
  args[:calls_per_client] = (ENV['THRIFT_NUM_CALLS'] || 50).to_i
267
280
  args[:interpreter] = ENV['THRIFT_CLIENT_INTERPRETER'] || ENV['THRIFT_INTERPRETER'] || "ruby"
268
281
  args[:log_exceptions] = !!ENV['THRIFT_LOG_EXCEPTIONS']
282
+ args[:protocol_type] = protocol_type
269
283
  BenchmarkManager.new(args, server).run
270
284
 
271
285
  server.shutdown
data/benchmark/client.rb CHANGED
@@ -18,24 +18,66 @@
18
18
  #
19
19
 
20
20
  $:.unshift File.dirname(__FILE__) + '/../lib'
21
+ $:.unshift File.dirname(__FILE__) + '/../ext'
21
22
  require 'thrift'
23
+ require 'openssl'
22
24
  $:.unshift File.dirname(__FILE__) + "/gen-rb"
23
25
  require 'benchmark_service'
24
26
 
25
27
  class Client
26
- def initialize(host, port, clients_per_process, calls_per_client, log_exceptions)
28
+ def initialize(host, port, clients_per_process, calls_per_client, log_exceptions, tls, protocol_type)
27
29
  @host = host
28
30
  @port = port
29
31
  @clients_per_process = clients_per_process
30
32
  @calls_per_client = calls_per_client
31
33
  @log_exceptions = log_exceptions
34
+ @tls = tls
35
+ @protocol_type = protocol_type || 'binary'
36
+ end
37
+
38
+ def create_protocol(socket)
39
+ case @protocol_type
40
+ when 'binary'
41
+ transport = Thrift::FramedTransport.new(socket)
42
+ Thrift::BinaryProtocol.new(transport)
43
+ when 'compact'
44
+ transport = Thrift::FramedTransport.new(socket)
45
+ Thrift::CompactProtocol.new(transport)
46
+ when 'header'
47
+ Thrift::HeaderProtocol.new(socket)
48
+ when 'header-compact'
49
+ Thrift::HeaderProtocol.new(socket, nil, Thrift::HeaderSubprotocolID::COMPACT)
50
+ when 'header-zlib'
51
+ protocol = Thrift::HeaderProtocol.new(socket)
52
+ protocol.add_transform(Thrift::HeaderTransformID::ZLIB)
53
+ protocol
54
+ else
55
+ transport = Thrift::FramedTransport.new(socket)
56
+ Thrift::BinaryProtocol.new(transport)
57
+ end
32
58
  end
33
59
 
34
60
  def run
35
61
  @clients_per_process.times do
36
- socket = Thrift::Socket.new(@host, @port)
37
- transport = Thrift::FramedTransport.new(socket)
38
- protocol = Thrift::BinaryProtocol.new(transport)
62
+ socket = if @tls
63
+ ssl_context = OpenSSL::SSL::SSLContext.new.tap do |ctx|
64
+ ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
65
+ ctx.min_version = OpenSSL::SSL::TLS1_2_VERSION
66
+
67
+ keys_dir = File.expand_path("../../../test/keys", __dir__)
68
+ ctx.ca_file = File.join(keys_dir, "CA.pem")
69
+ ctx.cert = OpenSSL::X509::Certificate.new(File.open(File.join(keys_dir, "client.crt")))
70
+ ctx.cert_store = OpenSSL::X509::Store.new
71
+ ctx.cert_store.add_file(File.join(keys_dir, 'server.pem'))
72
+ ctx.key = OpenSSL::PKey::RSA.new(File.open(File.join(keys_dir, "client.key")))
73
+ end
74
+
75
+ Thrift::SSLSocket.new(@host, @port, 5, ssl_context)
76
+ else
77
+ Thrift::Socket.new(@host, @port, 5)
78
+ end
79
+ protocol = create_protocol(socket)
80
+ transport = protocol.trans
39
81
  client = ThriftBenchmark::BenchmarkService::Client.new(protocol)
40
82
  begin
41
83
  start = Time.now
@@ -68,7 +110,8 @@ class Client
68
110
  end
69
111
 
70
112
  log_exceptions = true if ARGV[0] == '-log-exceptions' and ARGV.shift
113
+ tls = true if ARGV[0] == '-tls' and ARGV.shift
71
114
 
72
- host, port, clients_per_process, calls_per_client = ARGV
115
+ host, port, clients_per_process, calls_per_client, protocol_type = ARGV
73
116
 
74
- Client.new(host, port.to_i, clients_per_process.to_i, calls_per_client.to_i, log_exceptions).run
117
+ Client.new(host, port.to_i, clients_per_process.to_i, calls_per_client.to_i, log_exceptions, tls, protocol_type).run
data/benchmark/server.rb CHANGED
@@ -18,7 +18,9 @@
18
18
  #
19
19
 
20
20
  $:.unshift File.dirname(__FILE__) + '/../lib'
21
+ $:.unshift File.dirname(__FILE__) + '/../ext'
21
22
  require 'thrift'
23
+ require 'openssl'
22
24
  $:.unshift File.dirname(__FILE__) + "/gen-rb"
23
25
  require 'benchmark_service'
24
26
 
@@ -36,12 +38,46 @@ module Server
36
38
  end
37
39
  end
38
40
 
39
- def self.start_server(host, port, serverClass)
41
+ def self.create_factories(protocol_type)
42
+ case protocol_type
43
+ when 'binary'
44
+ [FramedTransportFactory.new, BinaryProtocolFactory.new]
45
+ when 'compact'
46
+ [FramedTransportFactory.new, CompactProtocolFactory.new]
47
+ when 'header'
48
+ [HeaderTransportFactory.new, HeaderProtocolFactory.new]
49
+ when 'header-compact'
50
+ [HeaderTransportFactory.new, HeaderProtocolFactory.new(nil, HeaderSubprotocolID::COMPACT)]
51
+ when 'header-zlib'
52
+ # Note: Server doesn't add transforms - it mirrors client's transforms
53
+ [HeaderTransportFactory.new, HeaderProtocolFactory.new]
54
+ else
55
+ [FramedTransportFactory.new, BinaryProtocolFactory.new]
56
+ end
57
+ end
58
+
59
+ def self.start_server(host, port, serverClass, tls, protocol_type = nil)
40
60
  handler = BenchmarkHandler.new
41
61
  processor = ThriftBenchmark::BenchmarkService::Processor.new(handler)
42
- transport = ServerSocket.new(host, port)
43
- transport_factory = FramedTransportFactory.new
44
- args = [processor, transport, transport_factory, nil, 20]
62
+ transport = if tls
63
+ ssl_context = OpenSSL::SSL::SSLContext.new.tap do |ctx|
64
+ ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
65
+ ctx.min_version = OpenSSL::SSL::TLS1_2_VERSION
66
+
67
+ keys_dir = File.expand_path("../../../test/keys", __dir__)
68
+ ctx.ca_file = File.join(keys_dir, "CA.pem")
69
+ ctx.cert = OpenSSL::X509::Certificate.new(File.open(File.join(keys_dir, "server.crt")))
70
+ ctx.cert_store = OpenSSL::X509::Store.new
71
+ ctx.cert_store.add_file(File.join(keys_dir, 'client.pem'))
72
+ ctx.key = OpenSSL::PKey::RSA.new(File.open(File.join(keys_dir, "server.key")))
73
+ end
74
+
75
+ Thrift::SSLServerSocket.new(host, port, ssl_context)
76
+ else
77
+ ServerSocket.new(host, port)
78
+ end
79
+ transport_factory, protocol_factory = create_factories(protocol_type || 'binary')
80
+ args = [processor, transport, transport_factory, protocol_factory, 20]
45
81
  if serverClass == NonblockingServer
46
82
  logger = Logger.new(STDERR)
47
83
  logger.level = Logger::WARN
@@ -65,12 +101,14 @@ module Server
65
101
  end
66
102
 
67
103
  def resolve_const(const)
68
- const and const.split('::').inject(Object) { |k,c| k.const_get(c) }
104
+ const and const.split('::').inject(Object) { |k, c| k.const_get(c) }
69
105
  end
70
106
 
71
- host, port, serverklass = ARGV
107
+ tls = true if ARGV[0] == '-tls' and ARGV.shift
108
+
109
+ host, port, serverklass, protocol_type = ARGV
72
110
 
73
- Server.start_server(host, port.to_i, resolve_const(serverklass))
111
+ Server.start_server(host, port.to_i, resolve_const(serverklass), tls, protocol_type)
74
112
 
75
113
  # let our host know that the interpreter has started
76
114
  # ideally we'd wait until the server was serving, but we don't have a hook for that
@@ -18,6 +18,7 @@
18
18
  #
19
19
 
20
20
  $:.unshift File.dirname(__FILE__) + '/../lib'
21
+ $:.unshift File.dirname(__FILE__) + '/../ext'
21
22
  require 'thrift'
22
23
  $:.unshift File.dirname(__FILE__) + "/gen-rb"
23
24
  require 'benchmark_service'