Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Trong bài nói chuyện của mình, Andrey Borodin sẽ cho bạn biết họ đã tính đến trải nghiệm mở rộng quy mô PgBouncer như thế nào khi thiết kế một công cụ tổng hợp kết nối Odyssey, cách họ triển khai nó trong quá trình sản xuất. Ngoài ra, chúng tôi sẽ thảo luận về những chức năng của công cụ tổng hợp mà chúng tôi muốn thấy trong các phiên bản mới: điều quan trọng đối với chúng tôi là không chỉ đáp ứng nhu cầu của chúng tôi mà còn phát triển cộng đồng người dùng Odyssey.

Video:

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Chào mọi người! Tên tôi là Andrew.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Tại Yandex, tôi đang phát triển cơ sở dữ liệu mã nguồn mở. Và hôm nay chúng ta có một chủ đề về kết nối tổng hợp kết nối.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Nếu bạn biết cách gọi tổng hợp kết nối bằng tiếng Nga, thì hãy cho tôi biết. Tôi thực sự muốn tìm một thuật ngữ kỹ thuật tốt nên được thiết lập trong tài liệu kỹ thuật.

Chủ đề này khá phức tạp, bởi vì trong nhiều cơ sở dữ liệu, trình tổng hợp kết nối được tích hợp sẵn và bạn thậm chí không cần biết về nó. Tất nhiên, một số cài đặt ở khắp mọi nơi, nhưng trong Postgres, điều này không hoạt động. Và song song (tại HighLoad++ 2019), có một báo cáo của Nikolai Samokhvalov về việc thiết lập truy vấn trong Postgres. Và tôi hiểu rằng những người đã đến đây đã cấu hình các yêu cầu một cách hoàn hảo và đây là những người đang gặp phải các sự cố hệ thống hiếm gặp hơn liên quan đến mạng, sử dụng tài nguyên. Và ở một số nơi, có thể khá khó khăn theo nghĩa là các vấn đề không rõ ràng.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Yandex có Postgres. Nhiều dịch vụ Yandex có trong Yandex.Cloud. Và chúng tôi có vài petabyte dữ liệu tạo ra ít nhất một triệu yêu cầu mỗi giây trong Postgres.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Và chúng tôi cung cấp một cụm khá điển hình cho tất cả các dịch vụ - đây là nút chính chính của nút, hai bản sao thông thường (đồng bộ và không đồng bộ), sao lưu, nhân rộng các yêu cầu đọc trên bản sao.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Mỗi nút cụm là Postgres, trên đó, ngoài Postgres và các hệ thống giám sát, một bộ tổng hợp kết nối cũng được cài đặt. Bộ gộp kết nối được sử dụng để đấu kiếm và cho mục đích chính của nó.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Mục đích chính của một tổng hợp kết nối là gì?

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Postgres áp dụng mô hình quy trình để làm việc với cơ sở dữ liệu. Điều này có nghĩa là một kết nối là một quá trình, một phụ trợ Postgres. Và có rất nhiều bộ đệm khác nhau trong phần phụ trợ này, khá tốn kém để tạo ra sự khác biệt cho các kết nối khác nhau.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Ngoài ra, có một mảng trong mã Postgres được gọi là procArray. Nó chứa dữ liệu cơ bản về các kết nối mạng. Và hầu như tất cả các thuật toán xử lý procArray đều có độ phức tạp tuyến tính, chúng chạy qua toàn bộ mảng kết nối mạng. Đó là một chu kỳ khá nhanh, nhưng với nhiều kết nối mạng hơn, mọi thứ sẽ đắt hơn một chút. Và khi mọi thứ trở nên đắt hơn một chút, bạn sẽ phải trả giá rất cao cho một số lượng lớn kết nối mạng.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Có 3 cách tiếp cận khả thi:

  • Về phía ứng dụng.
  • Về phía cơ sở dữ liệu.
  • Và giữa, nghĩa là, tất cả các kết hợp có thể.

Thật không may, công cụ tổng hợp tích hợp hiện đang được phát triển. Bạn bè tại PostgreSQL Professional hầu hết làm điều này. Khi nó sẽ xuất hiện là khó dự đoán. Và trên thực tế, chúng tôi có hai giải pháp cho sự lựa chọn của một kiến ​​​​trúc sư. Đây là nhóm phía ứng dụng và nhóm proxy.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Nhóm phía ứng dụng là cách dễ nhất. Và hầu như tất cả các trình điều khiển máy khách đều cung cấp cho bạn một cách: biểu thị hàng triệu kết nối của bạn trong mã dưới dạng vài chục kết nối tới cơ sở dữ liệu.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Có một vấn đề là tại một thời điểm nhất định, bạn muốn mở rộng quy mô phụ trợ, bạn muốn triển khai nó cho nhiều máy ảo.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Sau đó, bạn vẫn nhận ra rằng bạn có thêm một số vùng khả dụng, một số trung tâm dữ liệu. Và phương pháp tổng hợp phía khách hàng dẫn đến số lượng lớn. Những cái lớn là khoảng 10 kết nối. Đây là một cạnh có thể hoạt động tốt.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Nếu chúng ta nói về các công cụ gộp proxy, thì có hai công cụ gộp có thể làm được rất nhiều việc. Họ không chỉ là những người gộp chung. Họ là những người gộp chung + nhiều chức năng thú vị hơn. Cái này pgpool и Proxy giòn.

Nhưng thật không may, không phải ai cũng cần chức năng bổ sung này. Và nó dẫn đến một thực tế là các công cụ gộp chỉ hỗ trợ gộp phiên, tức là một máy khách đến, một máy khách đi vào cơ sở dữ liệu.

Điều này không phù hợp lắm với các nhiệm vụ của chúng tôi, vì vậy chúng tôi sử dụng PgBouncer, thực hiện tổng hợp giao dịch, tức là các kết nối máy chủ chỉ được ánh xạ tới các kết nối máy khách trong suốt thời gian giao dịch.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Và trên tải của chúng tôi - đó là sự thật. Nhưng có một số vấn đề.Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Sự cố bắt đầu khi bạn muốn chẩn đoán phiên, vì tất cả các kết nối đến đều cục bộ. Mọi người đều đến với loopback và bằng cách nào đó, việc theo dõi phiên trở nên khó khăn.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Tất nhiên bạn có thể sử dụng application_name_add_host. Đây là cách bên Bouncer để thêm địa chỉ IP vào application_name. Nhưng application_name được đặt bởi một kết nối bổ sung.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Trên biểu đồ này, đường màu vàng là yêu cầu thực và đường màu xanh là yêu cầu bay vào cơ sở dữ liệu. Và sự khác biệt này chính xác là cài đặt của application_name, chỉ cần thiết để theo dõi, nhưng nó hoàn toàn không miễn phí.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Ngoài ra, Bouncer không thể giới hạn một nhóm, tức là số lượng kết nối cơ sở dữ liệu trên mỗi người dùng, trên mỗi cơ sở dữ liệu.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Điều này dẫn đến điều gì? Bạn có một dịch vụ đã tải được viết bằng C ++ và ở đâu đó gần đó có một dịch vụ nhỏ trên một nút không làm gì sai với cơ sở, nhưng trình điều khiển của nó bị điên. Nó mở 20 kết nối và mọi thứ khác sẽ đợi. Ngay cả mã của bạn là chính xác.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Tất nhiên, chúng tôi đã viết một bản vá nhỏ cho Bouncer đã thêm cài đặt này, tức là giới hạn khách hàng trong nhóm.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Có thể thực hiện việc này ở phía Postgres, tức là giới hạn các vai trò trong cơ sở dữ liệu ở số lượng kết nối.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Nhưng sau đó bạn mất khả năng hiểu tại sao bạn không có kết nối với máy chủ. PgBouncer không gây ra lỗi kết nối, nó luôn trả về cùng một thông tin. Và bạn không thể hiểu được: có thể mật khẩu của bạn đã thay đổi, có thể cơ sở dữ liệu vừa bị hỏng, có thể có gì đó không ổn. Nhưng không có chẩn đoán. Nếu phiên không thể được thiết lập, bạn sẽ không biết tại sao nó không thể được thực hiện.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Tại một thời điểm nhất định, bạn nhìn vào biểu đồ của ứng dụng và thấy rằng ứng dụng không hoạt động.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Nhìn vào phía trên và thấy rằng Bouncer là một luồng. Đây là một bước ngoặt trong cuộc đời của dịch vụ. Bạn hiểu rằng bạn đang chuẩn bị mở rộng cơ sở dữ liệu trong một năm rưỡi và bạn cần mở rộng quy mô tổng hợp.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Chúng tôi đã đi đến kết luận rằng chúng tôi cần nhiều PgBouncer hơn.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

https://lwn.net/Articles/542629/

Bouncer đã được vá một chút.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Và họ đã tạo ra nó để một số Bouncer có thể được nâng lên bằng cách sử dụng lại cổng TCP. Và hệ điều hành đã tự động chuyển các kết nối TCP đến giữa chúng theo vòng tròn.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Điều này minh bạch đối với khách hàng, tức là có vẻ như bạn có một Bouncer, nhưng bạn có sự phân mảnh các kết nối không hoạt động giữa các Bouncer đang chạy.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Và tại một số điểm, bạn có thể nhận thấy rằng 3 Bouncer này đều ăn 100% lõi của chúng. Bạn cần khá nhiều Bouncers. Tại sao?

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Bởi vì bạn có TLS. Bạn có một kết nối được mã hóa. Và nếu bạn đo điểm chuẩn Postgres có và không có TLS, bạn sẽ thấy rằng số lượng kết nối được thiết lập giảm gần hai bậc độ lớn khi mã hóa được bật, vì quá trình bắt tay TLS tiêu tốn tài nguyên CPU.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Và ở trên cùng, bạn có thể thấy khá nhiều chức năng mật mã được thực thi trong một đợt kết nối đến. Vì cơ sở chính của chúng tôi có thể chuyển đổi giữa các vùng khả dụng, nên một làn sóng kết nối đến là một tình huống khá điển hình. Đó là, vì một số lý do, chính cũ không khả dụng, toàn bộ tải được gửi đến một trung tâm dữ liệu khác. Tất cả họ sẽ đến chào TLS cùng một lúc.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Và một số lượng lớn bắt tay TLS có thể không chào Bouncer rồi mà bóp cổ anh ta. Làn sóng các kết nối đến có thể trở nên nguyên vẹn do hết thời gian chờ. Nếu bạn thử lại cơ sở mà không có sự lùi lại theo cấp số nhân, thì chúng sẽ không quay lại lặp đi lặp lại trong một làn sóng nhất quán.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Dưới đây là ví dụ về 16 PgBouncers tải 16 lõi ở mức 100%.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Chúng tôi đã đến PgBouncer xếp tầng. Đây là cấu hình tốt nhất mà chúng tôi có thể đạt được khi tải Bouncer. Bouncers bên ngoài của chúng tôi phục vụ cho quá trình bắt tay TCP và Bouncer nội bộ phục vụ cho việc tổng hợp thực sự, để không làm phân mảnh quá nhiều các kết nối bên ngoài.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Trong cấu hình này, có thể khởi động lại mềm. Bạn có thể khởi động lại tất cả 18 Bouncers này từng cái một. Nhưng việc duy trì một cấu hình như vậy là khá khó khăn. Quản trị viên hệ thống, DevOps và những người thực sự chịu trách nhiệm về máy chủ này sẽ không hài lòng lắm với sơ đồ này.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Có vẻ như tất cả các cải tiến của chúng tôi có thể được quảng cáo trong mã nguồn mở, nhưng Bouncer không hỗ trợ tốt lắm. Ví dụ: khả năng chạy nhiều PgBouncer trên cùng một cổng đã được cam kết một tháng trước. Một yêu cầu kéo với tính năng này đã có cách đây vài năm.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

https://www.postgresql.org/docs/current/libpq-cancel.html

https://github.com/pgbouncer/pgbouncer/pull/79

Hoặc một ví dụ nữa. Trong Postgres, bạn có thể hủy một yêu cầu đang chạy bằng cách gửi bí mật đến một kết nối khác mà không cần xác thực bổ sung. Nhưng một số máy khách chỉ cần gửi TCP-reset, tức là chúng ngắt kết nối mạng. Bouncer sẽ làm gì với điều này? Anh ấy sẽ không làm gì đâu. Nó sẽ tiếp tục thực hiện yêu cầu. Nếu bạn đã nhận được một số lượng lớn các kết nối đặt cơ sở với các yêu cầu nhỏ, thì việc ngắt kết nối khỏi Bouncer là không đủ, bạn vẫn cần hoàn thành các yêu cầu đang chạy trong cơ sở dữ liệu.

Điều này đã được vá và vấn đề vẫn chưa được hợp nhất vào thượng nguồn của Bouncer.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Và vì vậy, chúng tôi đã đi đến kết luận rằng chúng tôi cần có công cụ tổng hợp kết nối của riêng mình, công cụ này sẽ được phát triển, vá lỗi, trong đó có thể nhanh chóng khắc phục sự cố và tất nhiên, công cụ này phải đa luồng.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Chúng tôi đặt đa luồng làm nhiệm vụ chính. Chúng tôi cần có khả năng xử lý tốt làn sóng kết nối TLS đến.

Để làm được điều này, chúng tôi phải phát triển một thư viện riêng gọi là Machinarium, thư viện này được thiết kế để mô tả trạng thái máy của kết nối mạng dưới dạng mã nối tiếp. Nếu bạn xem mã nguồn libpq, bạn sẽ thấy các cuộc gọi khá phức tạp có thể trả lại kết quả cho bạn và nói: "Gọi cho tôi sau một chút. Hiện tại tôi có IO, nhưng khi IO trôi qua, tôi có tải trên bộ xử lý. Và đây là một chương trình đa cấp. Tương tác mạng thường được mô tả bởi một máy trạng thái. Rất nhiều quy tắc như "Nếu trước đây tôi đã nhận được tiêu đề gói có kích thước N, thì bây giờ tôi đang đợi N byte", "Nếu tôi đã gửi gói SYNC, thì bây giờ tôi đang đợi gói có siêu dữ liệu kết quả." Nó chỉ ra một mã phản trực giác khá phức tạp, như thể mê cung được chuyển đổi thành quét dòng. Chúng tôi đã tạo ra nó để thay vì máy trạng thái, lập trình viên mô tả đường dẫn tương tác chính dưới dạng mã mệnh lệnh thông thường. Chỉ trong đoạn mã bắt buộc này, bạn cần chèn những vị trí mà trình tự thực thi cần được ngắt bằng cách chờ dữ liệu từ mạng, chuyển ngữ cảnh thực thi sang một coroutine khác (luồng màu xanh lá cây). Cách tiếp cận này tương tự như việc chúng ta viết liên tiếp đường đi được mong đợi nhất trong mê cung, sau đó thêm các nhánh vào đó.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Kết quả là, chúng tôi có một luồng làm cho TCP chấp nhận và quay vòng chuyển kết nối TPC cho nhiều công nhân.

Trong trường hợp này, mỗi kết nối máy khách luôn chạy trên một bộ xử lý. Và điều này cho phép bạn làm cho nó thân thiện với bộ đệm.

Và bên cạnh đó, chúng tôi đã cải thiện một chút việc thu thập các gói nhỏ thành một gói lớn để giảm tải ngăn xếp TCP của hệ thống.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Ngoài ra, chúng tôi đã cải thiện tổng hợp giao dịch theo nghĩa là Odyssey, khi được định cấu hình, có thể gửi CANCEL và ROLLBACK trong trường hợp kết nối mạng bị lỗi, tức là nếu không có ai đang chờ yêu cầu, Odyssey sẽ thông báo cho cơ sở dữ liệu không cố gắng thực hiện yêu cầu có thể lãng phí tài nguyên quý giá.

Và bất cứ khi nào có thể, chúng tôi giữ kết nối với cùng một khách hàng. Điều này tránh phải cài đặt lại application_name_add_host. Nếu có thể, thì chúng tôi không có thiết lập lại bổ sung các tham số cần thiết cho chẩn đoán.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Chúng tôi làm việc vì lợi ích của Yandex.Cloud. Và nếu bạn đang sử dụng PostgreSQL được quản lý và bạn đã cài đặt bộ tổng hợp kết nối, bạn có thể tạo bản sao logic ra bên ngoài, tức là để lại cho chúng tôi nếu bạn muốn, bằng cách sử dụng bản sao logic. Bouncer bên ngoài luồng sao chép hợp lý sẽ không cung cấp.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Đây là một ví dụ về thiết lập sao chép hợp lý.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Ngoài ra, chúng tôi có hỗ trợ sao chép vật lý ra bên ngoài. Tất nhiên, trong Đám mây, điều đó là không thể, vì khi đó cụm sẽ cung cấp cho bạn quá nhiều thông tin về chính nó. Nhưng trong quá trình cài đặt của bạn, nếu bạn cần sao chép vật lý thông qua bộ kết nối tổng hợp trong Odyssey, điều đó là có thể.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Odyssey có khả năng giám sát hoàn toàn tương thích với PgBouncer. Chúng tôi có cùng một bảng điều khiển thực thi hầu hết các lệnh giống nhau. Nếu thiếu thứ gì đó, hãy gửi yêu cầu kéo hoặc ít nhất là sự cố trên GitHub, chúng tôi sẽ hoàn thành các lệnh cần thiết. Nhưng chúng tôi đã có chức năng chính của bảng điều khiển PgBouncer.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Và tất nhiên chúng tôi có lỗi chuyển tiếp. Chúng tôi sẽ trả lại lỗi do cơ sở báo cáo. Bạn sẽ nhận được thông tin tại sao bạn không ở trong căn cứ, không chỉ là bạn không ở trong đó.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Tính năng này bị tắt trong trường hợp bạn cần tương thích 100% với PgBouncer. Chúng ta có thể cư xử như Bouncer, đề phòng.

Phát triển

Đôi lời về mã nguồn Odyssey.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

https://github.com/yandex/odyssey/pull/66

Ví dụ: có các lệnh "Tạm dừng / Tiếp tục". Chúng thường được sử dụng để cập nhật cơ sở dữ liệu. Nếu bạn cần nâng cấp Postgres, bạn có thể tạm dừng nó trong bộ kết nối, thực hiện pg_upgrade, sau đó tiếp tục. Và từ phía khách hàng, có vẻ như cơ sở dữ liệu đang chậm lại. Chức năng này đã được mang đến cho chúng tôi bởi những người từ cộng đồng. Cô ấy vẫn chưa chết, nhưng mọi thứ sẽ sớm thôi. (đã chết)

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

https://github.com/yandex/odyssey/pull/73 - đã chết

Ngoài ra, một trong những tính năng mới trong PgBouncer là hỗ trợ Xác thực SCRAM, tính năng này cũng do một người không làm việc trong Yandex.Cloud mang đến cho chúng tôi. Cả hai đều là chức năng phức tạp và quan trọng.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Do đó, tôi muốn cho bạn biết Odyssey được làm bằng gì, trong trường hợp bạn cũng muốn viết một số mã ngay bây giờ.

Bạn có cơ sở Odyssey ban đầu, dựa trên hai thư viện chính. Thư viện Kiwi là một triển khai của giao thức tin nhắn Postgres. Tức là, proto 3 gốc của Postgres là các thông báo tiêu chuẩn mà giao diện người dùng và phụ trợ có thể trao đổi. Chúng được triển khai trong thư viện Kiwi.

Thư viện Machinarium là thư viện triển khai luồng. Một đoạn nhỏ của Machinarium này được viết bằng trình biên dịch chương trình. Nhưng đừng lo, chỉ có 15 dòng thôi.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Kiến trúc Odyssey. Có một máy chính đang chạy coroutines. Máy này thực hiện chấp nhận các kết nối TCP đến và phân phối giữa các công nhân.

Trong một công nhân, một trình xử lý cho một số khách hàng có thể hoạt động. Và cũng trong luồng chính, bảng điều khiển và xử lý các tác vụ crone để loại bỏ các kết nối không còn cần thiết trong nhóm đang quay.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Odyssey được thử nghiệm bằng bộ thử nghiệm Postgres tiêu chuẩn. Chúng tôi chỉ chạy kiểm tra cài đặt thông qua Bouncer và thông qua Odyssey, chúng tôi nhận được div null. Có một số thử nghiệm liên quan đến định dạng ngày không hoàn toàn giống nhau trong Bouncer và Odyssey.

Ngoài ra, có nhiều trình điều khiển có thử nghiệm riêng của họ. Và chúng tôi sử dụng các bài kiểm tra của họ để kiểm tra Odyssey.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Ngoài ra, do cấu hình theo tầng của chúng tôi, chúng tôi phải thử nghiệm các gói khác nhau: Postgres + Odyssey, PgBouncer + Odyssey, Odyssey + Odyssey để đảm bảo rằng nếu Odyssey nằm trong bất kỳ phần nào trong tầng thì nó vẫn hoạt động như mong đợi .

Cào

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Chúng tôi sử dụng Odyssey trong sản xuất. Và sẽ không công bằng nếu tôi nói rằng mọi thứ chỉ hoạt động. Không, tức là có, nhưng không phải lúc nào cũng vậy. Ví dụ: trong quá trình sản xuất, mọi thứ chỉ hoạt động bình thường, sau đó những người bạn của chúng tôi từ PostgreSQL Professional đến và nói rằng chúng tôi bị rò rỉ bộ nhớ. Họ thực sự là, chúng tôi đã sửa chúng. Nhưng nó thật đơn giản.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Sau đó, chúng tôi nhận thấy rằng bộ tổng hợp kết nối có các kết nối TLS đến và các kết nối TLS đi. Và các kết nối cần chứng chỉ ứng dụng khách và chứng chỉ máy chủ.

Chứng chỉ máy chủ Bouncer và Odyssey được pcache đọc lại, nhưng chứng chỉ ứng dụng khách không cần phải đọc lại từ pcache, vì Odyssey có thể mở rộng của chúng tôi cuối cùng phụ thuộc vào hiệu suất hệ thống khi đọc chứng chỉ này. Điều này khiến chúng tôi ngạc nhiên vì anh ấy không nghỉ ngơi ngay lập tức. Lúc đầu, nó được mở rộng theo tuyến tính và sau 20 kết nối đến đồng thời, sự cố này đã tự xuất hiện.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Pluggable Authentication Method là khả năng xác thực bằng các công cụ lunux tích hợp sẵn. Trong PgBouncer, nó được triển khai theo cách có một luồng riêng chờ phản hồi từ PAM và có một luồng PgBouncer chính phục vụ kết nối hiện tại và có thể yêu cầu chúng nằm trong luồng PAM.

Chúng tôi đã không thực hiện điều này vì một lý do đơn giản. Chúng tôi có nhiều luồng. Tại sao chúng ta cần nó?

Do đó, điều này có thể tạo ra sự cố ở chỗ nếu bạn có xác thực PAM và xác thực không PAM, thì một đợt xác thực PAM lớn có thể làm chậm đáng kể xác thực không PAM. Đó là một trong những thứ mà chúng tôi chưa sửa. Nhưng nếu bạn muốn sửa nó, bạn có thể làm điều này.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Một vấn đề khác là chúng ta có một luồng chấp nhận tất cả các kết nối đến. Và sau đó chúng được chuyển đến nhóm công nhân, nơi sẽ diễn ra quá trình bắt tay TLS.

Do đó, nếu bạn có một làn sóng nhất quán gồm 20 kết nối mạng, tất cả chúng sẽ được chấp nhận. Và về phía máy khách, libpq sẽ bắt đầu báo cáo thời gian chờ. Theo mặc định, nó giống như 000 giây ở đó.

Nếu tất cả họ không thể vào cơ sở cùng một lúc, thì họ không thể vào cơ sở, bởi vì tất cả điều này có thể được bao phủ bởi một lần thử lại không theo cấp số nhân.

Cuối cùng, chúng tôi đã sao chép lược đồ PgBouncer tại đây để chúng tôi điều chỉnh số lượng kết nối TCP mà chúng tôi chấp nhận.

Nếu chúng tôi thấy rằng chúng tôi đang chấp nhận kết nối nhưng cuối cùng họ không có thời gian để bắt tay, chúng tôi sẽ đặt chúng vào hàng đợi để chúng không tiêu tốn tài nguyên CPU. Điều này dẫn đến thực tế là không thể thực hiện bắt tay đồng thời cho tất cả các kết nối đã đến. Nhưng ít nhất sẽ có người vào cơ sở dữ liệu, ngay cả khi tải đủ mạnh.

Lộ trình

Bạn muốn thấy điều gì trong tương lai ở Odyssey? Chúng ta đã sẵn sàng gì để phát triển bản thân và chúng ta mong đợi gì từ cộng đồng?

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Cho tháng 2019 năm XNUMX.

Đây là lộ trình của Odyssey vào tháng XNUMX:

  • Chúng tôi muốn xác thực SCRAM và PAM.
  • Chúng tôi muốn chuyển tiếp các yêu cầu đã đọc sang chế độ chờ.
  • Tôi muốn khởi động lại trực tuyến.
  • Và khả năng tạm dừng trên máy chủ.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Một nửa lộ trình này đã được thực hiện và không phải bởi chúng tôi. Và điều này là tốt. Vì vậy, hãy thảo luận về những gì còn lại và bổ sung thêm.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Liên quan đến chuyển tiếp các truy vấn chỉ đọc sang chế độ chờ? Chúng tôi có các bản sao, nếu không đáp ứng các yêu cầu, sẽ chỉ làm nóng không khí. Chúng tôi cần họ cung cấp chuyển đổi dự phòng và chuyển đổi. Trong trường hợp xảy ra sự cố ở một trong các trung tâm dữ liệu, tôi muốn giải quyết chúng bằng một số công việc hữu ích. Bởi vì chúng tôi không thể định cấu hình cùng một bộ xử lý trung tâm, cùng một bộ nhớ theo một cách khác, vì việc sao chép sẽ không hoạt động theo cách khác.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Về nguyên tắc, trong Postgres, bắt đầu từ 10, có thể chỉ định session_attrs khi kết nối. Bạn có thể liệt kê tất cả các máy chủ cơ sở dữ liệu trong kết nối và cho biết lý do tại sao bạn truy cập cơ sở dữ liệu: chỉ ghi hoặc chỉ đọc. Và bản thân trình điều khiển sẽ chọn máy chủ đầu tiên trong danh sách mà nó thích nhất, đáp ứng các yêu cầu của session_attrs.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Nhưng vấn đề với phương pháp này là nó không kiểm soát độ trễ sao chép. Bạn có thể có một số loại bản sao bị chậm trễ bởi thời gian không thể chấp nhận được đối với dịch vụ của bạn. Trên thực tế, để thực hiện đầy đủ tính năng của các yêu cầu đọc trên một bản sao, chúng tôi cần hỗ trợ trong Odyssey khả năng không hoạt động khi không thể đọc.

Thỉnh thoảng, Odyssey phải truy cập cơ sở dữ liệu và yêu cầu khoảng cách sao chép từ chính. Và nếu nó đã đạt đến giới hạn, đừng để các yêu cầu mới vào cơ sở dữ liệu, hãy nói với khách hàng rằng bạn cần bắt đầu lại các kết nối và có thể chọn một máy chủ khác để thực hiện các yêu cầu. Điều này sẽ cho phép cơ sở dữ liệu nhanh chóng khôi phục độ trễ sao chép và quay trở lại để trả lời một truy vấn.

Rất khó để đặt tên cho ngày thực hiện, bởi vì nó là mã nguồn mở. Nhưng, tôi hy vọng, không phải 2,5 năm như các đồng nghiệp từ PgBouncer. Đây là tính năng tôi muốn thấy trong Odyssey.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Trong cộng đồng, mọi người hỏi về hỗ trợ tuyên bố chuẩn bị. Bây giờ bạn có thể tạo một câu lệnh đã chuẩn bị sẵn theo hai cách. Đầu tiên, bạn có thể thực thi một lệnh SQL, cụ thể là "đã chuẩn bị". Để hiểu được lệnh SQL này, chúng ta cần học cách hiểu SQL ở phía Bouncer. Điều này sẽ là quá mức cần thiết vì nó quá mức cần thiết vì chúng tôi cần toàn bộ trình phân tích cú pháp. Chúng tôi không thể phân tích cú pháp mọi lệnh SQL.

Nhưng có một tuyên bố được chuẩn bị sẵn ở cấp giao thức thông báo trên proto3. Và đây là nơi thông tin mà câu lệnh đã chuẩn bị được tạo ra ở dạng có cấu trúc. Và chúng tôi có thể hỗ trợ hiểu rằng trên một số kết nối máy chủ, khách hàng đã yêu cầu tạo các câu lệnh đã chuẩn bị. Và ngay cả khi giao dịch đã đóng, chúng tôi vẫn cần giữ cho máy chủ và máy khách được kết nối.

Nhưng ở đây nảy sinh sự khác biệt trong cuộc đối thoại, bởi vì ai đó nói rằng bạn cần hiểu khách hàng đã tạo câu lệnh chuẩn bị nào và chia sẻ kết nối máy chủ giữa tất cả các khách hàng đã tạo kết nối máy chủ này, tức là người đã tạo câu lệnh chuẩn bị sẵn đó.

Andres Freund nói rằng nếu một khách hàng đến gặp bạn, người đã tạo một tuyên bố chuẩn bị sẵn như vậy trong một kết nối máy chủ khác, thì hãy tạo nó cho anh ta. Nhưng có vẻ hơi sai khi thực hiện các truy vấn trong cơ sở dữ liệu thay vì ứng dụng khách, nhưng theo quan điểm của nhà phát triển, người viết giao thức để tương tác với cơ sở dữ liệu, sẽ rất thuận tiện nếu anh ta chỉ được cấp một kết nối mạng. mà có một yêu cầu chuẩn bị như vậy.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Và một tính năng nữa mà chúng ta cần thực hiện. Chúng tôi hiện có tính năng giám sát tương thích với PgBouncer. Chúng tôi có thể trả về thời gian thực hiện truy vấn trung bình. Nhưng thời gian trung bình là nhiệt độ trung bình trong bệnh viện: ai đó lạnh, ai đó ấm - trung bình mọi người đều khỏe mạnh. Không phải như vậy.

Chúng tôi cần triển khai hỗ trợ cho phần trăm, điều này cho thấy rằng có các yêu cầu chậm tiêu tốn tài nguyên và sẽ giúp việc giám sát dễ chấp nhận hơn.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Điều quan trọng nhất là tôi muốn phiên bản 1.0 (Phiên bản 1.1 đã được phát hành). Thực tế là hiện tại Odyssey đang ở phiên bản 1.0rc, tức là ứng cử viên phát hành. Và tất cả các lỗi mà tôi liệt kê đã được sửa chính xác với cùng một phiên bản, ngoại trừ lỗi rò rỉ bộ nhớ.

Phiên bản 1.0 có ý nghĩa gì đối với chúng tôi? Chúng tôi đang triển khai Odyssey đến các căn cứ của chúng tôi. Nó đã chạy trên cơ sở dữ liệu của chúng tôi, nhưng khi nó đạt đến điểm 1 yêu cầu mỗi giây, thì chúng tôi có thể nói rằng đây là phiên bản phát hành và đây là phiên bản có thể được gọi là 000.

Một số người trong cộng đồng đã yêu cầu thêm tạm dừng và SCRAM trong phiên bản 1.0. Nhưng điều này có nghĩa là chúng tôi sẽ cần đưa phiên bản tiếp theo vào sản xuất, vì cả SCRAM và tạm dừng đều chưa được hợp nhất. Nhưng, rất có thể, vấn đề này sẽ được giải quyết khá nhanh chóng.

Lộ trình của Odyssey: chúng ta còn muốn gì nữa từ một công cụ tổng hợp kết nối. Andrey Borodin (2019)

Tôi đang chờ yêu cầu kéo của bạn. Và tôi cũng muốn biết bạn gặp vấn đề gì với Bouncer. Hãy thảo luận về chúng. Có lẽ chúng tôi có thể thực hiện một số chức năng mà bạn cần.

Điều này kết thúc phần của tôi, tôi muốn nghe từ bạn. Cảm ơn!

câu hỏi

Nếu tôi đặt application_name của riêng mình, nó có được đưa ra chính xác không, bao gồm cả giao dịch tổng hợp trong Odyssey?

Odyssey hay Bouncer?

Trong Odyssey. Bouncer được ném.

Chúng ta sẽ làm một bộ.

Và nếu kết nối thực của tôi nhảy qua các kết nối khác, liệu nó có được truyền đi không?

Chúng tôi sẽ tạo một tập hợp tất cả các tham số được liệt kê. Tôi không thể biết liệu application_name có trong danh sách này hay không. Có vẻ như anh ấy đã nhìn thấy anh ta ở đó. Chúng tôi sẽ thiết lập tất cả các thông số giống nhau. Với một yêu cầu, bộ sẽ thực hiện mọi thứ đã được khách hàng cài đặt trong quá trình khởi động.

Cảm ơn Andrey cho báo cáo! Báo cáo tốt! Tôi rất vui vì Odyssey đang phát triển ngày càng nhanh hơn mỗi phút. Tôi muốn tiếp tục như vậy. Chúng tôi đã yêu cầu bạn có kết nối nhiều nguồn dữ liệu để Odyssey có thể kết nối với các cơ sở dữ liệu khác nhau cùng một lúc, tức là chủ phụ, sau đó tự động kết nối với chủ mới sau khi chuyển đổi dự phòng.

Vâng, tôi dường như nhớ lại cuộc thảo luận đó. Bây giờ có một số kho lưu trữ. Nhưng không có chuyển đổi giữa chúng. Về phía chúng tôi, chúng tôi phải truy vấn máy chủ rằng nó vẫn còn hoạt động và hiểu rằng đã xảy ra chuyển đổi dự phòng, ai sẽ gọi pg_recovery. Tôi có một cách tiêu chuẩn để hiểu rằng chúng tôi đã không đến với chủ. Và chúng ta phải hiểu bằng cách nào đó từ những sai lầm hay như thế nào? Đó là, ý tưởng thú vị, nó đang được thảo luận. Viết thêm bình luận. Nếu bạn có bàn tay làm việc biết C, thì điều này nói chung là tuyệt vời.

Chúng tôi cũng quan tâm đến vấn đề mở rộng quy mô trên các bản sao, bởi vì chúng tôi muốn làm cho việc áp dụng các cụm sao chép trở nên đơn giản nhất có thể cho các nhà phát triển ứng dụng. Nhưng ở đây tôi xin góp ý thêm, đó là làm như thế nào, làm như thế nào cho tốt.

Câu hỏi cũng là về bản sao. Hóa ra bạn có một bản gốc và một số bản sao. Và rõ ràng là họ đến bản sao ít thường xuyên hơn so với bản chính để kết nối, vì chúng có thể có sự khác biệt. Bạn đã nói rằng sự khác biệt về dữ liệu có thể khiến doanh nghiệp của bạn không hài lòng và bạn sẽ không đến đó cho đến khi nó được sao chép. Đồng thời, nếu bạn đã không đến đó trong một thời gian dài và sau đó bắt đầu đi, thì dữ liệu bạn cần sẽ không có sẵn ngay lập tức. Đó là, nếu chúng ta liên tục chuyển đến bản chính, thì bộ đệm sẽ được khởi động ở đó và bộ đệm sẽ chậm hơn một chút so với bản sao.

Vâng đúng vậy. Sẽ không có khối dữ liệu nào trong pcache mà bạn muốn, trong bộ đệm thực sẽ không có thông tin về các bảng mà bạn muốn, sẽ không có truy vấn được phân tích cú pháp trong các gói, không có gì cả.

Và khi bạn có một số loại cụm và bạn thêm một bản sao mới vào đó, thì trong khi nó khởi động, mọi thứ đều tồi tệ trong đó, tức là nó phát triển bộ đệm của nó.

Tôi có ý tưởng. Cách tiếp cận đúng sẽ là trước tiên chạy một tỷ lệ phần trăm truy vấn nhỏ trên bản sao, điều này sẽ làm ấm bộ đệm. Nói một cách đại khái, chúng ta có một điều kiện là phải chậm hơn chủ nhân không quá 10 giây. Và điều kiện này không nên được đưa vào một làn sóng, nhưng đối với một số khách hàng một cách suôn sẻ.

Vâng, tăng cân.

Đây là một ý tưởng tốt. Nhưng trước tiên bạn cần thực hiện việc tắt máy này. Đầu tiên chúng ta cần tắt, sau đó chúng ta sẽ nghĩ cách bật. Đây là một tính năng tuyệt vời để bật trơn tru.

nginx có tùy chọn này slowly start trong cụm cho máy chủ. Và anh ta dần dần tăng tải.

Vâng, ý tưởng tuyệt vời, chúng tôi sẽ thử khi đạt được điều đó.

Nguồn: www.habr.com

Thêm một lời nhận xét