/* * 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 THRIFT_UTIL_TNONBLOCKINGSERVERCREATOR_H_ #define THRIFT_UTIL_TNONBLOCKINGSERVERCREATOR_H_ 1 #include "thrift/lib/cpp/util/ServerCreatorBase.h" #include "thrift/lib/cpp/server/TNonblockingServer.h" #include "thrift/lib/cpp/transport/TSocket.h" namespace apache { namespace thrift { class TProcessor; namespace util { class TNonblockingServerCreator : public ServerCreatorBase { public: typedef server::TNonblockingServer ServerType; /// Use 8 task threads by default. static const size_t DEFAULT_NUM_TASK_THREADS = 8; /// Use 1 I/O thread by default. static const size_t DEFAULT_NUM_IO_THREADS = 1; /** * By default, just run the I/O threads with the same priority as other * threads. */ static const bool DEFAULT_HI_PRI_IO_THREADS = false; /// Default limit on the size of the idle connection pool static const size_t DEFAULT_CONN_STACK_LIMIT = 1024; /// Default limit on the total number of connected sockets static const size_t DEFAULT_MAX_CONNECTIONS = INT_MAX; /// Default limit on the number of outstanding requests static const size_t DEFAULT_MAX_ACTIVE_PROCESSORS = INT_MAX; /** * By default, reject requests over 256MB. * * This avoids allocating giant buffers if a client sends a bogus frame * length. */ static const size_t DEFAULT_MAX_FRAME_SIZE = 256 * 1024 * 1024; /// Default overload hysteresis fraction static const double DEFAULT_HYSTERESIS_FRACTION; /** * Default overload action. * * TODO: None of the TNonblockingServer OverloadAction behaviors seem like * reasonable defaults. If the overload is occurring because we hit the * maxConnections limit, it seems like the best behavior is to try and close * idle connections. If the overload is occurring due to the * maxActiveProcessors limit, it seems like the best behavior may be to stop * calling accept() and stop reading on sockets until the # of active * processors drops to a reasonable limit. */ static const server::TOverloadAction DEFAULT_OVERLOAD_ACTION = server::T_OVERLOAD_NO_ACTION; /** * By default, give up on a request if we can't find a thread to process it * within 30 seconds. */ static const int64_t DEFAULT_TASK_EXPIRE_TIME = 30000; /// Default size of write buffer static const size_t DEFAULT_WRITE_BUFFER_SIZE = 1024; /// Maximum size of read buffer allocated to each idle connection static const size_t DEFAULT_IDLE_READ_BUF_LIMIT = 8192; /// Maximum size of write buffer allocated to each idle connection static const size_t DEFAULT_IDLE_WRITE_BUF_LIMIT = 8192; /** * By check to see if we should shrink oversized read/write buffers after * every 64 calls on connection. */ static const int DEFAULT_RESIZE_EVERY_N = 64; /// listen backlog static const size_t DEFAULT_LISTEN_BACKLOG = 1024; /** * Create a new TNonblockingServerCreator. */ TNonblockingServerCreator(const boost::shared_ptr& processor, uint16_t port, size_t numTaskThreads = DEFAULT_NUM_TASK_THREADS); /** * Set the number of threads to use for processing requests. * * Setting this to 0 causes all requests to be processed in the I/O * thread(s). You should only set this to 0 if the handler responds to all * requests immediately, without ever blocking. */ void setNumTaskThreads(size_t numThreads) { numTaskThreads_ = numThreads; } /** * Set the ThreadFactory to use for creating the task threads. */ void setTaskThreadFactory( const boost::shared_ptr& threadFactory) { taskThreadFactory_ = threadFactory; } /** * Set the number of threads to use for performing I/O. */ void setNumIOThreads(size_t numThreads) { numIOThreads_ = numThreads; } /** * Set whether or not the I/O threads should be given a higher scheduling * priority. */ void setUseHighPriorityIOThreads(bool useHiPri) { useHiPriIOThreads_ = useHiPri; } /** * Set the maximum number of TConnection objects to cache. * * By default, when a connection is closed TNonblockingServer caches the * TConnection object and re-uses it when a new connection comes in, instead * of deleting it and allocating a new one for the next connection. This * value caps the number of unused TConnection objects that will be cached. */ void setConnectionStackLimit(size_t limit) { connectionStackLimit_ = limit; } /// Set the maximum number of open connections void setMaxConnections(size_t maxConnections) { maxConnections_ = maxConnections; } /// Set the maximum number of active requests void setMaxActiveProcessors(size_t maxActiveProcessors) { maxActiveProcessors_ = maxActiveProcessors; } /// Set the maximum allowed request frame size. void setMaxFrameSize(size_t maxFrameSize) { maxFrameSize_ = maxFrameSize; } /// Set the overload hysteresis fraction void setOverloadHysteresis(double hysteresisFraction) { hysteresisFraction_ = hysteresisFraction; } /// Set the overload action void setOverloadAction(server::TOverloadAction action) { overloadAction_ = action; } /** * Set the task expiration time. * * If no task thread is available to process a request within taskExpireTime * milliseconds, close the connection rather than continuing to wait for a * thread. If the server is overloaded, this prevents it from processing * old requests that the client has already given up on. */ void setTaskExpireTime(int64_t taskExpireTime) { taskExpireTime_ = taskExpireTime; } /** * Set the socket options to use for accepted connections */ void setSocketOptions(const transport::TSocket::Options& options) { socketOptions_ = options; } /// Set the default write buffer size for new connections void setWriteBufferDefaultSize(size_t size) { defaultWriteBufferSize_ = size; } /** * Set the maximum read buffer size for idle connections. * * This value is checked when the connection is closed, and also every N * connections if setResizeBufferEveryN() has been set. If the read buffer * is larger than the allowed limit, free it. * * This prevents a single large request on a connection from continuing to * taking up a lot of buffer space. */ void setIdleReadBufferLimit(size_t limit) { idleReadBufferLimit_ = limit; } /** * Set the maximum write buffer size for idle connections. * * This value is checked when the connection is closed, and also every N * connections if setResizeBufferEveryN() has been set. If the write buffer * is larger than the allowed limit, free it. * * This prevents a single large response on a connection from continuing to * taking up a lot of buffer space. */ void setIdleWriteBufferLimit(size_t limit) { idleWriteBufferLimit_ = limit; } /// Check a connection's buffer size limits every count requests. void setResizeBufferEveryN(int32_t count) { resizeBufferEveryN_ = count; } /// listen backlog void setListenBacklog(int32_t listenBacklog) { listenBacklog_ = listenBacklog; } virtual boost::shared_ptr createServer(); boost::shared_ptr createNonblockingServer(); private: boost::shared_ptr processor_; uint16_t port_; size_t numTaskThreads_; size_t numIOThreads_; bool useHiPriIOThreads_; size_t connectionStackLimit_; size_t maxConnections_; size_t maxActiveProcessors_; size_t maxFrameSize_; double hysteresisFraction_; server::TOverloadAction overloadAction_; int64_t taskExpireTime_; size_t defaultWriteBufferSize_; size_t idleReadBufferLimit_; size_t idleWriteBufferLimit_; int32_t resizeBufferEveryN_; int32_t listenBacklog_; transport::TSocket::Options socketOptions_; boost::shared_ptr taskThreadFactory_; }; }}} // apache::thrift::util #endif // THRIFT_UTIL_TNONBLOCKINGSERVERCREATOR_H_