Làm cách nào để sao chép lưu lượng TCP đến một hoặc nhiều máy chủ từ xa cho mục đích đo điểm chuẩn?


30

Cơ sở hạ tầng: Máy chủ trong Datacenter, OS - Debian Squeeze, Webserver - Apache 2.2.16


Tình hình:

Máy chủ trực tiếp được sử dụng bởi các cusotmer của chúng tôi mỗi ngày, điều này khiến cho không thể kiểm tra các điều chỉnh và cải tiến. Do đó, chúng tôi muốn nhân đôi lưu lượng HTTP gửi đến trên máy chủ trực tiếp sang một hoặc nhiều máy chủ từ xa trong thời gian thực. Lưu lượng phải được chuyển đến Máy chủ web cục bộ (trong trường hợp này là Apache) VÀ đến (các) máy chủ từ xa. Qua đó, chúng ta có thể điều chỉnh cấu hình và sử dụng mã khác nhau / được cập nhật trên (các) máy chủ từ xa để đo điểm chuẩn và so sánh với máy chủ trực tiếp hiện tại. Hiện tại các máy chủ web đang nghe khoảng. 60 cổng bổ sung ngoài 80 và 443, do cấu trúc máy khách.


Câu hỏi: Làm thế nào có thể thực hiện sao chép này với một hoặc nhiều máy chủ từ xa?

Chúng tôi đã thử:

  • công cụ sao chép agnoster - điều này sẽ yêu cầu một phiên mở cho mỗi cổng không áp dụng. ( https://github.com/agnoster/d repeatator )
  • kklis proxy - chỉ chuyển tiếp lưu lượng truy cập đến máy chủ từ xa, nhưng không chuyển nó đến máy chủ web than. ( https://github.com/kklis/proxy )
  • iptables - DNAT chỉ chuyển tiếp lưu lượng, nhưng không chuyển nó đến máy chủ web cục bộ
  • iptables - TEE không trùng lặp với các máy chủ trong mạng cục bộ -> các máy chủ không nằm trong cùng một mạng do cấu trúc của trung tâm dữ liệu
  • đề xuất thay thế được cung cấp cho câu hỏi "lưu lượng truy cập tcp trùng lặp với proxy" tại stackoverflow ( https://stackoverflow.com/questions/7247668/d repeatate-tcp-training-with-a-proxy ) đã không thành công. Như đã đề cập, TEE không hoạt động với các máy chủ từ xa bên ngoài mạng cục bộ. teeproxy không còn khả dụng ( https://github.com/chrislusf/tee-proxy ) và chúng tôi không thể tìm thấy nó ở nơi nào khác.
  • Chúng tôi đã thêm một địa chỉ IP thứ hai (nằm trong cùng một mạng) và gán nó cho eth0: 0 (địa chỉ IP chính được gán cho eth0). Không thành công với việc kết hợp IP mới hoặc giao diện ảo eth0: 0 này với chức năng hoặc tuyến đường TEE của iptables.
  • các giải pháp thay thế được đề xuất cung cấp cho câu hỏi "sao chép lưu lượng truy cập tcp đến khi nén debian" ( Sao chép lưu lượng TCP đến trên Debian Squeeze ) không thành công. Các phiên cat | nc (cat / tmp / prodpipe | nc 127.0.0.1 12345 và cat / tmp / testpipe | nc 127.0.0.1 23456) bị gián đoạn sau mỗi yêu cầu / kết nối của khách hàng mà không có bất kỳ thông báo hay nhật ký nào. Keepalive đã không thay đổi tình trạng này. Gói TCP không được vận chuyển đến hệ thống từ xa.
  • Các thử bổ sung với các tùy chọn khác nhau của socat (HowTo: http://www.cyberciti.biz/faq/linux-unix-tcp-port-forwarding/ , https://stackoverflow.com/questions/9024227/d repeatate-input- unix-stream-to-multi-tcp-client-used-socat ) và các công cụ tương tự không thành công, vì hàm TEE được cung cấp sẽ chỉ ghi vào FS.
  • Tất nhiên, việc tìm kiếm và tìm kiếm "vấn đề" hoặc thiết lập này cũng không thành công.

Chúng tôi đang chạy ra khỏi các tùy chọn ở đây.

Có phương pháp nào để vô hiệu hóa việc thực thi "máy chủ trong mạng cục bộ" của chức năng TEE khi sử dụng IPTABLES không?

Mục tiêu của chúng tôi có thể đạt được bằng cách sử dụng IPTABLES hoặc Routes khác nhau không?

Bạn có biết một công cụ khác cho mục đích này đã được thử nghiệm và hoạt động cho những trường hợp cụ thể này không?

Có một nguồn khác cho tee-proxy (sẽ phù hợp hoàn hảo với yêu cầu của chúng tôi, AFAIK) không?


Cảm ơn trước cho câu trả lời của bạn.

----------

chỉnh sửa: 05.02.2014

đây là kịch bản python, sẽ hoạt động theo cách chúng ta cần:

import socket  
import SimpleHTTPServer  
import SocketServer  
import sys, thread, time  

def main(config, errorlog):
    sys.stderr = file(errorlog, 'a')

    for settings in parse(config):
        thread.start_new_thread(server, settings)

    while True:
        time.sleep(60)

def parse(configline):
    settings = list()
    for line in file(configline):
        parts = line.split()
        settings.append((int(parts[0]), int(parts[1]), parts[2], int(parts[3])))
    return settings

def server(*settings):
    try:
        dock_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        dock_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

        dock_socket.bind(('', settings[0]))

        dock_socket.listen(5)

        while True:
            client_socket = dock_socket.accept()[0]

            client_data = client_socket.recv(1024)
            sys.stderr.write("[OK] Data received:\n %s \n" % client_data)

            print "Forward data to local port: %s" % (settings[1])
            local_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            local_socket.connect(('', settings[1]))
            local_socket.sendall(client_data)

            print "Get response from local socket"
            client_response = local_socket.recv(1024)
            local_socket.close()

            print "Send response to client"
            client_socket.sendall(client_response)
            print "Close client socket"
            client_socket.close()

            print "Forward data to remote server: %s:%s" % (settings[2],settings[3])
            remote_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            remote_socket.connect((settings[2], settings[3]))
            remote_socket.sendall(client_data)       

            print "Close remote sockets"
            remote_socket.close()
    except:
        print "[ERROR]: ",
        print sys.exc_info()
        raise

if __name__ == '__main__':
    main('multiforwarder.config', 'error.log')

Các ý kiến ​​để sử dụng tập lệnh này:
Tập lệnh này chuyển tiếp một số cổng cục bộ được cấu hình sang một máy chủ ổ cắm cục bộ và từ xa khác.

Cấu hình:
Thêm vào tệp cấu hình dòng port-Forward.config với nội dung như sau:

Thông báo lỗi được lưu trữ trong tệp 'error.log'.

Kịch bản phân tách các tham số của tệp cấu hình:
Tách từng dòng cấu hình với khoảng trắng
0: cổng cục bộ để nghe
1: cổng cục bộ để chuyển tiếp đến
2: địa chỉ ip từ xa của máy chủ đích
3: cổng từ xa của máy chủ đích
và trả về cài đặt


Là tất cả lưu lượng HTTP?
longneck

có, tất cả lưu lượng truy cập là HTTP.
Sise

1
btw. teeproxy có sẵn tại đây: github.com/chrislusf/teeproxy
Tombart 16/215

1
Một khả năng khác: github.com/ebowman/splitter Scala / Netty-Dựa.
Giàu

Câu trả lời:


11

Nó là không thể. TCP là giao thức đầy đủ. Máy tính người dùng cuối tham gia vào từng bước kết nối và nó sẽ không bao giờ trả lời cho hai máy chủ riêng biệt đang cố gắng liên lạc với nó. Tất cả những gì bạn có thể làm là thu thập tất cả yêu cầu http trên máy chủ web hoặc một số proxy và phát lại chúng. Nhưng điều đó sẽ không cung cấp và chính xác điều kiện đồng thời hoặc lưu lượng truy cập của một máy chủ trực tiếp.


Sao chép TCP là không thể-- Tôi sẽ đồng ý với điều đó. Sao chép lưu lượng lớp 7 không. Bạn có thể nắm bắt các yêu cầu từ máy khách và phát lại chúng cho các máy chủ khác. Yêu cầu đơn giản cho mỗi lần phát lại phiên TCP sẽ khá dễ dàng. Các kết nối liên tục sẽ yêu cầu một số suy nghĩ trong chừng mực như cách bạn đặt thời gian cho các yêu cầu bổ sung của khách hàng.
Evan Anderson

@Kazimieras Aliulis: không bắt buộc phải giao tiếp với hai máy chủ riêng biệt. máy khách đang liên lạc với máy chủ chính = máy chủ trực tiếp. máy chủ trực tiếp đang xử lý các yêu cầu của máy khách và đang trả lời máy khách. bên cạnh việc xử lý và trả lời cho máy khách, máy chủ chính đang sao chép các yêu cầu đến máy chủ thứ hai = máy chủ thử nghiệm. các phản hồi từ máy chủ thứ hai đến máy chủ chính sẽ bị loại bỏ / bỏ qua tại máy chủ chính và sẽ không được chuyển tiếp đến máy khách.
Sise

@Evan Anderson: Sao chép ở cấp HTTP cũng là ý tưởng đầu tiên của chúng tôi, nhưng ví dụ proxy apache hoặc các công cụ hoặc mô-đun tương tự không cho phép xử lý đồng thời các yêu cầu cục bộ và sao chép nó vào máy chủ từ xa. Nếu bạn có bất kỳ ý tưởng khác, xin vui lòng tư vấn! :) chúng tôi muốn sao chép hơn ghi lại và phát lại để có kết quả so sánh ngay lập tức.
Sise

1
@Sise: bạn có thể thử viết proxy http của riêng mình, chuyển lưu lượng truy cập đến hai máy chủ. Nó sẽ khá dễ thực hiện với python Twisted framework twistmatrix.com .
Kazimieras Aliulis

@Kazimieras Aliulis: đó chắc chắn là một sự thay thế! Tôi chưa bao giờ nghe nói về nó. nhưng kiểm tra nó cho thấy rằng nó sẽ hoàn toàn phù hợp với mục đích của chúng tôi. Chúng tôi đã không xem xét python trước đây, nhưng hiện tại chúng tôi đang xem xét khuôn khổ Twisted và khả năng với python nói chung là tốt. Tôi sẽ báo cáo lại nếu chúng tôi thành công!
Sise

20

Từ những gì bạn mô tả, GOR dường như phù hợp với nhu cầu của bạn. https://github.com/ormser/gor/ "Phát lại lưu lượng HTTP trong thời gian thực. Phát lại lưu lượng truy cập từ sản xuất đến dàn dựng và môi trường dev." ?


2
Đây chính xác là những gì tôi đang tìm kiếm, cảm ơn rất nhiều, bạn đã lưu tôi viết chính xác điều này, trong Go! :-)
chmac


7

Teeproxy có thể được sử dụng để tái tạo lưu lượng. Cách sử dụng rất đơn giản:

./teeproxy -l :80 -a localhost:9000 -b localhost:9001
  • a máy chủ sản xuất
  • b máy chủ thử nghiệm

Khi bạn đặt HAproxy (có roundrobin) trước máy chủ web của mình, bạn có thể dễ dàng chuyển hướng 50% lưu lượng truy cập của mình đến trang web thử nghiệm:

         /------------------> production
HAproxy /                 ^
        \                /
         \---- teeproxy -.....> test (responses ignored)

4

TCP, là một giao thức có trạng thái, không thể đơn giản là làm nổ các bản sao của các gói tại một máy chủ khác, như @KazimierasAliulis chỉ ra.

Chọn các gói ở lớp kết thúc TCP và chuyển tiếp chúng dưới dạng luồng TCP mới là hợp lý. Công cụ sao chép mà bạn liên kết để trông giống như đặt cược tốt nhất của bạn. Nó hoạt động như một proxy TCP, cho phép máy trạng thái TCP hoạt động đúng. Các phản hồi từ máy kiểm tra của bạn sẽ bị loại bỏ. Nghe có vẻ phù hợp với hóa đơn cho những gì bạn muốn chính xác.

Tôi không rõ tại sao bạn lại viết công cụ sao chép là không thể chấp nhận được. Bạn sẽ phải chạy nhiều phiên bản của công cụ vì nó chỉ nghe trên một cổng duy nhất, nhưng có lẽ, bạn muốn chuyển tiếp từng cổng nghe khác nhau đó sang các cổng khác nhau trên hệ thống back-end. Nếu không, bạn có thể sử dụng iptables DNAT để hướng tất cả các cổng nghe sang một bản sao nghe duy nhất của công cụ sao chép.

Trừ khi các ứng dụng bạn đang kiểm tra rất đơn giản, tôi hy vọng rằng bạn sẽ gặp vấn đề với phương pháp thử nghiệm này liên quan đến thời gian và trạng thái ứng dụng nội bộ. Những gì bạn muốn làm nghe có vẻ đơn giản-- Tôi hy vọng bạn sẽ tìm thấy rất nhiều trường hợp cạnh.


vâng, bạn hoàn toàn đúng, công cụ sao chép agnoster sẽ phù hợp với yêu cầu của chúng tôi ngoại trừ tình huống đa cổng. Ngoài ra, việc loại bỏ các phản hồi của máy kiểm tra đã được điền đầy đủ. Để đạt được mục tiêu mô phỏng tình huống thực / sống chính xác nhất có thể, chúng tôi không thể bó tất cả các cổng trên máy chủ trực tiếp thành một cổng duy nhất trên máy thử nghiệm. Các cổng khác nhau được sử dụng để phân chia các thiết bị khách hàng thành các khách hàng khác nhau. Do đó, chúng tôi phải mở 60-70 phiên của công cụ sao chép này. Điều này không thực tế như bạn có thể tưởng tượng.
Sise

@Sise - Máy tính rất giỏi làm những việc tẻ nhạt. Tôi nghĩ rằng bạn có thể viết một tập lệnh để phân tích các cấu hình Apache của bạn và nhổ các dòng lệnh cần thiết để chạy 60 - 70 phiên bản của công cụ sao chép. Tôi không thể tưởng tượng công cụ sao chép rất tốn tài nguyên, nhưng ngay cả khi có, bạn có thể chạy 60 - 70 trường hợp đó trên một máy khác và thực hiện một số thủ thuật mạng để có lưu lượng truy cập ở đó. Đối với tôi, ít nhất, điều đó dường như hoàn toàn thực tế và là một cách khá đơn giản để xử lý việc này.
Evan Anderson

1

Tôi đang cố gắng làm một cái gì đó tương tự, tuy nhiên, nếu bạn chỉ đơn giản là cố gắng mô phỏng tải trên máy chủ, tôi sẽ xem xét một cái gì đó giống như khung kiểm tra tải. Tôi đã sử dụng locust.io trong quá khứ và nó hoạt động rất tốt để mô phỏng tải trên máy chủ. Điều đó sẽ cho phép bạn mô phỏng một số lượng lớn máy khách và cho phép bạn chơi với cấu hình của máy chủ mà không phải trải qua quá trình đau đớn để chuyển tiếp lưu lượng đến máy chủ khác.


0

Theo như "chúng tôi muốn nhân đôi lưu lượng HTTP gửi đến trên máy chủ trực tiếp sang một hoặc nhiều máy chủ từ xa trong thời gian thực", có một cách không được đề cập ở trên, đó là cấu hình một cổng nhân bản trên công tắc mà nó được kết nối.

Trong trường hợp thiết bị chuyển mạch Cisco Catalyst, đây được gọi là SPAN (thông tin thêm ở đây ). Trong môi trường Cisco, bạn thậm chí có thể có cổng được nhân đôi trên một công tắc khác.

Nhưng mục đích của việc này là để phân tích lưu lượng truy cập nên nó sẽ là một hướng - từ khóa trong văn bản được trích dẫn trong đoạn đầu tiên ở trên: trong nước . Tôi không nghĩ rằng cổng đó sẽ cho phép bất kỳ lưu lượng truy cập trở lại nào và nếu có, bạn sẽ xử lý lưu lượng truy cập trùng lặp như thế nào? Điều đó có thể sẽ tàn phá mạng của bạn.

Vì vậy, ... chỉ muốn thêm một khả năng vào danh sách của bạn, nhưng với lời cảnh báo rằng nó sẽ thực sự dành cho giao thông một chiều. Có lẽ bạn có thể đặt một hub trên cổng nhân bản đó và có các phản hồi máy chủ trùng lặp được đưa ra bởi một số trình giả lập máy khách cục bộ sẽ chọn các phiên đã bắt đầu và trả lời, nhưng sau đó bạn sẽ sao chép lưu lượng truy cập đến máy chủ trùng lặp của mình ... có thể không phải là bạn muốn


chúng tôi đã nghĩ về điều đó, tôi đã đọc về sự thay thế của việc sử dụng SPAN. Nhưng, vì các máy chủ được đặt trong một trung tâm dữ liệu của nhà cung cấp bên thứ ba, chúng tôi có khả năng hạn chế khi nói đến thay đổi phần cứng. Tôi đã yêu cầu kết nối trực tiếp 2 máy chủ trên nic thứ hai. Hành động này kết hợp với một mạng cục bộ cho chỉ 2 máy chủ này sẽ cho phép tôi sử dụng IPTABLES với TEE. Nhưng để đi đến giải pháp thay thế này, chúng ta sẽ cần thay đổi IP bên ngoài của các máy chủ, đó là NoGo vì các thiết bị khách được cấu hình để kết nối với IP đã đặt.
Sise

0

Tôi cũng đã viết một bộ cân bằng proxy / tải ngược cho mục đích tương tự với Node.js (nó chỉ để giải trí, không sẵn sàng sản xuất vào lúc này).

https://github.com/losnir/ampel

Nó rất quan tâm, và hiện đang hỗ trợ:

  • GET Sử dụng lựa chọn vòng tròn (1: 1)
  • POSTSử dụng tách yêu cầu. Không có khái niệm "chủ" và "bóng" - phần phụ trợ đầu tiên phản hồi là phần phụ sẽ phục vụ yêu cầu của khách hàng, và sau đó tất cả các phản hồi khác sẽ bị loại bỏ.

Nếu ai đó thấy nó hữu ích thì tôi có thể cải thiện nó để linh hoạt hơn.


Node.js là một lựa chọn ngôn ngữ rất lạ cho một ứng dụng như ứng dụng này sẽ đòi hỏi hiệu năng rất cao. Tôi không chắc điều này sẽ sẵn sàng sản xuất.
Michael Hampton

Bạn hoàn toàn đúng. Điều này không có nghĩa là có hiệu suất cao - chỉ dễ viết (đối với tôi). Tôi nghĩ rằng nó phụ thuộc vào tải yêu cầu. Tôi đã có thể đạt được một chút hơn 1.000rps trên một máy cấp thấp mặc dù (2 lõi).
losnir

0

Công ty của tôi có yêu cầu tương tự, sao chép một gói và gửi đến một máy chủ khác (chúng tôi chạy mô phỏng dữ liệu thị trường và cần một giải pháp tạm thời để nghe nguồn cấp dữ liệu TCP thị trường, nhập từng gói nhưng cũng gửi một bản sao của từng gói cho một trình giả lập khác máy chủ)

nhị phân này chạy rất tốt, đây là phiên bản của TCP Sao chép nhưng được viết bằng golang thay vì jscript, vì vậy cách của nó nhanh hơn và hoạt động như quảng cáo,

https://github.com/mkevac/god repeatator


-1

có một công cụ được tạo bởi một chàng trai từ một công ty Trung Quốc và có thể đó là thứ bạn cần: https://github.com/session-replay-tools/tcpcopy


2
Xin chào và chào mừng đến với serverfault. Xin vui lòng cung cấp một câu trả lời chi tiết hơn? Chương trình làm gì chính xác? Có phải nó được viết bằng C ...?
bgtvfr
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.