Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I already had question about this but obviously it was not accepted very well, apparently too long when it's actually more information so you could have given me better answer.

Ok, I will be much clearer now. Best possible logic to develop scalable chat in terms of stability, storing/reading messages on chat, updating chat on new message for all users etc.? I have most of this developed, the logic I think I miss is --> check if there is new message and show it for all users. I have this implemented but it crashes the site due to its traffic of 300k-400k people, so that's my main question.

The chat is PHP based and uses Pusher (www.pusher.com) for instant messaging but it lacks what I need because it's more like a websocket.


I'm using hardcoded files to keep messages (want to avoid database as much as possible). It's a no extension type of file, I'm sure you know. I'm getting crash with

$fp = fopen(..., "w"); // pretend ... is the path and filename
fwrite($fp, $msg); //hardcode the message
fclose($fp);

where $msg is the message itself. I'm having 1 file per message. I show last 150 messages = 150 file accesses and reads, yeah it's too much I guess. I have better logic now which I'm pursuing and that is 1 file with last 50-100 messages at all time. Sure it should be much better.

How does it crash, that's the trickiest part because everything seems ordinary, believe me it is difficult to determine what exactly crashes the site, but in like 5 minutes when I try to open the site it's gone, then I put the old content without chat and is back online again.

I'm having jquery post every 1 second to check if there is new message. I'm using timestamp in a special file where I keep the time last message was sent and if ((time() - time in file) <= 2) = reload last 150 messages including the last one. Too much input/output, write/read or however to say it I think is what crashes the site.

share|improve this question
    
How does it crash? –  MichaelT Jul 31 '13 at 2:09
    
I'm using hardcoded files to keep messages (want to avoid database as much as possible). It's a no extension type of file, I'm sure you know. I'm getting it with $fp = fopen(..., "w"); // pretend ... is the path and filename fwrite($fp, $msg); //hardcode the message fclose($fp); where $msg is the message itself. I'm having 1 file per message. I show last 150 messages = 150 file accesses and reads, yeah it's too much I guess. I have better logic now which I'm pursuing and that is 1 file with last 50-100 messages at all time. Sure it should be much better. And ideas or another approach? –  user2633999 Jul 31 '13 at 2:23
1  
Could you put that into the question itself (it can get hard to read things in messages). What I was wondering is you said that "it crashes the site" -- how does it crash? Is it out of memory? Out of network connections? doing disk IO to the point where everything crawls to a halt and times out? Something else? –  MichaelT Jul 31 '13 at 2:25
    
That's the trickiest part because everything seems ordinary, believe me it is difficult to determine what exactly crashes the site, but in like 5 minutes when I try to open the site it's gone, then I put the old content without chat and is back online again. I'm having jquery post every 1 second to check if there is new message. I'm using timestamp in a special file where I keep the time last message was sent and if ((time() - time in file) <= 2) = reload last 150 messages including the last one. Too much input/output, write/read or however to say it I think is what crashes the site. –  user2633999 Jul 31 '13 at 2:32
1  
MichaelT asked how does it crash, not what does crash it. You need shell access to the server to tell, but it shouldn't be too hard there. –  Jan Hudec Jul 31 '13 at 9:27

3 Answers 3

First of all, could you provide me with some clarification: are you coding a chat room (one-to-many) or individual (one-to-one) chats?

There are a couple of obvious flaws in your current system's design that I would like to point out. First, I'll start out with a brief analysis and then explain what is wrong with it and what you can do to fix it. Obviously if you want to run a successful project you should start from step one and get your hands dirty with systems analysis and design.

Problem

Website receives a high volume of traffic and eventually crashes.

Requirements

  1. Sustain high volume of web traffic
  2. Display previous 150 messages
  3. Secure communication pathway between clients

Problem Analysis

Right away it is obvious that your site is crashing because the code that opens the file is being called hundreds of thousands of times per second. Opening files and writing to them is very memory intensive.

The FILE Probem: Files do not handle concurrency very well at all. In fact, they're terrible with concurrency. Think about it like this, essentially you've opened the same file with notepad with hundreds of thousands of open windows/processes and you're changing the content in all of them simultaneously. When you try to solve a problem with this type of solution you end up with non-deterministic results. Basically, it is impossible to predict what data will be in the file.

Fortunately, there is a way to get deterministic results while still using files if you lock them properly. Unfortunately, this is not a solution to your problem. In your case, only one person would be able to send a message at a time. Surely that is NOT the solution you want!

Wait... there IS a solution:

You CAN USE a Database!

Databases are particularly good at solving this sort of concurrency issue! Depending on what database/engine you use your table may lock or only a single record might lock. In you case, I would suggest a free database like MySQL and a record-locking engine like InnoDB. If you're not a database rookie, you might want to look into MariaDB as well, it is a fork of the MySQL project by the original developer and is a binary drop in.

Basically, there is no way around it using a database for this type of solution. In fact, databases are very powerful and you can program procedures with them. From your query you can choose to select only 150 messages and then order them by most recent very easily. All users will be able to send messages at the same time with a record-locking database engine like InnoDB.

I would like to additionally point out that I would be a little troubled to find out what the code for the rest of the application looks like. It is very easy to write PHP code that looks fine but performs terribly. I'm not sure if you're familiar with asymptotic analysis or unit testing but I highly suggest that you thoroughly test your code before pushing it to production. Given the size of your userbase you should be concerned about code optimization and runtime. If your application/problem/solution was properly analyzed, designed, implemented, tested, and debugged you would have a much better handle on your problem.

It is also very easy to write code in PHP that is insecure. I would like to advise you to test your code thoroughly (try to break it) when writing modules that interact with the database. Poorly coded web applications can be very easy to exploit and given your user base of 300-400k I wouldn't doubt it if Cindy Lou Who suddenly decided to give it her own security audit. If a white hat hacker discovers the flaw in your system they will likely encourage you to fix it. If a black hat hacker discovers the flaw they will likely use it to spread malware and steal information.

share|improve this answer
2  
+1, its silly to not use a database of some sort in this type of situation. –  GrandmasterB Aug 21 '13 at 18:53

Personally in your case of High Traffic i would honestly try a redis server or some form of memory cache of the messages.

In any language from PHP web apps to desktop applications as soon as I know I might need to read something from a file more then 2 times in a second and the chance of it changing in that second is so low I cache the result. Caching helps a ton when looking at these kind of performance issues. HDD's always have the worst IO and on production servers I like using increased amounts of ram and cache where possible.

EDIT I would try and use Xdebug to analyse where my costly php functions are. I would also try another server and then a more powerful server. There is no point trying to run your website on a 1gig mem and 1 core cpu. You would need at lease a dedi and a couple cores.

If that does not work you could try clustering and using a redis server.

Also What you could try is increase the chat time to 4 or 5 seconds. Or look into customising the chat script to use web sockets.

share|improve this answer
    
You can also look into memcached –  Ludjer Aug 2 '13 at 6:01
    
this post is rather hard to read (wall of text). Would you mind editing it into a better shape? –  gnat Aug 2 '13 at 6:46
    
Thanks a lot for all answers. Here's the latest update. I'm using memcached to keep last 50-100 messages or so and even then the website crashes eventually. Sometimes it runs for hours, sometimes it's down in several minutes. Could it because of the heavy loads and memcached not being able to handle them since it's version 1.4.5. What to do next? Do you think having special server for the chat will solve the problem? For now I'm using the same server for chat where the main website is. Could this be bad? I know I'm very close to the solution, but still need a bit improvement... –  user2633999 Aug 5 '13 at 10:42
1  
what is the specs of your server and is there any errors or when it crashes. What is the load of the server when it crashes? The in memory caching should be easily able to handle the load I think it might be something else that is crashing it. Have you also tried it on another server? Also check exactly each item that is called. When dealing with high performance web sites every statement is costly. Look at xdebug the execution trace specifically and you can see where your costly calls are. –  Ludjer Aug 6 '13 at 12:16

What may be a good way to handle this is to insert data using php into a xml file that has the same structure as your mysql database.

Users would read the xml and thereby not force a php to do too much.

Every four days you could insert data from xml to database that is older than two days and clean up the xml file .

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.