halitpeker / servicestack

Automatically exported from code.google.com/p/servicestack
0 stars 0 forks source link

Highload usage #25

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
I have not found any forum to ask, so I'll ask here.
We have site with highload usage (300K+ visitors day).
We want to use redis to store statistics data.
Now I have problem with multi simultaneous request.
First I've used one static field
private static RedisClient _RedisClient  = new RedisClient()
but this gives us error "Unknown reply on integer response: 547, sPort: 3112, 
LastCommand:"

Then I change it to field
private RedisClient _RedisClient  = _BasicRedisClientManager.GetClient();
But this give us that server runs out of socket connection and it shut down.

Then I change it to using constuction, when i need redisconnection 
using (var RedisClient = _BasicRedisClientManager.GetClient())
{}
server is running, but I started to receive error
"Only one usage of each socket address (protocol/network address/port) is 
normally permitted 127.0.0.1:6379"

Can you tell how to use RedisClient in right way, when there are many 
simultaneous connections.

Original issue reported on code.google.com by okhotny on 26 Jul 2010 at 7:49

GoogleCodeExporter commented 9 years ago
Hi,

You're on the right track with your last example, you want to keep a static 
instance of a client manager like BasicRedisClientManager or 
PooledRedisClientManager. 

In the constructor you want to specify the host/port address like:

redisManager = new BasicRedisClientManager("RedisHostnameOrIpAddress:6379");

and then in your client code just do as you were doing before, i.e.:

using (var redis = redisManager.GetClient())
{
   //and away you go
}

So it basically works like most connection pools, where the connection pool 
manager is thread safe but the single IRedisClient is not.

Let me know if that helps?

- Demis

Original comment by demis.be...@gmail.com on 26 Jul 2010 at 12:26

GoogleCodeExporter commented 9 years ago
Now I've 
public class RedisGetter
{
static readonly BasicRedisClientManager _BasicRedisClientManager;
static RedisGetter()
{
_BasicRedisClientManager = new BasicRedisClientManager("127.0.0.1:6379");
}

and then use using block mentioned above
redis server console shows that number of clients connected is not continuously 
growing, but at the end i've recevied error: "Only one usage of each socket 
address (protocol/network address/port) is normally permitted 127.0.0.1:6379"

Original comment by okhotny on 26 Jul 2010 at 12:34

GoogleCodeExporter commented 9 years ago
So can you show me how you're using it? is it like:

using (var redis = _BasicRedisClientManager.GetClient()) //connection is 
created here
{
   //...

} //connection is terminated here

Cause each time the using statement ends, it should dispose of it. Also 
'RedisGetter' should be either be a singleton or you should ensure you only 
have one instance of it (a static class would work too).

We're using the BasicRedisClientManager for production as well for handling 
most of mflow.com's traffic and we're not encountering this issue. Although 
we're accessing the single instance of 'BasicRedisClientManager' through an IOC 
- tho it doesn't really matter how you're accessing it as both approaches 
should work.

The difference between the 'BasicRedisClientManager' and the 
'PooledRedisClientManager' is that the former creates a new connection when you 
call '_BasicRedisClientManager.GetClient()' which terminates the connection 
when it reaches the end of the using scope while the latter just places the 
connection back on the pool but you get to control how many open connections 
you want based on the 'PooledRedisClientManager.MaxWritePoolSize'. Again it 
really shouldn't matter which one you use, just that you're accessing the right 
way (i.e. inside the using statement block).

If its possible do you think you can create a self-contained test-case that 
exhibits this issue, that way I can see and diagnose the issue from here.

- Demis

Original comment by demis.be...@gmail.com on 26 Jul 2010 at 12:57

GoogleCodeExporter commented 9 years ago
Here is error:
[SocketException (0x2740): Only one usage of each socket address 
(protocol/network address/port) is normally permitted 127.0.0.1:6379]
   System.Net.Sockets.Socket.Connect(IPAddress[] addresses, Int32 port) +1551089
   System.Net.Sockets.Socket.Connect(String host, Int32 port) +128
   ServiceStack.Redis.RedisNativeClient.Connect() +95

[InvalidOperationException: could not connect to redis Instance at 
127.0.0.1:6379]
   ServiceStack.Redis.RedisNativeClient.Connect() +616
   ServiceStack.Redis.RedisNativeClient.AssertConnectedSocket() +138
   ServiceStack.Redis.RedisNativeClient.SendCommand(Byte[][] cmdWithBinaryArgs) +41
   ServiceStack.Redis.RedisNativeClient.SendExpectData(Byte[][] cmdWithBinaryArgs) +15
   ServiceStack.Redis.RedisNativeClient.GetBytes(String key) +85
   ServiceStack.Redis.RedisClient.GetValue(String key) +8
   RedisBanner.RedisGetter.BannerCountClick(Banner val) in D:\Hunter\Мои документы\Visual Studio 2008\Projects\RedisBanner\RedisBanner\RedisGetter.cs:173

Here is code:
public static class RedisGetter
    {
        private static readonly BasicRedisClientManager _BasicRedisClientManager;

        static RedisGetter()
        {
            _BasicRedisClientManager = new BasicRedisClientManager("127.0.0.1:6379");
        }
    private static int BannerCountClick(Banner val)
        {
            int t = 0;
            using (var RedisClient = _BasicRedisClientManager.GetClient())
            {
                int.TryParse(RedisClient.GetValue(string.Format("stat:banners:{0}:ClickCount", val.Id)), out t);
            }
            return t;
        }
}

Original comment by okhotny on 26 Jul 2010 at 1:39

GoogleCodeExporter commented 9 years ago
at server console:
it reports that current 0 active clients,
and it accepts new connection with incremented port numbers.
it works for some time, and then fails for most requests, but some requests are 
passing.

Original comment by okhotny on 26 Jul 2010 at 1:54