2011-07-08 36 views
5

Tôi đang phát triển máy chủ 'proxy' trong Chế độ tiết kiệm. Vấn đề của tôi là, mỗi kết nối đến proxy đều sử dụng cùng một cá thể của Trình xử lý. Việc thực hiện máy khách của proxy nằm trong Handler, vì vậy tất cả các máy khách đều liên lạc với cùng một kết nối đến máy chủ kết thúc.Tiết kiệm - phiên bản Trình xử lý khác nhau cho mỗi Ổ cắm

Tôi có: n khách hàng -> n ổ cắm -> 1 trình xử lý -> 1 socket -> 1 máy chủ Tôi muốn thực hiện: n khách hàng -> n socket -> n trình xử lý -> n ổ cắm -> 1 máy chủ

Bây giờ vấn đề là nếu một khách hàng thay đổi một tham số 'cục bộ' (một cái gì đó được xác định cho mỗi khách hàng một cách độc lập) trên máy chủ, các máy khách khác cũng sẽ làm việc với môi trường đã thay đổi.

shared_ptr<CassProxyHandler> handler(new CassProxyHandler(adr_s,port_s,keyspace)); 
shared_ptr<TProcessor> processor(new CassandraProcessor(handler)); 
shared_ptr<TServerTransport> serverTransport(new TServerSocket(port)); 
shared_ptr<TTransportFactory> transportFactory(new TFramedTransportFactory()); 
shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory()); 
TThreadedServer server(processor, serverTransport, transportFactory, protocolFactory); 
server.serve(); 

Có cách nào để triển khai máy chủ, tạo một phiên bản mới của Trình xử lý cho mỗi socket máy chủ thay vì sử dụng cùng một trình xử lý không?

Thanks cho bất kỳ gợi ý hay giúp đỡ, @

Trả lời

4

Tôi đã cố gắng giải quyết vấn đề này. Đã có một giải pháp đã được thực hiện trong Java. Tôi đã sử dụng cùng một ý tưởng và thực hiện nó trong C++.

Điều đầu tiên tôi làm là tạo một TProcessorFactory thay vì lớp TTransport. Điều này xử lý các TProcessors cho mỗi kết nối. Nó có một cấu trúc bản đồ trong nó, do đó, hàm 'get của nó trả về TProcessor tương ứng cho mỗi TTransport. TProcessor tương ứng (duy nhất) cho mỗi khách hàng.

Tôi phải tạo một TServer mới, vì vậy nó sẽ chấp nhận tham số mới được tạo ra TProcessorFactory thay cho TProcessor. Trong TServer cũng cần thiết để thay đổi một vài cuộc gọi hàm. Hàm getProcessor của bạn sẽ không còn trả về một TProcessor mà là một TProcessorFactory (vì vậy hãy thay đổi kiểu trả về và đổi tên).

Điều cuối cùng bạn phải làm là triển khai máy chủ cho phép khởi tạo, một lớp dẫn xuất của TServer. Tôi đề nghị sử dụng các TNonblockingServer (bit khó hơn để thực hiện thay đổi) hoặc TThreadPoolServer. Bạn phải thay đổi một vài cuộc gọi hàm. Sử dụng hàm get trên TProcessorFactory với tham số TTransport để có được một TProcessor khi cần thiết. Tham số TTransport là duy nhất cho mỗi luồng, mỗi kết nối máy khách được xử lý bởi một luồng. Ngoài ra hãy chắc chắn rằng bạn xóa các TProcessors cũ, bởi vì tiết kiệm hàng loạt (ít nhất là với TNonblockingServer) TTransport, vì vậy nếu bạn không xóa chúng và một khách hàng kết nối, anh ta có thể sẽ có một phiên không hoạt động trước đó và bạn có thể không không muốn. Nếu bạn sử dụng các con trỏ được chia sẻ, chỉ cần xóa chúng khỏi cấu trúc bản đồ, khi máy khách ngắt kết nối và nếu không còn cần thiết bằng cách tiết kiệm, chúng sẽ bị hủy.

Tôi hy vọng điều này sẽ giúp cho bất kỳ ai, những người gặp phải cùng một vấn đề tôi đã làm. Nếu bạn không biết cấu trúc bên trong của tiết kiệm, dưới đây là hướng dẫn tốt: http://diwakergupta.github.com/thrift-missing-guide/

Tôi hy vọng các nhà phát triển tiết kiệm sẽ thực hiện một giải pháp tương tự, phức tạp và trừu tượng hơn trong tương lai gần.

@

+0

Bạn đã từng đặt yêu cầu vé/vấn đề/tính năng @ apache tiết kiệm chưa? Tôi nghĩ rằng điều này cũng có thể được sử dụng để cho phép giao tiếp song công/hai chiều rất dễ dàng. – BatteryBackupUnit

0

Thay vì làm cho máy chủ proxy nói chuyện tiết kiệm của bạn, bạn chỉ có thể làm cho nó một TCP proxy chung mở ra một kết nối TCP mới cho mỗi kết nối đến.

+0

Tôi đã nghĩ về điều đó, tuy nhiên tôi cần gói giải nén để tôi có thể chuyển tiếp gói đến máy chủ phù hợp dựa trên thông tin chứa. Nó sẽ là số lượng lớn công việc để thực hiện nó mà không tiết kiệm. –

1

Tôi biết đây là một chủ đề cũ, nhưng trong trường hợp đó là bao giờ sử dụng cho bất cứ ai - Tôi đã đóng góp một sự thay đổi đến việc thực hiện C# của Thrift để giải quyết vấn đề này ...

https://issues.apache.org/jira/browse/THRIFT-3397

Ngoài các phương pháp cũ đi qua một TProcessor như là đối số đầu tiên đến các máy chủ ren, bây giờ người ta có thể thiết lập một cái gì đó giống như

new ThreadPoolServer(processorFactory,serverTransport, 
            transportFactory,protocolFactory); 

Trường hợp 'processorFactory' là một TProcessorFactory.

Tôi đã tạo TPrototypeProcessorFactory < TProcessor, Handler > (object [] handlerArgs) mà sẽ được thiết lập như sau:

TProcessorFactory processorFactory = 
     new TPrototypeProcessorFactory<ThriftGenerated.Processor, MyHandlerClass>(); 

Các 'MyHandlerClass' thực hiện ThriftGenerated.Iface của bạn. Theo tùy chọn, nếu lớp này có đối số, chúng có thể được thêm dưới dạng một mảng đối tượng vào nhà máy xử lý. nội - Đối với mỗi kết nối khách hàng mới, nhà máy xử lý này sẽ:

  1. Tạo một thể hiện mới của 'MyHandlerClass' sử dụng bất kỳ đối số cung cấp (sử dụng Activator.CreateInstance)

  2. Nếu cụ 'MyHandlerClass' 'TControllingHandler', nó sẽ đặt thuộc tính 'máy chủ' của nó thành TServer cha mẹ (ví dụ: để cho phép kiểm soát TServer bằng cách sử dụng máy khách nhanh)

  3. Trả về phiên bản mới của Thrif tGenerated.Processor (handler)

Vì vậy cho C# bạn nhận được n khách hàng -> n ổ cắm -> n xử lý -> n ổ cắm -> 1 máy chủ

Tôi hy vọng điều này trở nên hữu ích cho người khác - nó chắc chắn đã giải quyết được vấn đề cho tôi.

Các vấn đề liên quan