-
Notifications
You must be signed in to change notification settings - Fork 3.9k
/
server.h
785 lines (641 loc) · 31.3 KB
/
server.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
#ifndef BRPC_SERVER_H
#define BRPC_SERVER_H
// To brpc developers: This is a header included by user, don't depend
// on internal structures, use opaque pointers instead.
#include "bthread/errno.h" // Redefine errno
#include "bthread/bthread.h" // Server may need some bthread functions,
// e.g. bthread_usleep
#include <google/protobuf/service.h> // google::protobuf::Service
#include "butil/macros.h" // DISALLOW_COPY_AND_ASSIGN
#include "butil/containers/doubly_buffered_data.h" // DoublyBufferedData
#include "bvar/bvar.h"
#include "butil/containers/case_ignored_flat_map.h" // [CaseIgnored]FlatMap
#include "butil/ptr_container.h"
#include "brpc/controller.h" // brpc::Controller
#include "brpc/ssl_options.h" // ServerSSLOptions
#include "brpc/describable.h" // User often needs this
#include "brpc/data_factory.h" // DataFactory
#include "brpc/builtin/tabbed.h"
#include "brpc/details/profiler_linker.h"
#include "brpc/health_reporter.h"
#include "brpc/adaptive_max_concurrency.h"
#include "brpc/http2.h"
#include "brpc/redis.h"
#include "brpc/interceptor.h"
#include "brpc/concurrency_limiter.h"
#include "brpc/baidu_master_service.h"
namespace brpc {
class Acceptor;
class MethodStatus;
class NsheadService;
class ThriftService;
class SimpleDataPool;
class MongoServiceAdaptor;
class RestfulMap;
class RtmpService;
class RedisService;
struct SocketSSLContext;
struct ServerOptions {
ServerOptions(); // Constructed with default options.
// connections without data transmission for so many seconds will be closed
// Default: -1 (disabled)
int idle_timeout_sec;
// If this option is not empty, a file named so containing Process Id
// of the server will be created when the server is started.
// Default: ""
std::string pid_file;
// Process requests in format of nshead_t + blob.
// Owned by Server and deleted in server's destructor.
// Default: NULL
NsheadService* nshead_service;
// Process requests in format of thrift_binary_head_t + blob.
// Owned by Server and deleted in server's destructor.
// Default: NULL
ThriftService* thrift_service;
// Adaptor for Mongo protocol, check src/brpc/mongo_service_adaptor.h for details
// The adaptor will not be deleted by server
// and must remain valid when server is running.
const MongoServiceAdaptor* mongo_service_adaptor;
// Turn on authentication for all services if `auth' is not NULL.
// Default: NULL
const Authenticator* auth;
// false: `auth' is not owned by server and must be valid when server is running.
// true: `auth' is owned by server and will be deleted when server is destructed.
// Default: false
bool server_owns_auth;
// Turn on request interception if `interceptor' is not NULL.
// Default: NULL
const Interceptor* interceptor;
// false: `interceptor' is not owned by server and must be valid when server is running.
// true: `interceptor' is owned by server and will be deleted when server is destructed.
// Default: false
bool server_owns_interceptor;
// Number of pthreads that server runs on. Notice that this is just a hint,
// you can't assume that the server uses exactly so many pthreads because
// pthread workers are shared by all servers and channels inside a
// process. And there're no "io-thread" and "worker-thread" anymore,
// brpc automatically schedules "io" and "worker" code for better
// parallelism and less context switches.
// If this option <= 0, number of pthread workers is not changed.
// Default: #cpu-cores
int num_threads;
// Server-level max concurrency.
// "concurrency" = "number of requests processed in parallel"
//
// In a traditional server, number of pthread workers also limits
// concurrency. However brpc runs requests in bthreads which are
// mapped to pthread workers, when a bthread context switches, it gives
// the pthread worker to another bthread, yielding a higher concurrency
// than number of pthreads. In some situations, higher concurrency may
// consume more resources, to protect the server from running out of
// resources, you may set this option.
// If the server reaches the limitation, it responds client with ELIMIT
// directly without calling service's callback. The client seeing ELIMIT
// shall try another server.
// NOTE: accesses to builtin services are not limited by this option.
// Default: 0 (unlimited)
int max_concurrency;
// Default value of method-level max concurrencies,
// Overridable by Server.MaxConcurrencyOf().
AdaptiveMaxConcurrency method_max_concurrency;
// -------------------------------------------------------
// Differences between session-local and thread-local data
// -------------------------------------------------------
// * session-local data has to be got from a server-side Controller.
// thread-local data can be got in any function running inside a server
// thread without an object.
// * session-local data is attached to current RPC and invalid after
// calling `done'. thread-local data is attached to current server
// thread and invalid after leaving Service::CallMethod(). If you need
// to hand down data to an asynchronous `done' which is called outside
// Service::CallMethod(), you must use session-local data.
// -----------------
// General guideline
// -----------------
// * Choose a proper value for reserved_xxx_local_data, small value may
// not create enough data for all searching threads, while big value
// wastes memory.
// * Comparing to reserving data, making them as small as possible and
// creating them on demand is better. Passing a lot of stuff via
// session-local data or thread-local data is definitely not a good design.
// The factory to create/destroy data attached to each RPC session.
// If this option is NULL, Controller::session_local_data() is always NULL.
// NOT owned by Server and must be valid when Server is running.
// Default: NULL
const DataFactory* session_local_data_factory;
// Prepare so many session-local data before server starts, so that calls
// to Controller::session_local_data() get data directly rather than
// calling session_local_data_factory->Create() at first time. Useful when
// Create() is slow, otherwise the RPC session may be blocked by the
// creation of data and not served within timeout.
// Default: 0
size_t reserved_session_local_data;
// The factory to create/destroy data attached to each searching thread
// in server.
// If this option is NULL, brpc::thread_local_data() is always NULL.
// NOT owned by Server and must be valid when Server is running.
// Default: NULL
const DataFactory* thread_local_data_factory;
// Prepare so many thread-local data before server starts, so that calls
// to brpc::thread_local_data() get data directly rather than calling
// thread_local_data_factory->Create() at first time. Useful when Create()
// is slow, otherwise the RPC session may be blocked by the creation
// of data and not served within timeout.
// Default: 0
size_t reserved_thread_local_data;
// Call bthread_init_fn(bthread_init_args) in at least #bthread_init_count
// bthreads before server runs, mainly for initializing bthread locals.
// You have to set both `bthread_init_fn' and `bthread_init_count' to
// enable the feature.
bool (*bthread_init_fn)(void* args); // default: NULL (do nothing)
void* bthread_init_args; // default: NULL
size_t bthread_init_count; // default: 0
// Provide builtin services at this port rather than the port to Start().
// When your server needs to be accessed from public (including traffic
// redirected by nginx or other http front-end servers), set this port
// to a port number that's ONLY accessible from internal network
// so that you can check out the builtin services from this port while
// hiding them from public. Setting this option also enables security
// protection code which we may add constantly.
// Update: this option affects Tabbed services as well.
// Default: -1
int internal_port;
// Contain a set of builtin services to ease monitoring/debugging.
// Read docs/cn/builtin_service.md for details.
// DO NOT set this option to false if you don't even know what builtin
// services are. They're very helpful for addressing runtime problems.
// Setting to false makes -internal_port ineffective.
// Default: true
bool has_builtin_services;
// Enable more secured code which protects internal information from exposure.
bool security_mode() const { return internal_port >= 0 || !has_builtin_services; }
// SSL related options. Refer to `ServerSSLOptions' for details
bool has_ssl_options() const { return _ssl_options != NULL; }
const ServerSSLOptions& ssl_options() const { return *_ssl_options; }
ServerSSLOptions* mutable_ssl_options();
// Force ssl for all connections of the port to Start().
bool force_ssl;
// Whether the server uses rdma or not
// Default: false
bool use_rdma;
BaiduMasterService* baidu_master_service;
// [CAUTION] This option is for implementing specialized http proxies,
// most users don't need it. Don't change this option unless you fully
// understand the description below.
// If this option is set, all HTTP requests to the server will be delegated
// to this service which fully decides what to call and what to send back,
// including accesses to builtin services and pb services.
// The service must have a method named "default_method" and the request
// and response must have no fields.
//
// Owned by Server and deleted in server's destructor
::google::protobuf::Service* http_master_service;
// If this field is on, contents on /health page is generated by calling
// health_reporter->GenerateReport(). This object is NOT owned by server
// and must remain valid when server is running.
HealthReporter* health_reporter;
// For processing RTMP connections. Read src/brpc/rtmp.h for details.
// Default: NULL (rtmp support disabled)
RtmpService* rtmp_service;
// Only enable these protocols, separated by spaces.
// All names inside must be valid, check protocols name in global.cpp
// Default: empty (all protocols)
std::string enabled_protocols;
// Customize parameters of HTTP2, defined in http2.h
H2Settings h2_settings;
// For processing Redis connections. Read src/brpc/redis.h for details.
// Owned by Server and deleted in server's destructor.
// Default: NULL (disabled)
RedisService* redis_service;
// Optional info name for composing server bvar prefix. Read ServerPrefix() method for details;
// Default: ""
std::string server_info_name;
// Server will run in this tagged bthread worker group
// Default: BTHREAD_TAG_DEFAULT
bthread_tag_t bthread_tag;
private:
// SSLOptions is large and not often used, allocate it on heap to
// prevent ServerOptions from being bloated in most cases.
butil::PtrContainer<ServerSSLOptions> _ssl_options;
};
// This struct is originally designed to contain basic statistics of the
// server. But bvar contains more stats and is more convenient.
struct ServerStatistics {
size_t connection_count;
int user_service_count;
int builtin_service_count;
};
// Represent server's ownership of services.
enum ServiceOwnership {
SERVER_OWNS_SERVICE,
SERVER_DOESNT_OWN_SERVICE
};
struct ServiceOptions {
ServiceOptions(); // constructed with default options.
// SERVER_OWNS_SERVICE: the service will be deleted by the server.
// SERVER_DOESNT_OWN_SERVICE: the service shall be deleted by user after
// stopping the server.
// Default: SERVER_DOESNT_OWN_SERVICE
ServiceOwnership ownership;
// If this option is non-empty, methods in the service will be exposed
// on specified paths instead of default "/SERVICE/METHOD".
// Mappings are in form of: "PATH1 => NAME1, PATH2 => NAME2 ..." where
// PATHs are valid http paths, NAMEs are method names in the service.
// Default: empty
std::string restful_mappings;
// Work with restful_mappings, if this flag is false, reject methods accessed
// from default urls (SERVICE/METHOD).
// Default: false
bool allow_default_url;
// [ Not recommended to change this option ]
// If this flag is true, the service will convert http body to protobuf
// when the pb schema is non-empty in http servings. The body must be
// valid json or protobuf(wire-format) otherwise the request is rejected.
// This option does not affect pure-http services (pb schema is empty).
// Services that use older versions of brpc may need to turn this
// conversion off and handle http requests by their own to keep compatible
// with existing clients.
// Default: true
bool allow_http_body_to_pb;
// decode json string to protobuf bytes using base64 decoding when this
// option is turned on.
// Default: false if BAIDU_INTERNAL is defined, otherwise true
bool pb_bytes_to_base64;
// decode json array to protobuf message which contains a single repeated field.
// Default: false.
bool pb_single_repeated_to_array;
// enable server end progressive reading, mainly for http server
// Default: false.
bool enable_progressive_read;
};
// Represent ports inside [min_port, max_port]
struct PortRange {
int min_port;
int max_port;
PortRange(int min_port2, int max_port2)
: min_port(min_port2), max_port(max_port2) {
}
};
// Server dispatches requests from clients to registered services and
// sends responses back to clients.
class Server {
public:
enum Status {
UNINITIALIZED = 0,
READY = 1,
RUNNING = 2,
STOPPING = 3,
};
struct ServiceProperty {
bool is_builtin_service;
ServiceOwnership ownership;
// `service' and `restful_map' are mutual exclusive, they can't be
// both non-NULL. If `restful_map' is not NULL, the URL should be
// further matched by it.
google::protobuf::Service* service;
RestfulMap* restful_map;
bool is_user_service() const {
return !is_builtin_service && !restful_map;
}
const std::string& service_name() const;
};
typedef butil::FlatMap<std::string, ServiceProperty> ServiceMap;
struct MethodProperty {
bool is_builtin_service;
bool own_method_status;
// Parameters which have nothing to do with management of services, but
// will be used when the service is queried.
struct OpaqueParams {
bool is_tabbed;
bool allow_default_url;
bool allow_http_body_to_pb;
bool pb_bytes_to_base64;
bool pb_single_repeated_to_array;
bool enable_progressive_read;
OpaqueParams();
};
OpaqueParams params;
// NULL if service of the method was never added as restful.
// "@path1 @path2 ..." if the method was mapped from paths.
std::string* http_url;
google::protobuf::Service* service;
const google::protobuf::MethodDescriptor* method;
MethodStatus* status;
AdaptiveMaxConcurrency max_concurrency;
MethodProperty();
};
typedef butil::FlatMap<std::string, MethodProperty> MethodMap;
struct ThreadLocalOptions {
bthread_key_t tls_key;
const DataFactory* thread_local_data_factory;
ThreadLocalOptions()
: tls_key(INVALID_BTHREAD_KEY)
, thread_local_data_factory(NULL) {}
};
public:
Server(ProfilerLinker = ProfilerLinker());
~Server();
// A set of functions to start this server.
// Returns 0 on success, -1 otherwise and errno is set appropriately.
// Notes:
// * Default options are taken if `opt' is NULL.
// * A server can be started more than once if the server is completely
// stopped by Stop() and Join().
// * port can be 0, which makes kernel to choose a port dynamically.
// Start on an address in form of "0.0.0.0:8000".
int Start(const char* ip_port_str, const ServerOptions* opt);
int Start(const butil::EndPoint& ip_port, const ServerOptions* opt);
// Start on IP_ANY:port.
int Start(int port, const ServerOptions* opt);
// Start on `ip_str' + any useable port in `range'
int Start(const char* ip_str, PortRange range, const ServerOptions *opt);
// Start on IP_ANY + first useable port in `range'
int Start(PortRange range, const ServerOptions* opt);
// NOTE: Stop() is paired with Join() to stop a server without losing
// requests. The point of separating them is that you can Stop() multiple
// servers before Join() them, in which case the total time to Join is
// time of the slowest Join(). Otherwise you have to Join() them one by
// one, in which case the total time is sum of all Join().
// Stop accepting new connections and requests from existing connections.
// Returns 0 on success, -1 otherwise.
int Stop(int closewait_ms/*not used anymore*/);
// Wait until requests in progress are done. If Stop() is not called,
// this function NEVER return. If Stop() is called, during the waiting,
// this server responds new requests with `ELOGOFF' error immediately
// without calling any service. When clients see the error, they should
// try other servers.
int Join();
// Sleep until Ctrl-C is pressed, then stop and join this server.
// CAUTION: Don't call signal(SIGINT, ...) in your program!
// If signal(SIGINT, ..) is called AFTER calling this function, this
// function may block indefinitely.
void RunUntilAskedToQuit();
// Add a service. Arguments are explained in ServiceOptions above.
// NOTE: Adding a service while server is running is forbidden.
// Returns 0 on success, -1 otherwise.
int AddService(google::protobuf::Service* service,
ServiceOwnership ownership);
int AddService(google::protobuf::Service* service,
ServiceOwnership ownership,
const butil::StringPiece& restful_mappings,
bool allow_default_url = false);
int AddService(google::protobuf::Service* service,
const ServiceOptions& options);
// Remove a service from this server.
// NOTE: removing a service while server is running is forbidden.
// Returns 0 on success, -1 otherwise.
int RemoveService(google::protobuf::Service* service);
// Remove all services from this server.
// NOTE: clearing services when server is running is forbidden.
void ClearServices();
// Dynamically add a new certificate into server. It can be called
// while the server is running, but it's not thread-safe by itself.
// Returns 0 on success, -1 otherwise.
int AddCertificate(const CertInfo& cert);
// Dynamically remove a former certificate from server. Can be called
// while the server is running, but it's not thread-safe by itself.
// Returns 0 on success, -1 otherwise.
int RemoveCertificate(const CertInfo& cert);
// Dynamically reset all certificates except the default one. It can be
// called while the server is running, but it's not thread-safe by itself.
// Returns 0 on success, -1 otherwise.
int ResetCertificates(const std::vector<CertInfo>& certs);
// Find a service by its ServiceDescriptor::full_name().
// Returns the registered service pointer, NULL on not found.
// Notice that for performance concerns, this function does not lock service
// list internally thus races with AddService()/RemoveService().
google::protobuf::Service*
FindServiceByFullName(const butil::StringPiece& full_name) const;
// Find a service by its ServiceDescriptor::name().
// Returns the registered service pointer, NULL on not found.
// Notice that for performance concerns, this function does not lock service
// list internally thus races with AddService()/RemoveService().
google::protobuf::Service*
FindServiceByName(const butil::StringPiece& name) const;
// Put all services registered by user into `services'
void ListServices(std::vector<google::protobuf::Service*>* services);
// Get statistics of this server
void GetStat(ServerStatistics* stat) const;
// Get the options passed to Start().
const ServerOptions& options() const { return _options; }
// Status of this server.
Status status() const { return _status; }
// Return true iff this server is serving requests.
bool IsRunning() const { return status() == RUNNING; }
// Return the first service added to this server. If a service was once
// returned by first_service() and then removed, first_service() will
// always be NULL.
// This is useful for some production lines whose protocol does not
// contain a service name, in which case this service works as the
// default service.
google::protobuf::Service* first_service() const
{ return _first_service; }
// Set version string for this server, will be shown in /version page
void set_version(const std::string& version) { _version = version; }
const std::string& version() const { return _version; }
// Return the address this server is listening
butil::EndPoint listen_address() const { return _listen_addr; }
// Last time that Start() was successfully called. 0 if Start() was
// never called
time_t last_start_time() const { return _last_start_time; }
SimpleDataPool* session_local_data_pool() const { return _session_local_data_pool; }
const ThreadLocalOptions& thread_local_options() const { return _tl_options; }
// Print the html code of tabs into `os'.
// current_tab_name is the tab highlighted.
void PrintTabsBody(std::ostream& os, const char* current_tab_name) const;
// This method is already deprecated.You should NOT call it anymore.
int ResetMaxConcurrency(int max_concurrency);
// Get/set max_concurrency associated with a method.
// Example:
// server.MaxConcurrencyOf("example.EchoService.Echo") = 10;
// or server.MaxConcurrencyOf("example.EchoService", "Echo") = 10;
// or server.MaxConcurrencyOf(&service, "Echo") = 10;
// Note: These interfaces can ONLY be called before the server is started.
// And you should NOT set the max_concurrency when you are going to choose
// an auto concurrency limiter, eg `options.max_concurrency = "auto"`.If you
// still called non-const version of the interface, your changes to the
// maximum concurrency will not take effect.
AdaptiveMaxConcurrency& MaxConcurrencyOf(const butil::StringPiece& full_method_name);
int MaxConcurrencyOf(const butil::StringPiece& full_method_name) const;
AdaptiveMaxConcurrency& MaxConcurrencyOf(const butil::StringPiece& full_service_name,
const butil::StringPiece& method_name);
int MaxConcurrencyOf(const butil::StringPiece& full_service_name,
const butil::StringPiece& method_name) const;
AdaptiveMaxConcurrency& MaxConcurrencyOf(google::protobuf::Service* service,
const butil::StringPiece& method_name);
int MaxConcurrencyOf(google::protobuf::Service* service,
const butil::StringPiece& method_name) const;
int Concurrency() const {
return butil::subtle::NoBarrier_Load(&_concurrency);
};
// Returns true if accept request, reject request otherwise.
bool AcceptRequest(Controller* cntl) const;
bool has_progressive_read_method() const {
return this->_has_progressive_read_method;
}
private:
friend class StatusService;
friend class ProtobufsService;
friend class ConnectionsService;
friend class BadMethodService;
friend class ServerPrivateAccessor;
friend class PrometheusMetricsService;
friend class Controller;
int AddServiceInternal(google::protobuf::Service* service,
bool is_builtin_service,
const ServiceOptions& options);
int AddBuiltinService(google::protobuf::Service* service);
// Remove all methods of `service' from internal structures.
void RemoveMethodsOf(google::protobuf::Service* service);
int AddBuiltinServices();
// Initialize internal structure. Initializtion is
// ensured to be called only once
int InitializeOnce();
int InitALPNOptions(const ServerSSLOptions* options);
// Create acceptor with handlers of protocols.
Acceptor* BuildAcceptor();
int StartInternal(const butil::EndPoint& endpoint,
const PortRange& port_range,
const ServerOptions *opt);
// Number of user added services, not counting builtin services.
size_t service_count() const {
return _fullname_service_map.size() -
_builtin_service_count -
_virtual_service_count;
}
// Number of builtin services.
size_t builtin_service_count() const { return _builtin_service_count; }
static void* UpdateDerivedVars(void*);
void GenerateVersionIfNeeded();
void PutPidFileIfNeeded();
const MethodProperty*
FindMethodPropertyByFullName(const butil::StringPiece& fullname) const;
const MethodProperty*
FindMethodPropertyByFullName(const butil::StringPiece& full_service_name,
const butil::StringPiece& method_name) const;
const MethodProperty*
FindMethodPropertyByNameAndIndex(const butil::StringPiece& service_name,
int method_index) const;
const ServiceProperty*
FindServicePropertyByFullName(const butil::StringPiece& fullname) const;
const ServiceProperty*
FindServicePropertyByName(const butil::StringPiece& name) const;
std::string ServerPrefix() const;
// Mapping from hostname to corresponding SSL_CTX
typedef butil::CaseIgnoredFlatMap<std::shared_ptr<SocketSSLContext> > CertMap;
struct CertMaps {
CertMap cert_map;
CertMap wildcard_cert_map;
};
struct SSLContext {
std::shared_ptr<SocketSSLContext> ctx;
std::vector<std::string> filters;
};
// Mapping from [certificate + private-key] to SSLContext
typedef butil::FlatMap<std::string, SSLContext> SSLContextMap;
void FreeSSLContexts();
static int SSLSwitchCTXByHostname(struct ssl_st* ssl,
int* al, void* se);
static bool AddCertMapping(CertMaps& bg, const SSLContext& ssl_ctx);
static bool RemoveCertMapping(CertMaps& bg, const SSLContext& ssl_ctx);
static bool ResetCertMappings(CertMaps& bg, const SSLContextMap& ctx_map);
static bool ClearCertMapping(CertMaps& bg);
AdaptiveMaxConcurrency& MaxConcurrencyOf(MethodProperty*);
int MaxConcurrencyOf(const MethodProperty*) const;
static bool CreateConcurrencyLimiter(const AdaptiveMaxConcurrency& amc,
ConcurrencyLimiter** out);
template <typename T>
int SetServiceMaxConcurrency(T* service) {
if (NULL != service) {
const AdaptiveMaxConcurrency* amc = &service->_max_concurrency;
if (amc->type() == AdaptiveMaxConcurrency::UNLIMITED()) {
amc = &_options.method_max_concurrency;
}
ConcurrencyLimiter* cl = NULL;
if (!CreateConcurrencyLimiter(*amc, &cl)) {
LOG(ERROR) << "Fail to create ConcurrencyLimiter for method";
return -1;
}
service->_status->SetConcurrencyLimiter(cl);
}
return 0;
}
DISALLOW_COPY_AND_ASSIGN(Server);
// Put frequently-accessed data pool at first.
SimpleDataPool* _session_local_data_pool;
ThreadLocalOptions _tl_options;
Status _status;
int _builtin_service_count;
// number of the virtual services for mapping URL to methods.
int _virtual_service_count;
bool _failed_to_set_max_concurrency_of_method;
Acceptor* _am;
Acceptor* _internal_am;
// Use method->full_name() as key
MethodMap _method_map;
// Use service->full_name() as key
ServiceMap _fullname_service_map;
// In order to be compatible with some RPC framework that
// uses service->name() to designate an RPC service
ServiceMap _service_map;
// The only non-builtin service in _service_map, otherwise NULL.
google::protobuf::Service* _first_service;
// Store TabInfo of services inheriting Tabbed.
TabInfoList* _tab_info_list;
// Store url patterns for paths without exact service names, examples:
// *.flv => Method
// abc* => Method
RestfulMap* _global_restful_map;
// Default certificate which can't be reloaded
std::shared_ptr<SocketSSLContext> _default_ssl_ctx;
// Reloadable SSL mappings
butil::DoublyBufferedData<CertMaps> _reload_cert_maps;
// Holds the memory of all SSL_CTXs
SSLContextMap _ssl_ctx_map;
ServerOptions _options;
butil::EndPoint _listen_addr;
// ALPN extention protocol-list format. Server initialize this with alpns options.
// OpenSSL API use this variable to avoid conversion at each handshake.
std::string _raw_alpns;
std::string _version;
time_t _last_start_time;
bthread_t _derivative_thread;
bthread_keytable_pool_t* _keytable_pool;
// mutable is required for `ServerPrivateAccessor' to change this bvar
mutable bvar::Adder<int64_t> _nerror_bvar;
mutable bvar::PerSecond<bvar::Adder<int64_t> > _eps_bvar;
BAIDU_CACHELINE_ALIGNMENT mutable int32_t _concurrency;
bvar::PassiveStatus<int32_t> _concurrency_bvar;
bool _has_progressive_read_method;
};
// Get the data attached to current searching thread. The data is created by
// ServerOptions.thread_local_data_factory and reused between different threads.
// If ServerOptions.thread_local_data_factory is NULL, return NULL.
// If this function is not called inside a server thread, return NULL.
void* thread_local_data();
// Test if a dummy server was already started.
bool IsDummyServerRunning();
// Start a dummy server listening at `port'. If a dummy server was already
// running, this function does nothing and fails.
// NOTE: The second parameter(ProfilerLinker) is for linking of profiling
// functions when corresponding macros are defined, just ignore it.
// Returns 0 on success, -1 otherwise.
int StartDummyServerAt(int port, ProfilerLinker = ProfilerLinker());
} // namespace brpc
#endif // BRPC_SERVER_H