The Socket API, Part 3: Concurrent Servers

现场报错如下:

转:

Process 0:0:0 (0x1ffc) Worker 0x00000001E580A1A0 appears to be non-yielding on Scheduler 3. Thread creation time: 13153975602106. 
Approx Thread CPU Used: kernel 0 ms, user 0 ms. Process Utilization 21%. System Idle 76%. Interval: 73616 ms.

 

从报错来看是有些worker占用scheduler不释放引致,服务器材体的scheduler个数能够从sys.dm_os_sys_info.scheduler_count列中看出,常常的话服务器也就那二个核数,在这之中即使被non-yeilding的worker持久占用部分,将可能形成特别沉痛的性格难点。引发此主题素材的案由经常是少数查询并行度非常高的SQL,也与多少个BUG有关,最近从一些文档来看,此BUG并未有被排除,详见:

By Pankaj
Tanwar on October 1,
2011
in Coding, Developers · 2
Comments

从二〇〇八年SQL
Server二〇〇七开头,到前年五月SQL Server
二零一四版本那个难点依然应诉知,微软并未有提交显然的消弭办法。

图片 1

因此方今必须要在产出难点后登时寻找相关的SQL优化,何况经过改换查询调整器只怕并行查询阈值来防止难题现身。

In
this part of the series, we will learn how to deal with multiple clients
connected to the server.

从官方网址的降解来看:那是一个微软winsock
API自个儿的BUG。

Welcome
to another dose of socket programming! Till now, we’ve created servers
that are capable of creating connections with multiple clients [Part
1 & Part
2],
but the problem is that the server will communicate with only one client
at any point in time. This is because there is only one socket
descriptor, cfd, created to communicate with a client — and all
connections will wait on the same descriptor. Now, let’s use
the fork() system call to fork a copy of the server for each
client.

 

Here is
the code included from the previous article. This time it is for
IPv4…

I
am with the SQL Protocols Dev team. I’ve looked at the issue and most
likely it is related to the creation of child processes from within SQL
Server – e.g.
xp_cmdshell,
3rd party backup or compression software, etc. The problem occurs due to
a limitation of the Winsock API which does not offer creation of

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <signal.h>
 
int main()
{
    int sfd, cfd;
    socklen_t len;
    char ch, buff[INET_ADDRSTRLEN];
    struct sockaddr_in saddr, caddr;
 
    sfd= socket(AF_INET, SOCK_STREAM, 0);
 
    saddr.sin_family=AF_INET;
    saddr.sin_addr.s_addr=htonl(INADDR_ANY);
    saddr.sin_port=htons(1205);
 
    bind(sfd, (struct sockaddr *)&saddr, sizeof(saddr));
 
    listen(sfd, 5);
    signal(SIGCHLD, SIG_IGN);
 
    while(1) {
        printf("Server waiting\n");
        len=sizeof(caddr);
        cfd=accept(sfd, (struct sockaddr *)&caddr, &len);
 
        if( fork() == 0) {
            printf("Child Server Created Handling connection with %s\n",
                inet_ntop(AF_INET, &caddr.sin_addr, buff, sizeof(buff)));
 
            close(sfd);
 
            if(read(cfd, &ch, 1)<0) perror("read");
 
            while( ch != EOF) {
                if((ch>='a' && ch<='z') || (ch>='A' && ch<='Z'))
                ch^=0x20;  
                    /* EXORing 6th bit will result in change in case */
 
                if(write(cfd, &ch, 1)<0) perror("write");
 
                if(read(cfd, &ch, 1)<0) perror("read");
            }
            close(cfd);
            return 0;
 
        }
 
        close(cfd);
    }
}

non-inheritable
socket handles. If a child process of SQL Server is created after a
connected socket is created and before the inheritance flag of the

Let’s
see what we’ve done here. At line 23, after getting the socket
descriptor cfd from the call to accept, we forked the server. The
child process (where pid==0) closes the listening descriptor
with close(sfd), does the work the server is intended to do, and when
finished, closes the descriptor and returns (see lines 27-39).

socket
is cleared, the child process inherits the socket handle. When closing
the corresponding client connection, a proper Tcp cleanup cannot be
performed
before
the child process of SQL Server is closed.

The
server, on the other hand, where pid>0, just closes the cfd (line
39), and is again ready to accept more connections. Thus, for each
incoming connection, a new server process will be created.

To
implement a temporary workaround, add the TcpAbortiveClose SQL parameter
to registry as described in KB article
.
Please
be careful if you are doing this on a cluster to avoid checkpoint issue
and registry misconfiguration which would prevent SQL from coming
online.
SQL
Server needs to be restarted in order the changes to take effect. No
significant perf impact is expected from the change, no functional
impact should be either.

Another
method of doing this is using threads, but we’re not getting into that
right now.

 

Now,
compile, run and see the server running and handling multiple clients.
See Figure 1 — I’m running the server on a network now (;) though these
clients are VirtualBox running VMs with Backtrack (192.168.1.19) and
Arch (192.168.1.4), and Android phone running ConnectBot to create a TCP
connection.

  

图片 2