1 рд╕реАрдкреАрдпреВ рдХреЛрд░ рдкрд░ 1M HTTP рдЖрд░рдкреАрдПрд╕ред рдирдЧреАрдиреЗрдХреНрд╕ + рд▓рд╛рдЗрдирдХреНрд╕ рдХрд░реНрдиреЗрд▓ рдЯреАрд╕реАрдкреА / рдЖрдИрдкреА рдХреЗ рдмрдЬрд╛рдп рдбреАрдкреАрдбреАрдХреЗ

рдореИрдВ рдбреАрдкреАрдбреАрдХреЗ рдЬреИрд╕реА рдЪреАрдЬ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ - рдпрд╣ рдХрд░реНрдиреЗрд▓ рдХреЛ рджрд░рдХрд┐рдирд╛рд░ рдХрд░ рдиреЗрдЯрд╡рд░реНрдХ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд░реВрдкрд░реЗрдЦрд╛ рд╣реИред рдпрд╛рдиреА рдЖрдк рдХрд┐рд╕реА рднреА рд╕рд┐рд╕реНрдЯрдо рдХреЙрд▓ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреЗ рдмрд┐рдирд╛ рд╕реАрдзреЗ рдиреЗрдЯрд╡рд░реНрдХ рдХрд╛рд░реНрдб рдХреА рдХрддрд╛рд░ рдореЗрдВ рдкрдврд╝рдиреЗ рдХреЗ рд▓рд┐рдП userland \ рд╕реЗ рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣ рдЖрдкрдХреЛ рдкреНрд░рддрд┐рд▓рд┐рдкрд┐ рдмрдирд╛рдиреЗ рдФрд░ рдЕрдзрд┐рдХ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рд╕рд╛рд░реЗ рдУрд╡рд░рд╣реЗрдб рдмрдЪрд╛рддрд╛ рд╣реИред рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд░реВрдк рдореЗрдВ, рдореИрдВ рдПрдХ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд▓рд┐рдЦреВрдВрдЧрд╛ рдЬреЛ http рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдПрдХ рдкрд░реАрдХреНрд╖рдг рдкреГрд╖реНрда рджреЗрддрд╛ рд╣реИ рдФрд░ рдЗрд╕рдХреА рдЧрддрд┐ nginx рдХреЗ рд╕рд╛рде рддреБрд▓рдирд╛ рдХрд░рддрд╛ рд╣реИред

DPDK рдХреЛ рдпрд╣рд╛рдБ рдбрд╛рдЙрдирд▓реЛрдб рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ ред рд╕реНрдерд┐рд░ рди рд▓реЗрдВ - рдпрд╣ рдореЗрд░реЗ рд▓рд┐рдП EC2 рдкрд░ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, 18.05 рд▓реЗрдВ - рдЗрд╕рдХреЗ рд╕рд╛рде рд╕рдм рдХреБрдЫ рд╢реБрд░реВ рд╣реБрдЖред рд╢реБрд░реВ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рдЖрдкрдХреЛ рдлреНрд░реЗрдорд╡рд░реНрдХ рдХреЗ рд╕рд╛рдорд╛рдиреНрдп рд╕рдВрдЪрд╛рд▓рди рдХреЗ рд▓рд┐рдП рд╕рд┐рд╕реНрдЯрдо рдореЗрдВ рд╣реИрд╡реАрдкреЗрдЬреЛрдВ рдХреЛ рдЖрд░рдХреНрд╖рд┐рдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛ ред рд╕рд┐рджреНрдзрд╛рдВрдд рд░реВрдк рдореЗрдВ, рдкрд░реАрдХреНрд╖рдг рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рд╡рд┐рд╢рд╛рд▓рдХрд╛рдп рдмрд┐рдирд╛ рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд╡рд┐рдХрд▓реНрдк рдХреЗ рд╕рд╛рде рд▓реЙрдиреНрдЪ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдореИрдВрдиреЗ рд╣рдореЗрд╢рд╛ рдЙрдиреНрд╣реЗрдВ рд╢рд╛рдорд┐рд▓ рдХрд┐рдпрд╛ред * Grub-mkconfig рдХреЗ рдмрд╛рдж рдЕрдкрдбреЗрдЯ-рдЧреНрд░реБрдм рдХреЛ рди рднреВрд▓реЗрдВ * рдЬрдм рдЖрдк рдмрд╣реБрдд рдмрдбрд╝реЗ рдкреИрдорд╛рдиреЗ рдкрд░ рд╕рдорд╛рдкреНрдд рд╣реЛ рдЬрд╛рддреЗ рд╣реИрдВ, рддреЛ рддреБрд░рдВрдд ./usertools/dpdk-setup.py рдкрд░ рдЬрд╛рдПрдВ - рдпрд╣ рдЪреАрдЬрд╝ рд╕рдм рдХреБрдЫ рдПрдХрддреНрд░ рдФрд░ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░реЗрдЧреАред Google рдореЗрдВ рдЖрдк dpdk-setup.py рдХреЛ рдмрд╛рдпрдкрд╛рд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рдЗрдХрдЯреНрдард╛ рдХрд░рдиреЗ рдФрд░ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреА рд╕рд┐рдлрд╛рд░рд┐рд╢ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдирд┐рд░реНрджреЗрд╢ рдкрд╛ рд╕рдХрддреЗ рд╣реИрдВ - рдРрд╕рд╛ рди рдХрд░реЗрдВред рдареАрдХ рд╣реИ, рдЖрдк рдпрд╣ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдХреЗрд╡рд▓ рдореЗрд░реЗ рд╕рд╛рде, рдЬрдмрдХрд┐ рдореИрдВрдиреЗ dpdk-setup.py рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд┐рдпрд╛, рдХреБрдЫ рднреА рдХрд╛рдо рдирд╣реАрдВ рдХрд┐рдпрд╛ред рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ, dpdk-setup.py рдХреЗ рдЕрдВрджрд░ рдХреНрд░рд┐рдпрд╛рдУрдВ рдХрд╛ рдХреНрд░рдо:

  • x86_x64 linux рдмрдирд╛рдПрдБ
  • рд▓реЛрдб igb рдпреВрдЖрдИрдУ рдХрд░реНрдиреЗрд▓ рдореЙрдбреНрдпреВрд▓
  • рдирдХреНрд╢рд╛ рд╡рд┐рд╢рд╛рд▓ / mnt / рд╡рд┐рд╢рд╛рд▓
  • рдпреВрдЖрдИрдУ рдореЗрдВ рд╡рд╛рдВрдЫрд┐рдд рдирд┐рдХ рдХреЛ рдмрд╛рдВрдзреЗрдВ (рдЗрд╕рд╕реЗ рдкрд╣рд▓реЗ ifconfig ethX рдХреЛ рдХрд░рдирд╛ рди рднреВрд▓реЗрдВ)

рдЙрд╕рдХреЗ рдмрд╛рдж, рдЖрдк рдЗрд╕рдХреЗ рд╕рд╛рде рдбрд╛рдпрд░реЗрдХреНрдЯрд░реА рдореЗрдВ рд░рди рдмрдирд╛рдХрд░ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВред рдХреЗрд╡рд▓ рдПрдХ рдкрд░реНрдпрд╛рд╡рд░рдг рдЪрд░ RTE_SDK рдмрдирд╛рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИ рдЬреЛ DPDK рдХреЗ рд╕рд╛рде рдПрдХ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рддрд╛ рд╣реИред

рдпрд╣рд╛рдБ рдкреВрд░реНрдг рдЙрджрд╛рд╣рд░рдг рдХреЛрдб рдирд┐рд╣рд┐рдд рд╣реИред рдЗрд╕рдореЗрдВ рдЖрд░рдВрднреАрдХрд░рдг, рдЯреАрд╕реАрдкреА / рдЖрдИрдкреА рдФрд░ рдЖрджрд┐рдо http рдкрд╛рд░реНрд╕рд░ рдХреЗ рдЖрджрд┐рдо рд╕рдВрд╕реНрдХрд░рдг рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╢рд╛рдорд┐рд▓ рд╣реИред рдЖрдЗрдП рдЖрд░рдВрдн рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВред

int main(int argc, char** argv) { int ret; //  dpdk ret = rte_eal_init(argc, argv); if (ret < 0) { rte_panic("Cannot init EAL\n"); } //  memory pool g_packet_mbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", 131071, 32, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); if (g_packet_mbuf_pool == NULL) { rte_exit(EXIT_FAILURE, "Cannot init mbuf pool\n"); } g_tcp_state_pool = rte_mempool_create("tcp_state_pool", 65535, sizeof(struct tcp_state), 0, 0, NULL, NULL, NULL, NULL, rte_socket_id(), 0); if (g_tcp_state_pool == NULL) { rte_exit(EXIT_FAILURE, "Cannot init tcp_state pool\n"); } //  hash table struct rte_hash_parameters hash_params = { .entries = 64536, .key_len = sizeof(struct tcp_key), .socket_id = rte_socket_id(), .hash_func_init_val = 0, .name = "tcp clients table" }; g_clients = rte_hash_create(&hash_params); if (g_clients == NULL) { rte_exit(EXIT_FAILURE, "No hash table created\n"); } //    1     uint8_t nb_ports = rte_eth_dev_count(); if (nb_ports == 0) { rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n"); } if (nb_ports > 1) { rte_exit(EXIT_FAILURE, "Not implemented. Too much ports\n"); } //     struct rte_eth_conf port_conf = { .rxmode = { .split_hdr_size = 0, .header_split = 0, /**< Header Split disabled */ .hw_ip_checksum = 0, /**< IP checksum offload disabled */ .hw_vlan_filter = 0, /**< VLAN filtering disabled */ .jumbo_frame = 0, /**< Jumbo Frame Support disabled */ .hw_strip_crc = 0, /**< CRC stripped by hardware */ }, .txmode = { .mq_mode = ETH_MQ_TX_NONE, }, }; //          port_conf.txmode.offloads |= DEV_TX_OFFLOAD_IPV4_CKSUM; port_conf.txmode.offloads |= DEV_TX_OFFLOAD_TCP_CKSUM; ret = rte_eth_dev_configure(0, RX_QUEUE_COUNT, TX_QUEUE_COUNT, &port_conf); if (ret < 0) { rte_exit(EXIT_FAILURE, "Cannot configure device: err=%d\n", ret); } //     for (uint16_t j=0; j<RX_QUEUE_COUNT; ++j) { ret = rte_eth_rx_queue_setup(0, j, 1024, rte_eth_dev_socket_id(0), NULL, g_packet_mbuf_pool); if (ret < 0) { rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup:err=%d\n", ret); } } //    struct rte_eth_txconf txconf = { .offloads = port_conf.txmode.offloads, }; for (uint16_t j=0; j<TX_QUEUE_COUNT; ++j) { ret = rte_eth_tx_queue_setup(0, j, 1024, rte_eth_dev_socket_id(0), &txconf); if (ret < 0) { rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup:err=%d\n", ret); } } // NIC ret = rte_eth_dev_start(0); if (ret < 0) { rte_exit(EXIT_FAILURE, "rte_eth_dev_start:err=%d\n", ret); } //   lcore_hello(NULL); return 0; } 

рдЙрд╕ рд╕рдордп, рдЬрдм dpdk-setup.py рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╣рдо рдЪрдпрдирд┐рдд рдиреЗрдЯрд╡рд░реНрдХ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ dpdk рдбреНрд░рд╛рдЗрд╡рд░ рд╕реЗ рдмрд╛рдБрдзрддреЗ рд╣реИрдВ, рдпрд╣ рдиреЗрдЯрд╡рд░реНрдХ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХрд░реНрдиреЗрд▓ рдХреЗ рд▓рд┐рдП рд╕реБрд▓рдн рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред рдЙрд╕рдХреЗ рдмрд╛рдж, рдиреЗрдЯрд╡рд░реНрдХ рдХрд╛рд░реНрдб рдЗрд╕ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдореЗрдВ рдЖрдиреЗ рд╡рд╛рд▓реЗ рдХрд┐рд╕реА рднреА рдкреИрдХреЗрдЯ рдХреЛ рдбреАрдПрдордП рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЙрд╕ рдХрддрд╛рд░ рдореЗрдВ рд░рд┐рдХреЙрд░реНрдб рдХрд░реЗрдЧрд╛ рдЬреЛ рд╣рдордиреЗ рдЙрд╕реЗ рдкреНрд░рджрд╛рди рдХрд┐рдпрд╛ рдерд╛ред

рдФрд░ рдпрд╣рд╛рдБ рдкреИрдХреЗрдЯ рдкреНрд░реЛрд╕реЗрд╕рд┐рдВрдЧ рд▓реВрдк рд╣реИред

 struct rte_mbuf* packets[MAX_PACKETS]; uint16_t rx_current_queue = 0; while (1) { //  unsigned packet_count = rte_eth_rx_burst(0, (++rx_current_queue) % RX_QUEUE_COUNT, packets, MAX_PACKETS); for (unsigned j=0; j<packet_count; ++j) { struct rte_mbuf* m = packets[j]; //   ethernet  struct ether_hdr* eth_header = rte_pktmbuf_mtod(m, struct ether_hdr*); //  IP  if (RTE_ETH_IS_IPV4_HDR(m->packet_type)) { do { //   if (rte_pktmbuf_data_len(m) < sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) + sizeof(struct tcp_hdr)) { TRACE; break; } struct ipv4_hdr* ip_header = (struct ipv4_hdr*)((char*)eth_header + sizeof(struct ether_hdr)); if ((ip_header->next_proto_id != 0x6) || (ip_header->version_ihl != 0x45)) { TRACE; break; } if (ip_header->dst_addr != MY_IP_ADDRESS) { TRACE; break; } if (rte_pktmbuf_data_len(m) < htons(ip_header->total_length) + sizeof(struct ether_hdr)) { TRACE; break; } if (htons(ip_header->total_length) < sizeof(struct ipv4_hdr) + sizeof(struct tcp_hdr)) { TRACE; break; } struct tcp_hdr* tcp_header = (struct tcp_hdr*)((char*)ip_header + sizeof(struct ipv4_hdr)); size_t tcp_header_size = (tcp_header->data_off >> 4) * 4; if (rte_pktmbuf_data_len(m) < sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) + tcp_header_size) { TRACE; break; } if (tcp_header->dst_port != 0x5000) { TRACE; break; } size_t data_size = htons(ip_header->total_length) - sizeof(struct ipv4_hdr) - tcp_header_size; void* data = (char*)tcp_header + tcp_header_size; //     hash table struct tcp_key key = { .ip = ip_header->src_addr, .port = tcp_header->src_port }; //    tcp process_tcp(m, tcp_header, &key, data, data_size); } while(0); } else if (eth_header->ether_type == 0x0608) // ARP { //     -       ARP- do { if (rte_pktmbuf_data_len(m) < sizeof(struct arp) + sizeof(struct ether_hdr)) { TRACE; break; } struct arp* arp_packet = (struct arp*)((char*)eth_header + sizeof(struct ether_hdr)); if (arp_packet->opcode != 0x100) { TRACE; break; } if (arp_packet->dst_pr_add != MY_IP_ADDRESS) { TRACE; break; } send_arp_response(arp_packet); } while(0); } else { TRACE; } rte_pktmbuf_free(m); } } 

Rte_eth_rx_burst рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрддрд╛рд░ рд╕реЗ рдкреИрдХреЗрдЯ рдкрдврд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрджрд┐ рдХрддрд╛рд░ рдореЗрдВ рдХреБрдЫ рд╣реИ, рддреЛ рдпрд╣ рдкреИрдХреЗрдЯ рдХреЛ рдкрдврд╝реЗрдЧрд╛ рдФрд░ рдЙрдиреНрд╣реЗрдВ рдПрдХ рд╕рд░рдгреА рдореЗрдВ рдбрд╛рд▓ рджреЗрдЧрд╛ред рдпрджрд┐ рдХрддрд╛рд░ рдореЗрдВ рдХреБрдЫ рднреА рдирд╣реАрдВ рд╣реИ, рддреЛ 0 рд╡рд╛рдкрд╕ рдЖ рдЬрд╛рдПрдЧрд╛, рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдЖрдкрдХреЛ рддреБрд░рдВрдд рдЗрд╕реЗ рдлрд┐рд░ рд╕реЗ рдХреЙрд▓ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рд╣рд╛рдВ, рдпрд╣ рджреГрд╖реНрдЯрд┐рдХреЛрдг "рдХреБрдЫ рд╕рдордп рдХреЗ рд▓рд┐рдП рд╕реАрдкреАрдпреВ" рдЦрд░реНрдЪ рдХрд░рддрд╛ рд╣реИ рдпрджрд┐ рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдиреЗрдЯрд╡рд░реНрдХ рдкрд░ рдХреЛрдИ рдбреЗрдЯрд╛ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдЕрдЧрд░ рд╣рдордиреЗ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдбреАрдкреАрдбреАрдХреЗ рд▓рд┐рдпрд╛ рд╣реИ, рддреЛ рдпрд╣ рдорд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рд╣рдорд╛рд░рд╛ рдорд╛рдорд▓рд╛ рдирд╣реАрдВ рд╣реИред * рдорд╣рддреНрд╡рдкреВрд░реНрдг, рдлрд╝рдВрдХреНрд╢рди рдереНрд░реЗрдб-рд╕реБрд░рдХреНрд╖рд┐рдд рдирд╣реАрдВ рд╣реИ, рд╡рд┐рднрд┐рдиреНрди рдкреНрд░рдХреНрд░рд┐рдпрд╛рдУрдВ рдореЗрдВ рдПрдХ рд╣реА рдХрддрд╛рд░ рд╕реЗ рдирд╣реАрдВ рдкрдврд╝рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ * рдкреИрдХреЗрдЬ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, rte_pktmbuf_free рдХреЛ рдХреЙрд▓ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдПрдХ рдкреИрдХреЗрдЯ рднреЗрдЬрдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдк rte_eth_tx_burst рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреЛ rte_mbuf рд╕реЗ рдкреНрд░рд╛рдкреНрдд rte_pktmbuf_alloc рдХреЛ рдиреЗрдЯрд╡рд░реНрдХ рдХрд╛рд░реНрдб рдХрддрд╛рд░ рдореЗрдВ рд░рдЦрддрд╛ рд╣реИред

рдкреИрдХреЗрдЬ рд╣реЗрдбрд░ рдХреЗ рдбрд┐рд╕рд╛рдЗрдб рд╣реЛрдиреЗ рдХреЗ рдмрд╛рдж, tcp рд╕реЗрд╢рди рдмрдирд╛рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реЛрдЧрд╛ред Tcp рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рд╡рд┐рднрд┐рдиреНрди рд╡рд┐рд╢реЗрд╖ рдорд╛рдорд▓реЛрдВ, рд╡рд┐рд╢реЗрд╖ рд╕реНрдерд┐рддрд┐рдпреЛрдВ рдФрд░ рд╕реЗрд╡рд╛ рд╕реЗ рд╡рдВрдЪрд┐рдд рд╣реЛрдиреЗ рдХреЗ рдЦрддрд░реЛрдВ рд╕реЗ рднрд░рд╛ рд╣реБрдЖ рд╣реИред рдЕрдзрд┐рдХ рдпрд╛ рдХрдо рдкреВрд░реНрдг tcp рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдПрдХ рдЕрдиреБрднрд╡реА рдбреЗрд╡рд▓рдкрд░ рдХреЗ рд▓рд┐рдП рдПрдХ рдЙрддреНрдХреГрд╖реНрдЯ рдЕрднреНрдпрд╛рд╕ рд╣реИ, рд▓реЗрдХрд┐рди рдлрд┐рд░ рднреА, рдпрд╣рд╛рдВ рдврд╛рдВрдЪреЗ рдореЗрдВ рд╢рд╛рдорд┐рд▓ рдирд╣реАрдВ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рдкрд░реАрдХреНрд╖рдг рдХреЗ рд▓рд┐рдП tcp рдХреЛ рдкрд░реНрдпрд╛рдкреНрдд рд░реВрдк рд╕реЗ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред Dpdk рдХреЗ рд╕рд╛рде рдЖрдкреВрд░реНрддрд┐ рдХреА рдЧрдИ рд╣реИрд╢ рддрд╛рд▓рд┐рдХрд╛ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдПрдХ рд╕рддреНрд░ рддрд╛рд▓рд┐рдХрд╛ рдХреЛ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛, рдПрдХ tcp рдХрдиреЗрдХреНрд╢рди рдХреА рд╕реНрдерд╛рдкрдирд╛ рдФрд░ рддреЛрдбрд╝рдХрд░, рдЦрд╛рддреЗ рдХреЗ рдиреБрдХрд╕рд╛рди рдФрд░ рдкреИрдХреЗрдЯ рдкреБрди: рд╕рдВрдЪрд╛рд▓рди рдореЗрдВ рдбреЗрдЯрд╛ рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд┐рдП рдмрд┐рдирд╛ рдФрд░ рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ред Dpdk рдХреА рд╣реИрд╢ рдЯреЗрдмрд▓ рдореЗрдВ рдПрдХ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╕реАрдорд╛ рд╣реИ рдЬрд┐рд╕реЗ рдЖрдк рдкрдврд╝ рд╕рдХрддреЗ рд╣реИрдВ рд▓реЗрдХрд┐рди рдХрдИ рдереНрд░реЗрдбреНрд╕ рдкрд░ рдирд╣реАрдВ рд▓рд┐рдЦ рд╕рдХрддреЗред рдЙрджрд╛рд╣рд░рдг рдХреЛ рдПрдХрд▓-рдереНрд░реЗрдбреЗрдб рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ рдФрд░ рдпрд╣ рд╕рдорд╕реНрдпрд╛ рдпрд╣рд╛рдВ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдирд╣реАрдВ рд╣реИ, рдФрд░ рдХрдИ рдХреЛрд░ рдкрд░ рдЯреНрд░реИрдлрд┐рдХ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдиреЗ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдЖрдк рдЖрд░рдПрд╕рдПрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдПрдХ рд╣реИрд╢ рдЯреЗрдмрд▓ рднреЗрдЬ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдмрд┐рдирд╛ рдмреНрд▓реЙрдХ рдХрд┐рдП рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рдЯреАрд╕реАрдкреА рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди
 tatic void process_tcp(struct rte_mbuf* m, struct tcp_hdr* tcp_header, struct tcp_key* key, void* data, size_t data_size) { TRACE; struct tcp_state* state; if (rte_hash_lookup_data(g_clients, key, (void**)&state) < 0) //Documentaion lies!!! { TRACE; if ((tcp_header->tcp_flags & 0x2) != 0) // SYN { TRACE; struct ether_hdr* eth_header = rte_pktmbuf_mtod(m, struct ether_hdr*); if (rte_mempool_get(g_tcp_state_pool, (void**)&state) < 0) { ERROR("tcp state alloc fail"); return; } memcpy(&state->tcp_template, &g_tcp_packet_template, sizeof(g_tcp_packet_template)); memcpy(&state->tcp_template.eth.d_addr, &eth_header->s_addr, 6); state->tcp_template.ip.dst_addr = key->ip; state->tcp_template.tcp.dst_port = key->port; state->remote_seq = htonl(tcp_header->sent_seq); #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpointer-to-int-cast" state->my_seq_start = (uint32_t)state; // not very secure. #pragma GCC diagnostic pop state->fin_sent = 0; state->http.state = HTTP_START; state->http.request_url_size = 0; //not thread safe! only one core used if (rte_hash_add_key_data(g_clients, key, state) == 0) { struct tcp_hdr* new_tcp_header; struct rte_mbuf* packet = build_packet(state, 12, &new_tcp_header); if (packet != NULL) { new_tcp_header->rx_win = TX_WINDOW_SIZE; new_tcp_header->sent_seq = htonl(state->my_seq_start); state->my_seq_sent = state->my_seq_start+1; ++state->remote_seq; new_tcp_header->recv_ack = htonl(state->remote_seq); new_tcp_header->tcp_flags = 0x12; // mss = 1380, no window scaling uint8_t options[12] = {0x02, 0x04, 0x05, 0x64, 0x03, 0x03, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01}; memcpy((uint8_t*)new_tcp_header + sizeof(struct tcp_hdr), options, 12); new_tcp_header->data_off = 0x80; send_packet(new_tcp_header, packet); } else { ERROR("rte_pktmbuf_alloc, tcp synack"); } } else { ERROR("can't add connection to table"); rte_mempool_put(g_tcp_state_pool, state); } } else { ERROR("lost connection"); } return; } if ((tcp_header->tcp_flags & 0x2) != 0) // SYN retransmit { //not thread safe! only one core used if (rte_hash_del_key(g_clients, key) < 0) { ERROR("can't delete key"); } else { rte_mempool_put(g_tcp_state_pool, state); return process_tcp(m, tcp_header, key, data, data_size); } } if ((tcp_header->tcp_flags & 0x10) != 0) // ACK { TRACE; uint32_t ack_delta = htonl(tcp_header->recv_ack) - state->my_seq_start; uint32_t my_max_ack_delta = state->my_seq_sent - state->my_seq_start; if (ack_delta == 0) { if ((data_size == 0) && (tcp_header->tcp_flags == 0x10)) { ERROR("need to retransmit. not supported"); } } else if (ack_delta <= my_max_ack_delta) { state->my_seq_start += ack_delta; } else { ERROR("ack on unsent seq"); } } if (data_size > 0) { TRACE; uint32_t packet_seq = htonl(tcp_header->sent_seq); if (state->remote_seq == packet_seq) { feed_http(data, data_size, state); state->remote_seq += data_size; } else if (state->remote_seq-1 == packet_seq) // keepalive { struct tcp_hdr* new_tcp_header; struct rte_mbuf* packet = build_packet(state, 0, &new_tcp_header); if (packet != NULL) { new_tcp_header->rx_win = TX_WINDOW_SIZE; new_tcp_header->sent_seq = htonl(state->my_seq_sent); new_tcp_header->recv_ack = htonl(state->remote_seq); send_packet(new_tcp_header, packet); } else { ERROR("rte_pktmbuf_alloc, tcp ack keepalive"); } } else { struct tcp_hdr* new_tcp_header; struct rte_mbuf* packet = build_packet(state, state->http.last_message_size, &new_tcp_header); TRACE; if (packet != NULL) { new_tcp_header->rx_win = TX_WINDOW_SIZE; new_tcp_header->sent_seq = htonl(state->my_seq_sent - state->http.last_message_size); new_tcp_header->recv_ack = htonl(state->remote_seq); memcpy((char*)new_tcp_header+sizeof(struct tcp_hdr), &state->http.last_message, state->http.last_message_size); send_packet(new_tcp_header, packet); } else { ERROR("rte_pktmbuf_alloc, tcp fin ack"); } //ERROR("my bad tcp stack implementation((("); } } if ((tcp_header->tcp_flags & 0x04) != 0) // RST { TRACE; //not thread safe! only one core used if (rte_hash_del_key(g_clients, key) < 0) { ERROR("can't delete key"); } else { rte_mempool_put(g_tcp_state_pool, state); } } else if ((tcp_header->tcp_flags & 0x01) != 0) // FIN { struct tcp_hdr* new_tcp_header; struct rte_mbuf* packet = build_packet(state, 0, &new_tcp_header); TRACE; if (packet != NULL) { new_tcp_header->rx_win = TX_WINDOW_SIZE; new_tcp_header->sent_seq = htonl(state->my_seq_sent); new_tcp_header->recv_ack = htonl(state->remote_seq + 1); if (!state->fin_sent) { TRACE; new_tcp_header->tcp_flags = 0x11; // !@#$ the last ack } send_packet(new_tcp_header, packet); } else { ERROR("rte_pktmbuf_alloc, tcp fin ack"); } //not thread safe! only one core used if (rte_hash_del_key(g_clients, key) < 0) { ERROR("can't delete key"); } else { rte_mempool_put(g_tcp_state_pool, state); } } } 


Http рдкрд╛рд░реНрд╕рд░ рдХреЗрд╡рд▓ GET рдХреЛ рд╡рд╣рд╛рдВ рд╕реЗ URL рдкрдврд╝рдиреЗ рдФрд░ рдЕрдиреБрд░реЛрдзрд┐рдд URL рдХреЗ рд╕рд╛рде html рд╡рд╛рдкрд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдорд░реНрдерди рдХрд░реЗрдЧрд╛ред

HTTP рдкрд╛рд░реНрд╕рд░
 static void feed_http(void* data, size_t data_size, struct tcp_state* state) { TRACE; size_t remaining_data = data_size; char* current = (char*)data; struct http_state* http = &state->http; if (http->state == HTTP_BAD_STATE) { TRACE; return; } while (remaining_data > 0) { switch(http->state) { case HTTP_START: { if (*current == 'G') { http->state = HTTP_READ_G; } else { http->state = HTTP_BAD_STATE; } break; } case HTTP_READ_G: { if (*current == 'E') { http->state = HTTP_READ_E; } else { http->state = HTTP_BAD_STATE; } break; } case HTTP_READ_E: { if (*current == 'T') { http->state = HTTP_READ_T; } else { http->state = HTTP_BAD_STATE; } break; } case HTTP_READ_T: { if (*current == ' ') { http->state = HTTP_READ_SPACE; } else { http->state = HTTP_BAD_STATE; } break; } case HTTP_READ_SPACE: { if (*current != ' ') { http->request_url[http->request_url_size] = *current; ++http->request_url_size; if (http->request_url_size > MAX_URL_SIZE) { http->state = HTTP_BAD_STATE; } } else { http->state = HTTP_READ_URL; http->request_url[http->request_url_size] = '\0'; } break; } case HTTP_READ_URL: { if (*current == '\r') { http->state = HTTP_READ_R1; } break; } case HTTP_READ_R1: { if (*current == '\n') { http->state = HTTP_READ_N1; } else if (*current == '\r') { http->state = HTTP_READ_R1; } else { http->state = HTTP_READ_URL; } break; } case HTTP_READ_N1: { if (*current == '\r') { http->state = HTTP_READ_R2; } else { http->state = HTTP_READ_URL; } break; } case HTTP_READ_R2: { if (*current == '\n') { TRACE; char content_length[32]; sprintf(content_length, "%lu", g_http_part2_size - 4 + http->request_url_size + g_http_part3_size); size_t content_length_size = strlen(content_length); size_t total_data_size = g_http_part1_size + g_http_part2_size + g_http_part3_size + http->request_url_size + content_length_size; struct tcp_hdr* tcp_header; struct rte_mbuf* packet = build_packet(state, total_data_size, &tcp_header); if (packet != NULL) { tcp_header->rx_win = TX_WINDOW_SIZE; tcp_header->sent_seq = htonl(state->my_seq_sent); tcp_header->recv_ack = htonl(state->remote_seq + data_size); #ifdef KEEPALIVE state->my_seq_sent += total_data_size; #else state->my_seq_sent += total_data_size + 1; //+1 for FIN tcp_header->tcp_flags = 0x11; state->fin_sent = 1; #endif char* new_data = (char*)tcp_header + sizeof(struct tcp_hdr); memcpy(new_data, g_http_part1, g_http_part1_size); new_data += g_http_part1_size; memcpy(new_data, content_length, content_length_size); new_data += content_length_size; memcpy(new_data, g_http_part2, g_http_part2_size); new_data += g_http_part2_size; memcpy(new_data, http->request_url, http->request_url_size); new_data += http->request_url_size; memcpy(new_data, g_http_part3, g_http_part3_size); memcpy(&http->last_message, (char*)tcp_header+sizeof(struct tcp_hdr), total_data_size); http->last_message_size = total_data_size; send_packet(tcp_header, packet); } else { ERROR("rte_pktmbuf_alloc, tcp data"); } http->state = HTTP_START; http->request_url_size = 0; } else if (*current == '\r') { http->state = HTTP_READ_R1; } else { http->state = HTTP_READ_URL; } break; } default: { ERROR("bad http state"); return; } } if (http->state == HTTP_BAD_STATE) { return; } --remaining_data; ++current; } } 


рдЙрджрд╛рд╣рд░рдг рддреИрдпрд╛рд░ рд╣реЛрдиреЗ рдХреЗ рдмрд╛рдж, рдЖрдк рдирдЧреАрдирдХреНрд╕ рдХреЗ рд╕рд╛рде рдкреНрд░рджрд░реНрд╢рди рдХреА рддреБрд▓рдирд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдХреНрдпреЛрдВрдХрд┐ рдореИрдВ рдШрд░ рдкрд░ рдПрдХ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╕реНрдЯреИрдВрдб рдЗрдХрдЯреНрдард╛ рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛, рдореИрдВрдиреЗ рдЕрдореЗрдЬрд╝реЕрди рдИрд╕реА 2 рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ред EC2 рдиреЗ рдкрд░реАрдХреНрд╖рдг рдореЗрдВ рдЗрд╕рдХреЗ рд╕реБрдзрд╛рд░ рдХрд┐рдП - рдореБрдЭреЗ рдХрдиреЗрдХреНрд╢рди рдЫреЛрдбрд╝рдирд╛ рдкрдбрд╝рд╛: рдХрд░реАрдмреА рдЕрдиреБрд░реЛрдз, рдХреНрдпреЛрдВрдХрд┐ рдкрд░реАрдХреНрд╖рдг рд╢реБрд░реВ рд╣реЛрдиреЗ рдХреЗ рдХреБрдЫ рд╕реЗрдХрдВрдб рдмрд╛рдж 300k rps SYN рдХреЗ рдкреИрдХреЗрдЯ рдореЗрдВ рдХреБрдЫ рдмреВрдВрджреЗрдВ рдЧрд┐рд░рдирд╛ рд╢реБрд░реВ рд╣реБрдИрдВред рдЬрд╛рд╣рд┐рд░ рд╣реИ, SYN-рдмрд╛рдврд╝ рдХреЗ рдЦрд┐рд▓рд╛рдл рдХрд┐рд╕реА рдкреНрд░рдХрд╛рд░ рдХрд╛ рд╕рдВрд░рдХреНрд╖рдг рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рдЬреАрд╡рд┐рдд рд░рдЦрд╛ рдЧрдпрд╛ рдерд╛ред EC2 рдкрд░, dpdk рд╕рднреА рдЙрджрд╛рд╣рд░рдгреЛрдВ рдкрд░ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП m1.medium рдкрд░ рдпрд╣ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред рд╕реНрдЯреИрдВрдб рдиреЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рд╕рд╛рде 1 рдЗрдВрд╕реНрдЯреЗрдВрд╕ r4.8xlarge рдФрд░ рд▓реЛрдб рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП 2 рдЗрдВрд╕реНрдЯреЗрдВрд╕ r4.8xlarge рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ред рд╡реЗ рдПрдХ рдирд┐рдЬреА рд╡реАрдкреАрд╕реА рд╕рдмрдиреЗрдЯ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╣реЛрдЯрд▓ рдиреЗрдЯрд╡рд░реНрдХ рдЗрдВрдЯрд░рдлреЗрд╕ рдкрд░ рд╕рдВрд╡рд╛рдж рдХрд░рддреЗ рд╣реИрдВред рдореИрдВрдиреЗ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдЙрдкрдпреЛрдЧрд┐рддрд╛рдУрдВ рдХреЗ рд╕рд╛рде рд▓реЛрдб рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХреА: рдПрдмреА, рдЖрд░рдХреЗ, рдПрдЪ тАЛтАЛ2 рд▓реЛрдб, рдШреЗрд░рд╛рдмрдВрджреАред рд╕рдмрд╕реЗ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ wrk рдерд╛, рдХреНрдпреЛрдВрдХрд┐ рдпрджрд┐ рдиреЗрдЯрд╡рд░реНрдХ рдкрд░ рддреНрд░реБрдЯрд┐рдпрд╛рдВ рд╣реИрдВ, рддреЛ ab рдПрдХрд▓-рдереНрд░реЗрдбреЗрдб рд╣реИ рдФрд░ рд╡рд┐рдХреГрдд рдЖрдВрдХрдбрд╝реЗ рддреИрдпрд╛рд░ рдХрд░рддрд╛ рд╣реИред

EC2 рдореЗрдВ рдмрд╣реБрдд рдЕрдзрд┐рдХ рдЯреНрд░реИрдлрд╝рд┐рдХ рдХреЗ рд╕рд╛рде, рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рдмреВрдВрджреЛрдВ рдХреЛ рджреЗрдЦрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рд╕рд╛рдзрд╛рд░рдг рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдпрд╣ рдЕрджреГрд╢реНрдп рд╣реЛрдЧрд╛, рд▓реЗрдХрд┐рди рдПрдм рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдХреЛрдИ рднреА рдкреНрд░рддрд┐рд╕рд╛рдж рдХреБрд▓ рд╕рдордп рдФрд░ рдПрдмрдЯ рд▓реЗрддрд╛ рд╣реИ, рдЬрд┐рд╕рдХреЗ рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк рдкреНрд░рддрд┐ рд╕реЗрдХрдВрдб рдЕрдиреБрд░реЛрдзреЛрдВ рдХреА рдФрд╕рдд рд╕рдВрдЦреНрдпрд╛ рдкрд░ рдбреЗрдЯрд╛ рдЕрдиреБрдкрдпреБрдХреНрдд рд╣реИрдВред рдмреВрдВрджреЛрдВ рдХреЗ рдХрд╛рд░рдгреЛрдВ рд╕реЗ рдЕрд▓рдЧ рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрд▓рдЧ рд░рд╣рд╕реНрдп рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐, рддрдереНрдп рдпрд╣ рд╣реИ рдХрд┐ рди рдХреЗрд╡рд▓ рдбреАрдкреАрдбреАрдХреЗ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╕рдордп рд╕рдорд╕реНрдпрд╛рдПрдВ рд╣реИрдВ, рдмрд▓реНрдХрд┐ рдирдЧрдиреЗрдХреНрд╕ рдХреЗ рд╕рд╛рде рднреА, рдпрд╣ рдмрддрд╛рддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдХреБрдЫ рдЧрд▓рдд рдХрд╛ рдЙрджрд╛рд╣рд░рдг рдирд╣реАрдВ рд▓рдЧрддрд╛ рд╣реИред

рдореИрдВрдиреЗ рджреЛ рдЪрд░рдгреЛрдВ рдореЗрдВ рдкрд░реАрдХреНрд╖рдг рдХрд┐рдпрд╛, рдкрд╣рд▓реЗ рдореИрдВрдиреЗ 1 рдЙрджрд╛рд╣рд░рдг рдкрд░, рдлрд┐рд░ 2 рдкрд░ рд░реЗрдХ рдЪрд▓рд╛рдпрд╛ред рдпрджрд┐ 2 рдЙрджрд╛рд╣рд░рдгреЛрдВ рдореЗрдВ рд╕реЗ рдХреБрд▓ рдкреНрд░рджрд░реНрд╢рди 1 рд╣реИ, рддреЛ рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдореИрдВ рдЦреБрдж рд╣реА wrk рдХреЗ рдкреНрд░рджрд░реНрд╢рди рдореЗрдВ рдирд╣реАрдВ рдЖрдпрд╛ рдерд╛ред

R4.8xlarge рдкрд░ dpdk рдЙрджрд╛рд╣рд░рдг рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдкрд░рд┐рдгрд╛рдо
рд▓реЙрдиреНрдЪ wrk c 1 рдЙрджрд╛рд╣рд░рдг

root@ip-172-30-0-127:~# wrk -t64 -d10s -c4000 --latency http://172.30.4.10/testu
Running 10s test @ http://172.30.4.10/testu
64 threads and 4000 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 32.19ms 63.43ms 817.26ms 85.01%
Req/Sec 15.97k 4.04k 113.97k 93.47%
Latency Distribution
50% 2.58ms
75% 17.57ms
90% 134.94ms
99% 206.03ms
10278064 requests in 10.10s, 1.70GB read
Socket errors: connect 0, read 17, write 0, timeout 0
Requests/sec: 1017645.11
Transfer/sec: 172.75MB

рдПрдХ рд╣реА рд╕рдордп рдореЗрдВ 2 рдЙрджрд╛рд╣рд░рдгреЛрдВ рд╕реЗ рдЪрд▓ рд░рд╣рд╛ рд╣реИ
root@ip-172-30-0-127:~# wrk -t64 -d10s -c4000 --latency http://172.30.4.10/testu
Running 10s test @ http://172.30.4.10/testu
64 threads and 4000 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 67.28ms 119.20ms 1.64s 88.90%
Req/Sec 7.99k 4.58k 132.62k 96.67%
Latency Distribution
50% 2.31ms
75% 103.45ms
90% 191.51ms
99% 563.56ms
5160076 requests in 10.10s, 0.86GB read
Socket errors: connect 0, read 2364, write 0, timeout 1
Requests/sec: 510894.92
Transfer/sec: 86.73MB

root@ip-172-30-0-225:~# wrk -t64 -d10s -c4000 --latency http://172.30.4.10/testu
Running 10s test @ http://172.30.4.10/testu
64 threads and 4000 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 74.87ms 148.64ms 1.64s 93.45%
Req/Sec 8.22k 2.59k 42.51k 81.21%
Latency Distribution
50% 2.41ms
75% 110.42ms
90% 190.66ms
99% 739.67ms
5298083 requests in 10.10s, 0.88GB read
Socket errors: connect 0, read 0, write 0, timeout 148
Requests/sec: 524543.67
Transfer/sec: 89.04MB


Nginx рдиреЗ рдРрд╕реЗ рдкрд░рд┐рдгрд╛рдо рджрд┐рдП
рд▓реЙрдиреНрдЪ wrk c 1 рдЙрджрд╛рд╣рд░рдг

root@ip-172-30-0-127:~# wrk -t64 -d10s -c4000 --latency http://172.30.4.10/testu
Running 10s test @ http://172.30.4.10/testu
64 threads and 4000 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 14.36ms 56.41ms 1.92s 95.26%
Req/Sec 15.27k 3.30k 72.23k 83.53%
Latency Distribution
50% 3.38ms
75% 6.82ms
90% 10.95ms
99% 234.99ms
9813464 requests in 10.10s, 2.12GB read
Socket errors: connect 0, read 1, write 0, timeout 3
Requests/sec: 971665.79
Transfer/sec: 214.94MB


рдПрдХ рд╣реА рд╕рдордп рдореЗрдВ 2 рдЙрджрд╛рд╣рд░рдгреЛрдВ рд╕реЗ рдЪрд▓ рд░рд╣рд╛ рд╣реИ

root@ip-172-30-0-127:~# wrk -t64 -d10s -c4000 --latency http://172.30.4.10/testu
Running 10s test @ http://172.30.4.10/testu
64 threads and 4000 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 52.91ms 82.19ms 1.04s 82.93%
Req/Sec 8.05k 3.09k 55.62k 89.11%
Latency Distribution
50% 3.66ms
75% 94.87ms
90% 171.83ms
99% 354.26ms
5179253 requests in 10.10s, 1.12GB read
Socket errors: connect 0, read 134, write 0, timeout 0
Requests/sec: 512799.10
Transfer/sec: 113.43MB

root@ip-172-30-0-225:~# wrk -t64 -d10s -c4000 --latency http://172.30.4.10/testu
Running 10s test @ http://172.30.4.10/testu
64 threads and 4000 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 64.38ms 121.56ms 1.67s 90.32%
Req/Sec 7.30k 2.54k 34.94k 82.10%
Latency Distribution
50% 3.68ms
75% 103.32ms
90% 184.05ms
99% 561.31ms
4692290 requests in 10.10s, 1.01GB read
Socket errors: connect 0, read 2, write 0, timeout 21
Requests/sec: 464566.93
Transfer/sec: 102.77MB


nginx config
рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ www-рдбреЗрдЯрд╛;
рдХрд╛рд░реНрдпрдХрд░реНрддрд╛_рдкреНрд░реЛрд╕реЗрд╕ рдСрдЯреЛ;
pid /run/nginx.pid;
рдХрд╛рд░реНрдпрдХрд░реНрддрд╛_рдкреНрд░рдореБрдЦ_рдирд┐рд░реАрдХреНрд╖рдг 50000;
рдШрдЯрдирд╛рдПрдБ {
worker_connections 10000;
}
http {
рдкрд░ рднреЗрдЬ рджреЗрдирд╛;
tcp_nopush on;
tcp_nodelay on;
Keepalive_timeout 65;
type_hash_max_size 2048;

/etc/nginx/mime.types рд╢рд╛рдорд┐рд▓ рдХрд░реЗрдВ;
default_type рдкрд╛рда / рд╕рд╛рджреЗ;

error_log /var/log/nginx/error.log;
access_log рдмрдВрдж;

рд╕рд░реНрд╡рд░ {
80 default_server рдмреИрдХрд▓реЙрдЧ = 10000 рдкреБрди: рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ;
рд╕реНрдерд╛рди / {
рд╡рд╛рдкрд╕реА 200 "answer.padding _____________________________________________________________________";
}
}
}

рдХреБрд▓ рдореЗрдВ, рд╣рдо рджреЗрдЦрддреЗ рд╣реИрдВ рдХрд┐ рджреЛрдиреЛрдВ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдореЗрдВ рд╣рдореЗрдВ рдкреНрд░рддрд┐ рд╕реЗрдХрдВрдб рд▓рдЧрднрдЧ 1M рдЕрдиреБрд░реЛрдз рдорд┐рд▓рддреЗ рд╣реИрдВ, рдХреЗрд╡рд▓ nginx рдиреЗ рдЗрд╕рдХреЗ рд▓рд┐рдП рд╕рднреА 32 рд╕реАрдкреАрдпреВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рд╣реИ, рдФрд░ рдХреЗрд╡рд▓ рдПрдХ рд╣реА dpdkред рд╢рд╛рдпрдж EC2 рдлрд┐рд░ рд╕реЗ рдЗрд╕рдореЗрдВ рдПрдХ рд╕реБрдЕрд░ рдбрд╛рд▓рддрд╛ рд╣реИ рдФрд░ 1M rps рдПрдХ рдиреЗрдЯрд╡рд░реНрдХ рд▓рд┐рдорд┐рдЯреЗрд╢рди рд╣реИ, рд▓реЗрдХрд┐рди рдЕрдЧрд░ рдРрд╕рд╛ рд╣реИ рднреА, рддреЛ рдкрд░рд┐рдгрд╛рдо рдмрд╣реБрдд рд╡рд┐рдХреГрдд рдирд╣реАрдВ рд╣реИрдВ, рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕рдХреЗ рд▓рд┐рдП рджреЗрд░реА рдЬреЛрдбрд╝ рд░рд╣рд╛ рд╣реИ (int x = 0; x <100; ++ x) http рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдПред тЖТ request_url [0] = 'a' + (http-> request_url [0]% 10) рдкреИрдХреЗрдЯ рднреЗрдЬрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рдЗрд╕рдиреЗ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЖрд░рдкреАрдПрд╕ рдХрдо рдХрд░ рджрд┐рдпрд╛, рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдЙрдкрдпреЛрдЧреА рдХрд╛рдо рдХреЗ рд╕рд╛рде рд▓рдЧрднрдЧ рдкреВрд░реНрдг рд╕реАрдкреАрдпреВ рд▓реЛрдб рдХрд░рдирд╛ред

рдкреНрд░рдпреЛрдЧреЛрдВ рдХреЗ рджреМрд░рд╛рди, рдПрдХ рд░рд╣рд╕реНрдп рдХрд╛ рдкрддрд╛ рдЪрд▓рд╛, рдЬрд┐рд╕реЗ рдореИрдВ рдЕрднреА рднреА рд╣рд▓ рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛ред рдпрджрд┐ рдЖрдк рдЪреЗрдХрд╕рдо рдСрдлрд╝рд▓реЛрдбрд┐рдВрдЧ рд╕рдХреНрд╖рдо рдХрд░рддреЗ рд╣реИрдВ, рдЕрд░реНрдерд╛рдд, рдиреЗрдЯрд╡рд░реНрдХ рдХрд╛рд░реНрдб рджреНрд╡рд╛рд░рд╛ рд╣реА рдЖрдИрдкреА рдФрд░ рдЯреАрд╕реАрдкреА рд╣реЗрдбрд░ рдХреЗ рд▓рд┐рдП рдЪреЗрдХрд╕рдо рдХреА рдЧрдгрдирд╛, рддреЛ рд╕рдордЧреНрд░ рдкреНрд░рджрд░реНрд╢рди рдореЗрдВ рдЧрд┐рд░рд╛рд╡рдЯ рдЖрддреА рд╣реИ, рдФрд░ рд╡рд┐рд▓рдВрдмрддрд╛ рдореЗрдВ рд╕реБрдзрд╛рд░ рд╣реЛрддрд╛ рд╣реИред
рдпрд╣рд╛рдВ рдСрдлрд▓реЛрдбрд┐рдВрдЧ рд╕рдХреНрд╖рдо рдХреЗ рд╕рд╛рде рд╢реБрд░реБрдЖрдд рд╣реИ

root@ip-172-30-0-127:~# wrk -t64 -d10s -c4000 --latency http://172.30.4.10/testu
Running 10s test @ http://172.30.4.10/testu
64 threads and 4000 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 5.91ms 614.33us 28.35ms 96.17%
Req/Sec 10.48k 1.51k 69.89k 98.78%
Latency Distribution
50% 5.91ms
75% 6.01ms
90% 6.19ms
99% 6.99ms
6738296 requests in 10.10s, 1.12GB read
Requests/sec: 667140.71
Transfer/sec: 113.25MB


рдФрд░ рдпрд╣рд╛рдБ рд╕реАрдкреАрдпреВ рдкрд░ рдЪреЗрдХрд╕рдо рдХреЗ рд╕рд╛рде

root@ip-172-30-0-127:~# wrk -t64 -d10s -c4000 --latency http://172.30.4.10/testu
Running 10s test @ http://172.30.4.10/testu
64 threads and 4000 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 32.19ms 63.43ms 817.26ms 85.01%
Req/Sec 15.97k 4.04k 113.97k 93.47%
Latency Distribution
50% 2.58ms
75% 17.57ms
90% 134.94ms
99% 206.03ms
10278064 requests in 10.10s, 1.70GB read
Socket errors: connect 0, read 17, write 0, timeout 0
Requests/sec: 1017645.11
Transfer/sec: 172.75MB


рдареАрдХ рд╣реИ, рдореИрдВ рдкреНрд░рджрд░реНрд╢рди рдбреНрд░реЙрдк рдХреЛ рдЗрд╕ рддрдереНрдп рд╕реЗ рд╕рдордЭрд╛ рд╕рдХрддрд╛ рд╣реВрдВ рдХрд┐ рдиреЗрдЯрд╡рд░реНрдХ рдХрд╛рд░реНрдб рдзреАрдорд╛ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдпрд╣ рдЕрдЬреАрдм рд╣реИ, рдЗрд╕реЗ рддреЗрдЬ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред рд▓реЗрдХрд┐рди рдХреНрдпреЛрдВ, рд╡рд┐рд▓рдВрдмрддрд╛ рдХреЗ рдирдХреНрд╢реЗ рдкрд░ рдЪреЗрдХрд╕рдо рдХреА рдЧрдгрдирд╛ рдХреЗ рд╕рд╛рде, рд▓рдЧрднрдЧ 6ms рдХреЗ рдмрд░рд╛рдмрд░ рд╕реНрдерд┐рд░ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдпрджрд┐ рдЖрдк рд╕реАрдкреАрдпреВ рдкрд░ рднрд░реЛрд╕рд╛ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдпрд╣ 2.5ms рд╕реЗ 817ms рддрдХ рддреИрд░рддрд╛ рд╣реИ? рдПрдХ рдЧреИрд░-рдЖрднрд╛рд╕реА рд╕реНрдЯреИрдВрдб рджреНрд╡рд╛рд░рд╛ рдкреНрд░рддреНрдпрдХреНрд╖ рдХрдиреЗрдХреНрд╢рди рдХреЗ рд╕рд╛рде рдХрд╛рд░реНрдп рдХреЛ рдмрд╣реБрдд рд╕рд░рд▓ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рд▓реЗрдХрд┐рди рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ, рдореЗрд░реЗ рдкрд╛рд╕ рдпрд╣ рдирд╣реАрдВ рд╣реИред DPDK рд╕реНрд╡рдпрдВ рд╕рднреА рдиреЗрдЯрд╡рд░реНрдХ рдХрд╛рд░реНрдб рдкрд░ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рдЖрдкрдХреЛ рд╕реВрдЪреА рдХреА рдЬрд╛рдВрдЪ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред

рдФрд░ рдЕрдВрдд рдореЗрдВ, рдПрдХ рд╕рд░реНрд╡реЗрдХреНрд╖рдгред

Source: https://habr.com/ru/post/hi416651/


All Articles