I'm developing a simple assignment using Apache Thrift and the C++ POCO
library. The assignment requires me to make a benchmark by creating multiple concurrent threads make the same request to the Thrift TThreadPoolServer
.
This is my client-side code, where I creates 10 concurrent threads, all of them make the same GET
request (request info from only one user D
) to the server:
// define a MyWorker class which inherits Runnable
class MyWorker : public Runnable {
public:
MyWorker(int k = -1) : Runnable(), n(k) {
}
void run() {
// create connection
boost::shared_ptr<TTransport> socket(new TSocket("localhost", 9090));
boost::shared_ptr<TTransport> transport(new TBufferedTransport(socket));
boost::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
APIsClient client(protocol);
try {
transport->open();
int res = -1;
// make the request
res = client.get("D");
printf("Thread %d, res = %d \n", n, res);
transport->close();
} catch (TException te) {
cout << te.what() << endl;
}
}
private:
int n;
};
void handleBenchmarkTest(const std::string& name, const std::string& value) {
//TODO!
const int N = 10;
MyWorker w[N];
for (int i = 0; i < N; i++) w[i] = MyWorker(i);
Thread t[N];
for (int i = 0; i < N; i++) t[i].start(w[i]);
for (int i = 0; i < N; i++) t[i].join(); // wait for all threads to end
cout << endl << "Threads joined" << endl;
}
I implemented my server using TThreadPoolServer
. This is the the handler function when the server receive a GET
request:
// this function make use of POCO::Data
int getRequest(const std::string& _username) {
int res = -1;
Statement select(*mySQLsession);
std::string match("'" + _username + "'");
select << "SELECT counter FROM view_count_info WHERE username = " + match + " LIMIT 1;", into(res);
select.execute();
return res;
}
Above are all of my codes. When I run the client-side benchmark app, this is what returned:
MySQL // from the try-catch block above
MySQL // from the try-catch block above
Thread 2, res = -1 // expected result
MySQL // from the try-catch block above
Thrift: Fri Jun 26 15:54:05 2015 TSocket::read() recv() <Host: localhost Port: 9090>Connection reset by peer
No more data to read.
THRIFT_ECONNRESET
No more data to read.
No more data to read.
Thrift: Fri Jun 26 15:54:05 2015 TSocket::read() recv() <Host: localhost Port: 9090>Connection reset by peer
THRIFT_ECONNRESET
Thrift: Fri Jun 26 15:54:05 2015 TSocket::read() recv() <Host: localhost Port: 9090>Connection reset by peer
THRIFT_ECONNRESET
Threads joined
In the server, the result is:
2015-06-26 08:54:00 : > Server is running
2015-06-26 08:54:05 : handle GET request
D
2015-06-26 08:54:05 : handle GET request
D
2015-06-26 08:54:05 : handle GET request
D
-1
2015-06-26 08:54:05 : handle GET request
2015-06-26 08:54:05 : handle GET request
D
2015-06-26 08:54:05 : handle GET request
D
2015-06-26 08:54:05 : handle GET request
D
D
RUN FINISHED; Segmentation fault; core dumped; real time: 5s; user: 0ms; system: 0ms
I don't know why this happened. One more thing, when I try to change to not use MySQL request in the server side (instead I just return a random integer for each request), the app runs well without any errors or warning. So I guess the problem here is with the MySQL database. It does work if I only make 1 request at a time, but something goes wrong when there are multiple, concurrent GET
requests are made.
Thanks to @JensG, I found out that the problem here is because I used a global variable
mySQLsession
to handle all the MySQL database requests, which causes threads conflict. Thanks you all again !