It is a HTTP server based on NIO framework Netty that provide handle HTTP requests and store information about them in the data base.
ServerInitializer- provides helpful server initialization and some configurations.ServerHttpRequestHandler- main server handler which process HTTP requests and based on that construct responses.ServerConnectionCountHandler- provides counting of all and current connections to the server.ServerTrafficHandler- provides a count of input/output data.ServerDataBaseCleaner- monitors the "purity" of the database.HttpObjectAggregator- provides handle only full HTTP messages and be okay with some memory overhead.HttpServerCodec- provides decode HTTP requests from clients/decode HTTP response for clients.
http://localhost:{port}/helloserver wait 10 second and that sends response with HTML page which contains "Hello World" string.http://localhost:{port}/redirect?url=<url>server redirect client to specified<url>.http://localhost:{port}/statusserver sends response with HTML page which contains server status.http://localhost:{port}/{smth.another}server sends response with ERROR 404 HTML page.
To configure the server port use
~/config/server-config.properties. All path registration occurs in PathRegistry interface.
To provide all of these functions, the handler uses a Controller. The controller gets a path that a client specified and returns a content of a corresponds page. There are three type of Page:
- HelloPage contains "Hello Word!" string.
- StatusPage contains server statistic: number of all requests, number of unique requests from IP, number of current connections, table with unique requests, table with redirect information and table with information about last connections(by default table have 3, 3, 16 rows corresponds).
Also if the path is /redirect?url=<url>, the controller can
prepare a <url> for handler. All responses sends the handler.
The counter based on ChannelTrafficShapingHandler.
It is has two AtomicInteger
variables: CURRENT_CONNECTION_COUNT and ALL_CONNECTION_COUNT which count current connections and
all connections to server corresponds. Also handler provides two methods that provides getting numbers from this
inner counters.
This handler has only one public constructor without and arguments. By default inner variable
CHECK_INTERVAL = 0, it's mean that handler doesn't call withdoAccounting()method.
This handler provides database cleaning. It is the child of ChannelTrafficShapingHandler.
When a method doAccounting(...) works, inner DBManager
cleans storage. Also you can configure cleaning interval(cleanInterval) and how many rows the cleaner left in table(leftRows)
via handler constructor. By default cleanInterval = 1000 milliseconds, leftRows = 16, but you can save more rows in storage on your opinion if you want to save more information about last connections.
Also you can turn off the cleaner if initialize
cleanInterval = 0, in this case methoddoAccounting(...)and do not calls.
#####A little bit about server storage
The server uses H2DataBase
in-memory mode to store data about a server status.
To store and retrieve data the server uses HikariCP,
it is a "zero-overhead" production ready JDBC connection pool and very comfortable in work.
Also you can configure server storage by ~/config/db-config.properties.
For example - switch DB mode to embedded and save all server status information in one file,
configure path to DB, user name/password, max connection pool size. To provide more flexibility, the server
have a DAO layer based on the Factory Method design pattern. The DAO layer have two dao interfaces - ConnectDao
and RedirectDao implementations of which provide communication with DB(H2ConnectDao, H2RedirectDao).
In the improved server version we are have three DAO.
Each time before the server start, DBManager prepares the database.
This counter specialized on counting received and sent data by server. Also handler calculates the speed of each connection and stores all data in the database using H2ConnectDao.
This handler has only one public constructor without and arguments. By default inner variable
CHECK_INTERVAL = 0, it's mean that handler doesn't call withdoAccounting()method.
####Additional The Server has two branches:
master- implementation totally based on data base, so we can't get all unique requests via saving all connections to data base, after a little bit time server will start work very slowly. But in this case we can get all number of connections correctly, ofc. it's in my implementation, and ofc. it's not best way.unique-request-dao- (improved version) in this case I had implemented count number of unique request viaHashMapand one synchronized method, so now we may see correct unique requests counting. To do that I changedServerConnectionCountHandlerand create new DAO -UniqueReqDaofor more flexibility. This DAO gets all information about unique requests to the server fromServerConnectionCountHandler.
In folder
~/screenshotsyou can find results of the server test for two cases which was considered above.
Also server has some classes helpers:
- ConfigReader -
provides reading
.propertiesconfigurations files. - DBUtil - provides static methods that helps to close the database Connection, PreparedStatement, Statement and ResultSet.