Đây là tình huống khi tính song song phải được đưa vào máy chủ phụ trợ.
Tôi sẵn sàng truy vấn N ELB, mỗi truy vấn có 5 truy vấn khác nhau và gửi kết quả lại cho máy khách web.
Phần phụ trợ là Tornado, theo tôi trongtài liệuTrước đây tôi đã đọc nhiều lần rằng nếu tôi sử dụng @gen.Task hoặc gen.coroutine thì tôi có thể xử lý nhiều tác vụ song song.
Tuy nhiên, tôi chắc chắn đang thiếu một cái gì đó ở đây, bởi vì tất cả các yêu cầu của tôi (số 20, 4 elbs * 5 truy vấn) đang được xử lý lần lượt.
def query_elb(fn, vùng, elb_name, dấu chấm, gọi lại):
gọi lại(fn (vùng, elb_name, dấu chấm))
lớp Bảng điều khiểnELBHandler(RequestHandler):
@tornado.gen.coroutine
def get_elb_info(bản thân, vùng, elb_name, dấu chấm):
elbReq = năng suất gen.Task(query_elb, ELBSumRequest, vùng, elb_name, dấu chấm)
elb2XX = năng suất gen.Task(query_elb, ELBBackend2XX, vùng, elb_name, dấu chấm)
elb3XX = năng suất gen.Task(query_elb, ELBBackend3XX, vùng, elb_name, dấu chấm)
elb4XX = năng suất gen.Task(query_elb, ELBBackend4XX, vùng, elb_name, dấu chấm)
elb5XX = năng suất gen.Task(query_elb, ELBBackend5XX, vùng, elb_name, dấu chấm)
nâng cao cơn lốc xoáy.gen.Return(
[
elbReq,
elb2XX,
elb3XX,
elb4XX,
elb5XX,
]
)
@tornado.web.authenticated
@tornado.web.không đồng bộ
@tornado.gen.coroutine
bài viết chắc chắn (tự):
ret = []
khoảng thời gian = self.get_argument("thời gian", "5 phút")
cloud_deployment = db.foo.bar.baz()
đối với khu vực, triển khai trong cloud_deployment.iteritems():
elb_name = triển khai["elb"][0]
res = năng suất self.get_elb_info(vùng, elb_name, dấu chấm)
ret.append(res)
self.push_json(ret)
def ELBQuery(khu vực, elb_name, range_name, số liệu, thống kê, đơn vị):
kích thước = { u"LoadBalancerName": [elb_name] }
(start_stop, dấu chấm) = calc_range(range_name)
cw = boto.ec2.cloudwatch.connect_to_khu vực (vùng)
data_points = cw.get_metric_statistics( dấu chấm, bắt đầu, dừng,
số liệu, "AWS/ELB", thống kê, thứ nguyên, đơn vị)
trả về data_point
ELBSumRequest = vùng lambda, elb_name, range_name : ELBQuery(vùng, elb_name, range_name, "RequestCount", "Tổng", "Đếm")
ELBLatency = vùng lambda, elb_name, range_name : ELBQuery(vùng, elb_name, range_name, "Độ trễ", "Trung bình", "Giây")
ELBBackend2XX = vùng lambda, elb_name, range_name : ELBQuery(vùng, elb_name, range_name, "HTTPCode_Backend_2XX", "Tổng", "Đếm")
ELBBackend3XX = vùng lambda, elb_name, range_name : ELBQuery(vùng, elb_name, range_name, "HTTPCode_Backend_3XX", "Tổng", "Đếm")
ELBBackend4XX = vùng lambda, elb_name, range_name : ELBQuery(vùng, elb_name, range_name, "HTTPCode_Backend_4XX", "Tổng", "Đếm")
ELBBackend5XX = vùng lambda, elb_name, range_name : ELBQuery(vùng, elb_name, range_name, "HTTPCode_Backend_5XX", "Tổng", "Đếm")
问题是 Truy vấn ELB
là một chức năng chặn. nếu nó không ở đâu đónăng suất
Một coroutine khác, bộ lập lịch coroutine không thể xen kẽ các cuộc gọi. (Đó là toàn bộ mục đích của coroutine - chúng hợp tác chứ không phải là quyền ưu tiên.)
Nếu vấn đề tương tự như phạm vi calc
cuộc gọi, điều đó có thể dễ xử lý - chia nó thành các phần nhỏ hơn, mỗi phần nhường chỗ cho phần tiếp theo, điều này giúp người lập lịch có cơ hội kẹp giữa mỗi khối.
Nhưng rất có thể, lệnh gọi boto đang chặn và phần lớn thời gian chức năng của bạn dành cho việc chờ đợi get_metric_statistic
quay trở lại trong khi không có gì khác có thể chạy.
Vì vậy, làm thế nào để giải quyết vấn đề này?
- Chia một chủ đề cho mỗi nhiệm vụ boto. Tornado giúp dễ dàng bọc các coroutine xung quanh các luồng hoặc các tác vụ trong nhóm luồng một cách trong suốt, giúp bỏ chặn tất cả các thao tác chặn một cách kỳ diệu. Tất nhiên, việc sử dụng các chủ đề sẽ phải trả giá.
- Lên lịch các tác vụ boto trên nhóm luồng thay vì trên mỗi luồng. Sự cân bằng tương tự như #1, đặc biệt nếu bạn chỉ có một số lượng nhỏ nhiệm vụ. (Tuy nhiên, nếu bạn có thể thực hiện 5 tác vụ, mỗi tác vụ cho 500 người dùng khác nhau, bạn có thể muốn có một nhóm dùng chung.)
- Ghi đè hoặc Monkeypatch boto để sử dụng coroutines. Đây sẽ là giải pháp lý tưởng... nhưng đó là giải pháp hiệu quả nhất (và có nguy cơ phá mã lớn nhất mà bạn không hiểu và phải duy trì dưới dạng cập nhật boto, v.v.). Tuy nhiên, ít nhất một số người cũng đã bắt đầu làm điều này, ví dụ:
không đồng bộ
. dự án.
- sử dụng
rau xanh
và điều chỉnh đủ các phần phụ thuộc của thư viện để đánh lừa nó trở nên không đồng bộ. Điều này nghe có vẻ ngô nghê nhưng thực sự có thể là giải pháp tốt nhất;Kết hôn Boto với Tornado为此。
- sử dụng
rau xanh
và khỉ vá toàn bộ stdlib ala gevent
Để lừa boto và lốc xoáy hợp tác với nhau mà không hề hay biết. Điều này nghe có vẻ là một ý tưởng tồi; tốt hơn hết bạn nên chuyển toàn bộ ứng dụng sang gevent
.
- Sử dụng một quy trình riêng biệt (hoặc thậm chí là một nhóm trong số chúng), nó sử dụng cái gì đó như
gevent
的东西。
Nếu không biết thêm chi tiết, tôi khuyên bạn nên xem xét số 2 và số 4 trước, nhưng tôi không thể đảm bảo chúng sẽ là câu trả lời tốt nhất cho bạn.
Tôi là một lập trình viên xuất sắc, rất giỏi!