2011-11-22 25 views
9

Tôi đã thử nghiệm với Event Store 3.0 của JOliver như một thành phần tiềm năng trong một dự án và đã cố gắng đo lường thông lượng của các sự kiện thông qua Cửa hàng Sự kiện.Event Store 3.0 - Thông lượng/Hiệu suất

Tôi bắt đầu sử dụng một khai thác đơn giản về cơ bản lặp qua vòng lặp for tạo luồng mới và cam kết một sự kiện rất đơn giản bao gồm id GUID và thuộc tính chuỗi cho MSSQL2K8 R2 DB. Điều phối viên cơ bản là một no-op.

Cách tiếp cận này quản lý để đạt được ~ 3K hoạt động/giây chạy trên một cách 8 HP G6 DL380 với DB trên một cách riêng biệt 32 G7 DL580. Các máy thử nghiệm không bị ràng buộc tài nguyên, việc chặn xem có vẻ là giới hạn trong trường hợp của tôi.

Có ai có bất kỳ kinh nghiệm nào về đo lường thông lượng của Cửa hàng sự kiện và đã đạt được loại số liệu nào không? Tôi đã hy vọng có được ít nhất 1 đơn hàng thông lượng lớn hơn để làm cho nó trở thành một lựa chọn khả thi.

Trả lời

6

Tôi đồng ý rằng việc chặn IO sẽ là nút cổ chai lớn nhất. Một trong những vấn đề mà tôi có thể thấy với điểm chuẩn là bạn đang hoạt động chống lại một luồng. Bạn có bao nhiêu nguồn gốc tổng hợp trong miền của mình với sự kiện 3K + mỗi giây? Thiết kế chính của EventStore là cho các hoạt động đa luồng đối với nhiều tập hợp làm giảm ganh đua và khóa cho các ứng dụng đọc thế giới.

Ngoài ra, bạn đang sử dụng cơ chế tuần tự hóa nào? JSON.NET? Tôi chưa có triển khai thực hiện Protocol Buffers, nhưng mọi điểm chuẩn cho thấy PB nhanh hơn đáng kể về hiệu suất. Nó sẽ là thú vị để chạy một hồ sơ đối với ứng dụng của bạn để xem nơi các nút cổ chai lớn nhất được.

Một điều khác tôi nhận thấy là bạn đang giới thiệu một bước nhảy mạng vào phương trình làm tăng độ trễ (và thời gian chặn) đối với bất kỳ luồng nào. Nếu bạn đang viết cho một cá thể SQL cục bộ sử dụng các ổ đĩa trạng thái rắn, tôi có thể thấy các con số cao hơn nhiều so với một cá thể SQL từ xa chạy các ổ đĩa từ và có các tệp dữ liệu và bản ghi trên cùng một đĩa.

Cuối cùng, ứng dụng chuẩn của bạn có sử dụng System.Transactions hoặc đã làm mặc định cho giao dịch không? (EventStore là an toàn mà không cần sử dụng System.Transactions hoặc bất kỳ loại giao dịch SQL nào.)

Bây giờ, với tất cả những gì được nói, tôi không có nghi ngờ rằng có các khu vực trong EventStore có thể được tối ưu hóa đáng kể với chút chú ý. Như một vấn đề của thực tế, tôi đang đá xung quanh một vài sửa đổi lược đồ tương thích ngược cho bản phát hành 3.1 để giảm số lượng ghi được thực hiện trong SQL Server (và các công cụ RDBMS nói chung) trong một hoạt động cam kết đơn.

Một trong những câu hỏi thiết kế lớn nhất mà tôi gặp phải khi bắt đầu viết lại 2.x làm nền tảng cho 3.x là ý tưởng không đồng bộ, không chặn IO. Chúng ta đều biết rằng node.js và các máy chủ web không chặn khác đánh bại các máy chủ web luồng theo thứ tự độ lớn. Tuy nhiên, tiềm năng cho sự phức tạp được giới thiệu trên người gọi được tăng lên và là cái gì đó phải được xem xét mạnh mẽ bởi vì nó là một sự thay đổi cơ bản trong cách hầu hết các chương trình và thư viện hoạt động. Nếu và khi chúng ta chuyển sang mô hình không bị chặn, nó sẽ có nhiều hơn trong khung thời gian 4.x.

Điểm mấu chốt: xuất bản điểm chuẩn của bạn để chúng tôi có thể biết nơi mà các nút cổ chai là.

+1

Cảm ơn câu trả lời Jonathan. Để làm rõ;) Mỗi ​​Commit là một EventSource mới, vì vậy tôi cam kết 3K EventSources riêng biệt mỗi giây. Ommiting mạng hop đã không cải thiện mọi thứ nhưng là một điểm hợp lệ. Theo như giao dịch có liên quan, tôi không rõ ràng tranh thủ trong một giao dịch nhưng đó có thể không giống như việc không sử dụng Giao dịch. Tôi đang sử dụng JSON cho serialization mặc dù như chúng tôi không bị ràng buộc CPU Tôi không nghĩ rằng đó là hạn chế chúng tôi được nêu ra. Tôi đã xuất bản các thử nghiệm khai thác để GitHub (https://github.com/MattCollinge/EventStore-Performance-Tests.git). – MattC

6

Câu hỏi tuyệt vời Matt (+1) và tôi thấy chính Oliver trả lời là câu trả lời (+1)!

Tôi muốn ném theo một cách tiếp cận hơi khác so với bản thân tôi đang chơi với để trợ giúp với 3.000 nút thắt cổ chai mỗi giây bạn đang thấy.

Mẫu CQRS, hầu hết mọi người sử dụng EventStore của JOliver dường như đang cố gắng theo dõi, cho phép một số mẫu phụ "mở rộng". Người đầu tiên thường xếp hàng là sự kiện tự cam kết, mà bạn đang nhìn thấy một nút cổ chai. "Queue off" có nghĩa là được tải xuống từ các cam kết thực tế và chèn chúng vào một số quy trình I/O được ghi tối ưu, không bị chặn hoặc " xếp hàng".

giải thích lỏng lẻo của tôi là: Quá trình phát

lệnh -> Handlers lệnh -> Tin quảng bá cho sự kiện -> xử lý sự kiện -> Store tổ chức sự kiện

Có thực sự hai điểm quy mô-ra ở đây trong các mô hình: các Trình xử lý lệnhTrình xử lý sự kiện. Như đã nói ở trên, hầu hết bắt đầu với việc chia tỷ lệ phần xử lý sự kiện hoặc Cam kết trong trường hợp của bạn thành thư viện EventStore, vì đây thường là nút cổ chai lớn nhất do cần phải lưu giữ ở đâu đó (ví dụ: cơ sở dữ liệu Microsoft SQL Server).

Bản thân tôi đang sử dụng một vài nhà cung cấp khác nhau để kiểm tra hiệu suất tốt nhất để "xếp hàng" các cam kết này. CouchDB và AppFabric Cache của .NET (có tính năng GetAndLock() tuyệt vời). [OT] Tôi thực sự thích các tính năng lưu trữ lâu bền của AppFabric cho phép bạn tạo các máy chủ lưu trữ dự phòng sao lưu vùng của bạn trên nhiều máy - do đó, bộ nhớ cache của bạn vẫn hoạt động miễn là có ít nhất 1 máy chủ hoạt động. [/ OT]

Vì vậy, hãy tưởng tượng Trình xử lý sự kiện của bạn không ghi các cam kết trực tiếp vào EventStore. Thay vào đó, bạn có một trình xử lý chèn chúng vào một hệ thống "xếp hàng", chẳng hạn như Hàng đợi Windows Azure, CouchDB, Memcache, AppFabric Cache, v.v. Vấn đề là chọn một hệ thống có ít hoặc không có khối để xếp hàng các sự kiện, nhưng đó là bền với dự phòng được xây dựng trong (Memcache được yêu thích nhất của tôi cho các tùy chọn dự phòng). Bạn phải có dự phòng đó, trong trường hợp nếu máy chủ bị giảm, bạn vẫn có sự kiện xếp hàng.

Để cuối cùng cam kết từ "Sự kiện xếp hàng" này, có một số tùy chọn. Tôi thích mẫu hàng đợi của Windows Azure cho điều này, bởi vì nhiều "công nhân" bạn có thể liên tục tìm kiếm công việc trong hàng đợi. Nhưng nó không phải là Windows Azure - Tôi đã bắt chước mẫu Queue của Azure trong mã cục bộ bằng cách sử dụng một "Queue" và "Worker Roles" chạy trong các chủ đề nền. Nó quy mô thực sự độc đáo.

Giả sử bạn có 10 công nhân liên tục xem xét "hàng đợi" này cho bất kỳ sự kiện Cập nhật người dùng nào (tôi thường viết một vai trò công nhân cho mỗi loại sự kiện, giúp bạn dễ dàng theo dõi số liệu thống kê của từng loại). Hai sự kiện được đưa vào hàng đợi, hai công nhân đầu tiên ngay lập tức nhận một tin nhắn, và chèn chúng (Commit them) trực tiếp vào EventStore của bạn cùng một lúc - đa luồng, như Jonathan đã đề cập trong câu trả lời của anh ta. Nút cổ chai của bạn với mẫu đó sẽ là bất kỳ cơ sở dữ liệu/sự kiện sao lưu nào bạn chọn. Giả sử EventStore của bạn đang sử dụng MSSQL và nút cổ chai vẫn là 3.000 RPS. Đó là tốt, bởi vì hệ thống được xây dựng để 'bắt kịp' khi những RPS rơi xuống, nói 50 RPS sau khi một vụ nổ 20.000. Đây là mô hình tự nhiên CQRS cho phép: "Sự nhất quán cuối cùng".

Tôi đã nói rằng có các mẫu quy mô khác có nguồn gốc từ các mẫu CQRS. Khác, như tôi đã đề cập ở trên, là các trình xử lý lệnh (hoặc các sự kiện lệnh). Đây là một trong những tôi đã làm là tốt, đặc biệt là nếu bạn có một tên miền miền rất phong phú là một trong những khách hàng của tôi không (hàng chục kiểm tra xác nhận chuyên sâu xử lý trên mỗi lệnh). Trong trường hợp đó, tôi sẽ thực sự xếp hàng các Lệnh, để được xử lý trong nền bởi một số vai trò công nhân.Điều này mang lại cho bạn một mô hình quy mô tốt đẹp là tốt, bởi vì bây giờ toàn bộ phụ trợ của bạn, bao gồm các cam kết EvetnStore của sự kiện, có thể được luồng.

Rõ ràng, nhược điểm đó là bạn mất một số kiểm tra xác nhận thời gian thực. Tôi giải quyết điều đó bằng cách thường phân đoạn xác nhận thành hai loại khi cấu trúc miền của tôi. Một là Ajax hoặc thời gian thực "nhẹ" xác nhận trong tên miền (loại giống như một kiểm tra Pre-Command). Và những người khác là kiểm tra xác thực không thành công, chỉ được thực hiện trong miền nhưng không có sẵn để kiểm tra thời gian thực. Sau đó bạn sẽ cần phải mã-cho-thất bại trong mô hình miền. Có nghĩa là, luôn luôn mã cho một con đường ra nếu một cái gì đó không thành công, thường là trong các hình thức của một email thông báo lại cho người dùng rằng một cái gì đó đã đi sai. Vì người dùng không còn bị chặn bởi Lệnh được xếp hàng đợi này, nên họ cần phải được thông báo nếu lệnh không thành công.

Và kiểm tra xác nhận của bạn mà cần phải đi đến các 'backend' sẽ truy vấn của bạn hoặc "read-only" cơ sở dữ liệu, riiiight? Đừng đi vào EventStore để kiểm tra, ví dụ, một địa chỉ Email duy nhất. Bạn sẽ thực hiện xác thực của mình dựa trên kho dữ liệu chỉ đọc có sẵn cao cho các Truy vấn của giao diện người dùng của bạn. Heck, có một tài liệu CouchDB duy nhất được dành riêng cho chỉ một danh sách của tất cả các địa chỉ email trong hệ thống như phần truy vấn của bạn của CQRS.

CQRS chỉ là gợi ý ... Nếu bạn thực sự cần kiểm tra thời gian thực của một phương pháp xác thực nặng, thì bạn có thể xây dựng một cửa hàng truy vấn (chỉ đọc) xung quanh đó và tăng tốc xác thực - trên giai đoạn PreCommand, trước nó được chèn vào hàng đợi. Rất linh hoạt. Và tôi thậm chí còn cho rằng việc xác thực những thứ như tên người dùng trống và email trống không phải là mối quan tâm của miền, mà là trách nhiệm của giao diện người dùng (không cần phải thực hiện xác thực thời gian thực trong miền). Tôi đã phác thảo một vài dự án mà tôi đã xác thực giao diện người dùng rất phong phú trên MVC/MVVM ViewModels của mình. Tất nhiên tên miền của tôi đã xác nhận rất nghiêm ngặt, để đảm bảo rằng nó hợp lệ trước khi xử lý. Nhưng di chuyển kiểm tra xác thực đầu vào tầm thường, hoặc cái mà tôi gọi là xác nhận "trọng lượng nhẹ", vào các lớp ViewModel, cung cấp phản hồi gần như ngay lập tức cho người dùng cuối mà không cần tiếp cận miền của tôi. (Có những thủ thuật để giữ cho rằng đồng bộ với tên miền của bạn là tốt).

Tóm lại, có thể xem xét xếp hàng các Sự kiện đó trước khi chúng được cam kết. Điều này phù hợp với các tính năng đa luồng của EventStore khi Jonathan đề cập đến câu trả lời của anh.

+1

Câu trả lời thú vị. Cảm ơn bạn đã viết nó lên! –

0

Chúng tôi xây dựng một boilerplate nhỏ cho đồng thời lớn sử dụng Erlang/Elixir, https://github.com/work-capital/elixir-cqrs-eventsourcing sử dụng Eventstore. Chúng tôi vẫn phải tối ưu hóa kết nối db, tổng hợp, v.v ... nhưng ý tưởng có một quy trình cho mỗi tổng hợp với nhiều kết nối db phù hợp với nhu cầu của bạn.