Điện toán đám mây với Web Amazon Services, Phần 4 : Truyền tin tin cậy với SQS

Tìm hiểu những khái niệm cơ bản về Amazon SimpleDB (SDB) và khám phá một số chức năng được cung cấp bởi boto, một thư viện mã nguồn mở Python để tương tác với SDB. Trong loạt bài "Điện toán mây với Web Amazon Services" tìm hiểu về điện toán đám mây sử dụng dịch vụ Web Amazon. Khám phá cách các dịch vụ cung cấp, một sự thay thế hấp dẫn cho việc kiến trúc và xây dựng các ứng dụng đáng tin cậy với khả năng mở rộng. Trong bài viết này học về dịch vụ nhắn tin tin cậy và có thể mở rộng được được cung cấp bởi Amazon Simple Queue Service (SQS).

Prabhakar Chaganti, Kiến trúc sư trưởng, Ylastic, LLC

Prabhakar Chaganti photoPrabhakar Chaganti là CTO của Ylastic, là người đầu tiên thực hiện xây dựng một giao diện thống nhất cho các nhà kiến trúc sư, nhà quản lý và người giám sát của môi trường điện toán đám mây AWS: EC2, S3, SQS và SimpleDB. Ông cũng là tác giả của hai trong số các cuốn sách được xuất bản gần đây, là Xen Virtualization và GWT Java AJAX Programing. Đồng thời ông cũng giành được giải thưởng cao nhất cho hầu hết các sáng tạo ứng dụng máy ảo trong VMware Global Virtual Appliance Challenge



20 05 2009

Amazon SQS

Amazon Simple Queue Service (SQS) là một khung làm việc truyền tin mở rộng và đáng tin cậy nó làm cho việc tạo, lưu trữ, và lấy các thông điệp trở nên đơn giản. Bạn có thể sử dụng nó như là một cơ sở cho sự gắn kết các ứng dụng dựa trên dịch vụ Web của Amazon của bạn. Sử dụng SQS là cách tuyệt vời để xây dựng các ứng dụng mở rộng trên nền web. Bạn trả phí cho các thông điệp dựa trên lượng sử dụng của bạn. Toàn bộ khung hàng đợi hoạt động bên trong môi trường bảo mật của các trung tâm dữ liệu của chính Amazon.

Một số đặc tính cung cấp bởi SQS:

Tính tin cậy
SQS được xây dựng để lưu trữ các thông điệp SQS một cách dư thừa trên các trung tâm đa dữ liệu và để làm cho chúng luôn sẵn sàng bất cứ khi nào.
Tính đơn giản
Mô hình lập trình cho việc truy cập và sử dụng SQS rất đơn giản và có thể được sử dụng từ rất nhiều ngôn ngữ lập trình khác nhau.
Bảo mật
SQS được thiết kế để cung cấp mức độ bảo mật cao. Sự truy cập tới các thông điệp bị giới hạn trong những người dùng có thẩm quyền.
Tính có thể mở rộng được
SQS cho bạn khả năng để tạo các ứng dụng dựa trên hàng đợi mà có thể đọc và viết các thông điệp không giới hạn, không có một giới hạn nào.
Rẻ
Sử dụng SQS rất kinh tế và là sự thay thế hấp dẫn cho nhu cầu truyền tin của bạn.

Phần còn lại của phần này khám phá các khái niệm mà củng cố khung làm việc của SQS.

Thông điệp Message

Các thông điệp có thể chứa dữ liệu văn bản với dung lượng lên tới 8 KB. Mỗi thông điệp được lưu trữ cho đến khi nó được thu nhận bởi một ứng dụng nào đó. Một giá trị thời gian chờ, theo giây, được chỉ rõ khi ứng dụng đó đọc một thông điệp từ hàng đợi. Điều này hoạt động giống như một cái khóa và để đảm bảo rằng, cho một khoảng thời gian cụ thể:

  • Thông điệp được nhận sẽ không sẵn sàng cho các ứng dụng khác của hàng đợi.
  • Thông điệp sẽ chỉ tái xuất hiện trong hàng đợi khi thời gian chờ đã hết, và chỉ nếu, nó không bị xóa bởi tiến trình đọc nó.

Werner Vogels CTO của Amazon có một bài thảo luận về các phân tích nguồn gốc cho sự nhất quán cuối cùng trên blog của anh ta (xem Tài nguyên).

Các thông điệp được giữ lại trong một thông điệp trong bốn ngày. SQS sẽ tự động xóa bất cứ thông điệp nào ở trong hàng đợi quá bốn ngày. SQS tuân theo mô hình của "nhất quán cuối cùng", nghĩa là bạn có thể gửi một thông điệp tới hàng đợi, nhưng một ứng dụng sử dụng hàng đợi đó có thể không thấy thông điệp đó trong một khoảng thời gian nào đó. Thông điệp cuối cùng sẽ được gửi đi, nhưng đây là một sự cân nhắc quan trọng nếu các ứng dụng của bạn quan tâm đến trật tự của các thông điệp.

Một thông điệp bao gồm các phần như trong Bảng 1.

Bảng 1. Các phần của một thông điệp
PhầnMô tả
MessageId Một định danh ID duy nhất tham chiếu tới thông điệp.
ReceiptHandle Một trình xử lý duy nhất mà được trả về khi một thông điệp được thu nhận từ hàng đợi. Trình xử lý này là khác nhau với mỗi lần lấy một thông điệp từ hàng đợi. Nó được yêu cầu khi bạn xóa thông điệp.
MD5OfBodyMã MD5 của chuỗi thông điệp không bị mã hóa.
Body Dữ liệu thực sự của thông điệp.

Hàng đợi Queues

Các hàng đợi (Queues) là các thùng chứa các thông điệp. Mỗi thông điệp phải chỉ rõ một hàng đợi mà sẽ chứa nó. Các thông điệp được gửi tới hàng đợi sẽ ở đó cho đến khi bạn thực sự xóa chúng. Trật tự của hàng đợi là vào trước, ra trước, nhưng trật từ này không được đảm bảo. Mỗi hàng đợi đều có một thời gian chờ để nhìn thấy là 30 giây. Bạn có thể thay đổi giá trị này cho toàn bộ hàng đợi, hoặc nó có thể được đặt một cách riêng lẻ cho từng thông điệp. Thời gian chờ để nhìn thấy tối đa cho một hàng đợi hay thông điệp là hai giờ (7200 giây). SQS duy trì quyền xóa hàng đợi một cách tự động nếu không có hoạt động thực sự nào trên hàng đợi trong vòng 30 ngày liên tục.

Cân nhắc thiết kế

SQS hơi khác một chút so với các khung làm việc hàng đợi thông dụng. Có ba thứ bạn cần cân nhắc trước khi thiết kế ứng dụng dựa trên SQS của bạn:

  • SQS không đảm bảo trật tự của các trông điệp trong một hàng đợi.

    Các thông điệp được sắp xếp trong một hàng đợi; chúng không thực sự được lưu trữ theo trật tự mà chúng được thêm vào hàng đợt. SQS sẽ cố để duy trì trật tự trong các thông điệp, nhưng nó không đảm bảo rằng bạn sẽ nhận được các thông điệp theo trật tự chính xác như khi bạn gửi. Nếu trật tự của thông điệp là quan trọng với ứng dụng của bạn, bạn cần phải thêm dữ liệu tuần tự vào mỗi thông điệp.

  • SQS không đảm bảo sự xóa của một thông điệp trong hàng đợi.

    Bạn phải thiết kế ứng dụng của bạn sao cho nó không bị ảnh hưởng nếu cùng một thông điệp được xử lý nhiều hơn một lần. Mỗi thông điệp của bạn được lưu trữ trên nhiều máy chủ khác nhau bởi SQS, để cung cấp tính dư thừa và tính sẵn sàng cao. Nếu một trong các máy chủ này không hoạt động trong khi một thông điệp đang bị xóa, bạn có thể nhận được một bản sao của thông điệp trong khi nhận các thông điệp.

  • SQS không đảm bảo tất cả các thông điệp trong hàng đợi sẽ được trả lại khi được yêu cầu.

    SQS sử dụng việc lấy mẫu thông điệp dựa trên phân bố ngẫu nhiên có trọng số, và nó trả lại thông điệp chỉ từ những tập con được lấy mẫu của các máy chủ khi bạn yêu cầu các thông điệp. Thậm chí, một yêu cầu cụ thể có thể sẽ không trả lại tất cả các thông điệp trong hàng đợi, nếu bạn tiếp tục nhận thông điệp từ hàng đợi nó sẽ kết thúc việc lấy mẫu tất cả các máy chủ và bạn sẽ nhận được tất cả các thông điệp của bạn.

Các phiên bản của API

Có hai phiên bản của SQS: phiên bản gốc (2007-05-01) và một phiên bản 2008-01-01. Mỗi phiên bản của API được tham chiếu đến ngày phát hành. API 2007-05-01 sẽ kết thúc vào ngày 06 tháng 05 năm 2009, sau đó chỉ có phiên bản mới nhất của API mới được hỗ trợ. Người dùng nên:

  • Bắt đầu chuyển dịch các ứng dụng mà họ xây dựng sử dụng phiên bản API cũ càng nhanh càng tốt.
  • Để giảm thiểu bất cứ sự ngắt quãng nào, sử dụng phiên bản mới nhất của API khi tạo các ứng dụng mới với SQS.

Phiên bản 2008-01-01 cập nhật giá cả, nó giảm giá sử dụng SQS cho hầu hết người sử dụng, và bao gồm các tính năng phụ trợ và sự sửa đổi. Tuy nhiên, nó cũng giới thiệu sự thay đổi đáng kể và không tương thích với phiên bản trước. Tất cả các thư viện và công cụ được xây dựng trên phiên bản cần được thay đổi. Một mô tả chi tiết của các thay đổi giữa các phiên bản có trên trang web của SQS (xem Tài nguyên).


Bảng giá

Bảng giá chi tiết sau đây chỉ cho phiên bản 2008-01-01. (Bạn có thể lấy chi tiết về cấu trúc giá cả cho phiên bản cũ hơn ở trang web của SQS (xem Tài nguyên). Giá được dựa trên:

  • Số lượng yêu cầu tới SQS, bao gồm những thao tác sau:
    • CreateQueue
    • ListQueues
    • DeleteQueue
    • SendMessage
    • ReceiveMessage
    • DeleteMessage
    • SetQueueAttributes
    • GetQueueAttributes


    Bảng 2. Giá cho các yêu cầu
    KiểuGiá
    Yêu cầu tới SQS $0.000001 cho một yêu cầu
  • Khối lượng dữ liệu chuyển đến và đi từ SQS. Việc chuyển dữ liệu giữa SQS và các thể hiện EC2 là miễn phí.

    Bảng 3. Giá cho việc luân chuyển dữ liệu
    Kiểu luận chuyểnGiá
    Chuyển tất cả dữ liệu $0.100 cho 1 GB — tất cả dữ liệu chuyển đến

    $0.170 cho 1 GB — 10 TB dữ liệu đầu tiên chuyển đi trong tháng
    $0.130 cho 1 GB — 40 TB dữ liệu chuyển đi tiếp theo trong tháng
    $0.110 cho 1 GB — 100 TB dữ liệu chuyển đi tiếp theo trong tháng
    $0.100 cho 1 GB — dữ liệu chuyển đi vượt quá 150 TB trong tháng

Tham khảo Amazon SQS để biết thông tin về giá cả mới nhật. Bạn cũng có thể sử dụng máy tính Simple Monthly Calculator của Amazon Web Services để tính toán giá thành sử dụng hàng tháng của bạn cho SQS và các dịch vụ khác trên Amazon Web Services (xem Tài nguyên).


Bắt đầu với Amazon Web Services và SQS

Để bắt đầu khám phá SQS, đầu tiên bạn sẽ phải đăng ký một tài khoản trên Amazon Web Services (xem Tài nguyên). Xem Phần 2 của loạt bài này để biết các chỉ dẫn chi tiết về việc đăng ký tài khoản trên Amazon Web Services.

Khi bạn có một tài khoản trên Amazon Web Services, bạn phải bật dịch vụ Amazon SQS cho tài khoản của bạn:

  1. Đăng nhập vào tài khoản Amazon Web Services của bạn.
  2. Tìm đến trang chủ của SQS.
  3. Nhấn Sign Up For Amazon SQS nằm ở bên phải.
  4. Cung cấp các thông tin cần thiết và hoàn tất quá trình đăng ký.

Tất cả các giao tiếp với bất kỳ dịch vụ nào của Amazon Web Services đều thông qua giao tiếp SOAP hoặc giao tiếp truy vấn. Trong bài này, bạn sử dụng giao tiếp truy vấn bằng thư viện của bên thứ ba.

Bạn cần nhận được các khóa truy cập, cái mà bạn có thể truy cập từ trang thông tin tài khoản của bạn bằng cách lựa chọn View Access Key Identifiers. Bạn bây giờ đã sẵn sàng để sử dụng dịch vụ của Amazon Web Services và đã bật dịch vụ SQS cho tài khoản của bạn.


Tương tác với SQS

Trong ví dụ này, bạn sử dụng một thư viện Python mã mở tên là boto để làm quen với SQS bằng cách thực thi đoạn mã nhỏ trong một cửa sổ lệnh Python.

Cài đặt boto và thiết lập môi trường

Tải boto Phiên bản mới nhất, khi viết bài này, là 1.4c. Giải nén vào một thư mục tùy ý. Chuyển tới thư mục này và thi hành setup.py để cài đặt boto vào môi trường Python cục bộ của bạn, như trong Ví dụ 1.

Ví dụ 1. Cài đặt boto
$ cd directory_where_you_unzipped_boto

$ python setup.py install

Thiết lập một số biến môi trường để trỏ đến các khóa truy cập dịch vụ của Amazon Web Services. Các khóa truy cập có sẵn trên trang thông tin tài khoản.

Ví dụ 2. Thiết lập biến môi trường
# Export variables with your AWS access keys
$ export AWS_ACCESS_KEY_ID=Your_AWS_Access_Key_ID 
$ export AWS_SECRET_ACCESS_KEY=Your_AWS_Secret_Access_Key

Kiểm tra để đảm bảo rằng mọi thứ được thiết lập đúng đắn bằng cách khởi động một cửa sổ lệnh Python và nhập thư viện boto vào, như trong Ví dụ 3.

Ví dụ 3. Kiểm tra thiết lập
$ python
Python 2.4.5 (#1, Apr 12 2008, 02:18:19) 
[GCC 4.0.1 (Apple Computer, Inc. build 5367)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import boto
>>>

Khám phá SQS với boto

Sử dụng lớp SQSConnection để cung cấp giao diện chính cho sự tương tác với SQS. Môi trường để sử dụng boto là cửa sổ lệnh của Python. Ví dụ này gọi các phương thức khác nhau trên đối tượng SQSConnection và kiểm tra các phản hồi trả về bởi SQS, cái mà sẽ giúp bạn làm quen với API trong khi bạn khám phá các khái niệm nằm sau SQS.

Bước đầu tiên là tạo một đối tượng kết nối tới SQS sử dụng các khóa truy cập dịch vụ của Amazon Web Services mà bạn đã nhập vào môi trường làm việc lúc trước. Thư viện boto luôn kiểm tra môi trường trước tiên để xem xem nếu những biến này đã được thiết lập. Nếu chúng đã được thiết lập, boto sử dụng chúng một cách tự động khi nó tạo ra kết nối.

Ví dụ 4. Tạo một kết nối tới SQS
>>> import boto
>>> sqs_conn = boto.connect_sqs()
>>>

Cho phần còn lại của bài này bạn có thể sử dụng đối tượng sqs_conn, được tạo ở trên, để tương tác với SQS. Bạn có thể tạo một hàng đợi bằng cách chỉ ra một tên cho nó, cùng với một giá trị thời gian chờ để nhìn thấy. Nếu bạn bỏ qua giá trị chờ, boto sẽ tạo một hàng đợi với giá trị thời gian chờ mặc định là 30 giây.

Ví dụ 5. Tạo một hàng đợi
>>> q1 = sqs_conn.create_queue('devworks-sqs-1')
>>> 
>>> q1.get_timeout()
30
>>> q2 = sqs_conn.create_queue('devworks-sqs-2', 60)
>>> 
>>> q2.get_timeout()
60
>>>

Lấy một danh sách các hàng đợi của bạn, nó sẽ trả lại một đối tượng resultset, đó là một danh sách Python, như trong Ví dụ 6. Bạn có thể lặp qua danh sách này và truy cập tất cả các thông tin cho từng hàng đợi.

Ví dụ 6. Liệt kê tất cả các hàng đợi
>>> all_queues = sqs_conn.get_all_queues()
>>> 
>>> len(all_queues)
2
>>> 
>>> for q in all_queues:
...     print q.id
...     print q.count()
...     print q.get_timeout()
...     print q.url
... 
/devworks-sqs-1
0
30
http://queue.amazonaws.com/devworks-sqs-1

/devworks-sqs-2
0
60
http://queue.amazonaws.com/devworks-sqs-2

Bạn phải xóa tất cả các thông điệp trong một hàng đợi trước khi xóa hàng đợi. Phương thức clear() của boto có thể xóa tất cả các thông điệp có trong một hàng đợi.

Ví dụ 7. Làm rỗng và xóa các hàng đợi
>>> q2.clear()
0
>>> sqs_conn.delete_queue(q2)
True
>>>

Bạn có thể gửi các thông điệp văn bản với kích thước tối đa là 8 KB tới một hàng đợi. Tạo một thông điệp mới bằng cách sử dụng lớp Message của boto, như trong Ví dụ 8.

Ví dụ 8. Gửi một thông điệp
>>> from boto.sqs.message import Message
>>> 
>>> m1 = Message()
>>> 
>>> m1.set_body('Hi there devworks!')
>>> 
>>> status = q1.write(m1)
>>> 
>>> print status
True
>>>

Sự thu nhận các thông điệp cho một hàng đợi trả lại một đối tượng result-set là một danh sách Python chứa các đối tượng thông điệp. Mỗi đối tượng thông điệp có một định danh ID duy nhất và một trình quản lý gắn với nó. Khi bạn đọc một thông điệp từ một hàng đợi, thông điệp đó tự động ẩn đi đối với các ứng dụng sử dụng hàng đợi khác cho đến khi thời gian chờ để nhìn thấy hết hạn. Sau khi hết hạn, thông điệp lại xuất hiện trong hàng đợi, cho phép các ứng dụng khác nhận và xử lý nó. Tuy nhiên, nếu thông điệp bí xóa khỏi hàng đợi trước khi thời gian chờ hết hạn, nó sẽ biến mất vĩnh viễn và sẽ không xuất hiện trở lại trong hàng đợi.

Ví dụ 9. Lấy một thông điệp
>>> msgs = q1.get_messages()
>>> 
>>> len(msgs)
1
>>>
>>> for msg in msgs:
...     print "Message ID: ",msg.id
...     print "Message Handle: ",msg.receipt_handle
...     print "Queue ID: ", msg.queue.id
...     print "Message Body: ", msg.get_body()
... 
Message ID:  9a930aaf-87de-48ad-894d-b22dd0b1cd1b

Message Handle:  Prl0vft3nRjgDDT33svtLnzyPQGWFpRusXdn2v3Lwq+TDtD3hk3aBKbSH1mGc4hzO/VZO
IC0RFyAd7MhbJKPGHn3x35CTz9dAQeNoKYAHiwERXc/xrYXBLGngyuJI+kGmbjvIKqA/wpfQpqzPk2bVA==

Queue ID:  /devworks-sqs-1

Message Body:  Hi there devworks!
>>>

Bạn có thể lấy nhiều hơn một thông điệp bằng cách chỉ rõ số lượng thông điệp bạn muốn. Giá trị mặc địch là một thông điệp. Hãy thêm một thông điệp khác vào hàng đợi và lấy tất cả các thông điệp, như trong Ví dụ 10. Hãy nhớ rằng nó có thể mất cả phút hoặc hơn để một thông điệp mới được thêm vào xuất hiện trong hàng đợi.

Ví dụ 10. Lấy nhiều thông điệp
>>> m2 = Message()
>>> 
>>> m2.set_body('Still there?')
>>> 
>>> status = q1.write(m2)
>>> 
>>> print status
True
>>>
>>> msgs = q1.get_messages(10)
>>> 
>>> len(msgs)
2
>>>
>>> for msg in msgs:
...     print "Message ID: ",msg.id
...     print "Message Handle: ",msg.receipt_handle
...     print "Queue ID: ", msg.queue.id
...     print "Message Body: ", msg.get_body()
...     print "*"*80
... 
Message ID:  9a930aaf-87de-48ad-894d-b22dd0b1cd1b

Message Handle:  Prl0vft3nRjgDDT33svtLnzyPQGWFpRusXdn2v3Lwq+TDtD3hk3aBKbSH1mGc4hzO/VZOIC0R
FyAd7MhbJKPGHn3x35CTz9dAQeNoKYAHiwERXc/xrYXBLGngyuJI+kGmbjvIKqA/wpfQpqzPk2bVA==

Queue ID:  /devworks-sqs-1

Message Body:  Hi there devworks!


Message ID:  ce1632b3-0a6e-4ee2-a5b0-b2e9821d150f

Message Handle:  Prl0vft3nRiRunVNVvjOQEc7Tm+uSBQpW4bZcpFMbzWTDtD3hk3aBKbSH1mGc4hzO/VZOIC0R
FxbhtlykUxvNbRQNWJqrMXrxj5m6GwhA7iX0Nu9mqjo+9/hnda8Ou0df+LQ3dOMfXSybzbhed128w==

Queue ID:  /devworks-sqs-1

Message Body:  Still there?
>>>

Các thông điệp có thể bị xóa bỏ khỏi một hàng đợi bằng cách yêu cầu delete_message(). Nhớ rằng, bạn phải xóa tất cả các thông điệp trong hàng đợi trước khi xóa hàng đợi.

Ví dụ 11. Xóa một thông điệp
>>> msgs = q1.get_messages()
>>> 
>>> len(msgs)
1
>>> print msgs[0].get_body()
Hi there devworks!
>>> 
>>> q1.delete_message(msgs[0])
True
>>>

Kết luận

Bài này đã giới thiệu với bạn dịch vụ SQS của Amazon. Bạn đã tìm hiểu một số khái niệm cơ bản và đã khám phá một số hàm được cung cấp bởi SQS. Bạn nên đọc hướng dẫn ở Amazon SQS Developer Guide để biết thêm thông tin (xem Tài nguyên).

Phần 5 của loạt bài " Điện toán đám mây với Amazon Web Services" sẽ xem xét Amazon SimpleDB cho việc xử lý tập dữ liệu trong đám mây.

Tài nguyên

Học tập

Lấy sản phẩm và công nghệ

Thảo luận

Bình luận

developerWorks: Đăng nhập

Các trường được đánh dấu hoa thị là bắt buộc (*).


Bạn cần một ID của IBM?
Bạn quên định danh?


Bạn quên mật khẩu?
Đổi mật khẩu

Bằng việc nhấn Gửi, bạn đã đồng ý với các điều khoản sử dụng developerWorks Điều khoản sử dụng.

 


Ở lần bạn đăng nhập đầu tiên vào trang developerWorks, một hồ sơ cá nhân của bạn được tạo ra. Thông tin trong bản hồ sơ này (tên bạn, nước/vùng lãnh thổ, và tên cơ quan) sẽ được trưng ra cho mọi người và sẽ đi cùng các nội dung mà bạn đăng, trừ khi bạn chọn việc ẩn tên cơ quan của bạn. Bạn có thể cập nhật tài khoản trên trang IBM bất cứ khi nào.

Thông tin gửi đi được đảm bảo an toàn.

Chọn tên hiển thị của bạn



Lần đầu tiên bạn đăng nhập vào trang developerWorks, một bản trích ngang được tạo ra cho bạn, bạn cần phải chọn một tên để hiển thị. Tên hiển thị của bạn sẽ đi kèm theo các nội dung mà bạn đăng tải trên developerWorks.

Tên hiển thị cần có từ 3 đến 30 ký tự. Tên xuất hiện của bạn phải là duy nhất trên trang Cộng đồng developerWorks và vì lí do an ninh nó không phải là địa chỉ email của bạn.

Các trường được đánh dấu hoa thị là bắt buộc (*).

(Tên hiển thị cần có từ 3 đến 30 ký tự)

Bằng việc nhấn Gửi, bạn đã đồng ý với các điều khoản sử dụng developerWorks Điều khoản sử dụng.

 


Thông tin gửi đi được đảm bảo an toàn.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=70
Zone=SOA và dịch vụ Web, Nguồn mở
ArticleID=390964
ArticleTitle=Điện toán đám mây với Web Amazon Services, Phần 4 : Truyền tin tin cậy với SQS
publish-date=05202009