Asynchronous request pool

Posted by fou2enve on Sun, 27 Feb 2022 14:35:04 +0100

Asynchronous request pool

What is the difference between synchronous and asynchronous?

Concept: it is the relationship between the two. For example, processes and processes, or clients and servers. Whether the request will be suspended and wait for return after being called or sent.

Synchronization: after calling the interface, the process will hang and wait for return. At this time, the two threads carry out this process at the same time, which is called synchronization

Asynchrony: after calling, the process will not hang and wait, but instead perform other tasks. When the result is returned, the process will be notified to receive and process it. At this time, the two processes do not perform this process at the same time, which is called asynchronous

Application scenario

When the business server accesses the business that needs to wait, the business access thread needs to wait and hang until the server gives feedback, such as requests for mysql,redis,http,dns and other services. The return of these requests needs to wait for a period of time, which greatly deepens the bearing pressure of the business server and will also affect its overall performance. Asynchronous request pool came into being to solve this problem.

How to implement an asynchronous request pool?

What are the concerns of asynchronous request pool implementation?

  1. Is the asynchronous request a connection or multiple connections
  2. Connected network I/O management issues
  3. If there are multiple connections, the fd management problem occurs when the response is not received after the request is sent
  4. Are requests and responses in one thread

Realization idea:

init

  • The responsibility is to create threads, manage fd, and receive responses. Receiving response is realized through callback function

commint

  • Establish a good network connection
  • Organize corresponding agreements
  • Send to the corresponding server
  • Whether fd is readable and fd is added to epoll

callback

  • epoll_wait() detects those fd readable recvs (fd)
  • Read out all data. Is to receive the response

destory

  • close
  • pthread_cancel

code implementation

#include<stdlib.h>
#include <unistd.h>
#include<stdio.h>
#include<sys/epoll.h>
#include<pthread.h>
#include<sys/socket.h>
#include<sys/un.h>
#include <sys/types.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <netinet/in.h>

struct ep_arg{
    int sockfd;
    void(*callback)(void*,int);
};

struct async_context{
    int epfd;
    pthread_t thread_id;
};

typedef void(*async_result_cb)(void*,int);


int dns_client_commit(struct async_context* ctx,async_result_cb cb){//The function is to make a request
    int sockfd = socket(AF_INET,SOCK_DGRAM,0);//UDP
    if(sockfd < 0){
        perror("create sockfd failed!\n");
        exit(-1);
    }

    struct sockaddr_in dest;
    bzero(&dest, sizeof(dest));
    dest.sin_family = AF_INET;
    dest.sin_port = htons(5555);
    dest.sin_addr.s_addr = inet_addr("127.0.0.1");

    int ret = connect(sockfd, (struct sockaddr*)&dest, sizeof(dest));//connect
    printf("connect :%d\n", ret);  

    //Custom protocol type
#if 0
      struct dns_header header = {0};
      dns_create_header(&header);
     
      struct dns_requestion question = {0};
      dns_create_quetion(&question);

      char request[1024] = {0};
      int req_len = dns_build_request(&header,&question,request);
      
      int slen = sendto(sockfd,request,req_len,0,(struct sockaddr*)&dest,sizeof(struct sockaddr));
#endif
    char buf[10] = "hello";
    ret = sendto(sockfd,buf,10,0,(struct sockaddr*)&dest,sizeof(struct sockaddr));
    
    //After the request is sent, manage fd and register the read event handler
    struct ep_arg* ptr = (struct ep_arg*)calloc(1,sizeof(struct ep_arg));
    ptr->sockfd = sockfd;
    ptr->callback = cb;

    struct epoll_event evs;
    evs.data.fd = sockfd;
    evs.events = EPOLLIN;
    epoll_ctl(ctx->epfd,EPOLL_CTL_ADD,sockfd,&evs);

}

void* dns_async_callback(void* arg){
    struct async_context* ctx = (struct async_context*)arg;
    while(1){
        struct epoll_event events[128] = {0};

        int nready = epoll_wait(ctx->epfd,events,128,-1);
        if(nready < 0) continue;

        int i = 0;
        for(i = 0;i < nready;++i){
            struct ep_arg* ptr = (struct ep_arg*)events[i].data.ptr;
            int sockfd = ptr->sockfd;

            char buffer[1024] = {0};
            struct sockaddr_in addr;
            size_t addr_len = sizeof(struct sockaddr_in);

            int n = recvfrom(sockfd,buffer,1024,0,(struct sockaddr*)&addr,(socklen_t*)&addr_len);
            printf("recvfrom n : %d\n",n);

            /* struct dns_item* domains = NULL; */
            /* int count = dns_parse_response(buffer,&domains); */

            /* ptr->callback(domains,count); */

            close(sockfd);

            free(ptr);
        }
    
    }
}

void* dns_client_init(const char* ){//Create a thread to receive a response
    int epfd = epoll_create(1);
    if(epfd < 0)    return NULL;

    struct async_context* ctx = (struct async_context*)calloc(1,sizeof(struct async_context));
    ctx->epfd = epfd;

    int ret = pthread_create(&ctx->thread_id,NULL,dns_async_callback,ctx);
    if(ret < 0){
        close(epfd);
        free(ctx);
        return NULL;
    }

    return ctx;
}

------The above arrangement is from watching the course of zero sound college

Topics: C# Linux server http