本文介绍如何使用Python SDK中的sample代码,完成创建主题、创建订阅、启动HTTP Endpoint、发布消息、查看HTTP Endpoint接收消息和删除主题操作。
步骤一:准备工作
- 下载最新版Python SDK,解压后进入mns_python_sdk子目录。
- 打开sample.cfg文件,配置以下内容:
- AccessKey ID、AccessKey Secret
- 访问阿里云API的密钥对。
- 如果使用阿里云账号访问,请登录阿里云AccessKey管理页面创建、查看。
- 如果使用RAM用户访问,请登录阿里云访问控制控制台查看。
- Endpoint
- 访问消息服务MNS的接入地址,登录MNS控制台,单击右上角获取Endpoint查看。
- 不同地域的接入地址不同。
- SecurityToken
- 阿里云访问控制服务提供的短期访问权限凭证,直接使用阿里云账号或者RAM用户访问不需要配置该项。更多信息,请参见什么是STS。
- AccessKey ID、AccessKey Secret
- 进入sample目录,后续使用的脚本都在这里。
步骤二:创建主题
运行createtopic.py创建主题。默认创建的主题名称是MySampleTopic,也可以通过参数指定主题名称。更多信息,请参见Topic。
- 运行以下命令:
python createtopic.py MyTopic1
返回结果如下:
Create Topic Succeed! TopicName:MyTopic1
- 核心代码:
endpoint、accid、acckey和token从步骤一的配置文件中读取。
#init my_account, my_topic my_account = Account(endpoint, accid, acckey, token) topic_name = sys.argv[1] if len(sys.argv) > 1 else "MySampleTopic" my_topic = my_account.get_topic(topic_name) #you can get more information of TopicMeta from mns/topic.py topic_meta = TopicMeta() try: topic_url = my_topic.create(topic_meta) print "Create Topic Succeed! TopicName:%s\n" % topic_name except MNSExceptionBase, e: if e.type == "TopicAlreadyExist": print "Topic already exist, please delete it before creating or use it directly." sys.exit(0) print "Create Topic Fail! Exception:%s\n" % e
步骤三:启动HTTP Endpoint
运行simple_http_notify_endpoint.py来启动HTTP Endpoint。脚本启动后,输出该脚本的监听地址,这个地址后续作为创建订阅的Endpoint参数,用于接收消息服务MNS推送消息的请求。
- 服务器功能:
- 对消息服务MNS推送消息请求做签名验证。如果错误,返回MNS 403。
说明 示例中HTTP Endpoint的针对Authorization的校验不能完全规避掉恶意伪造的MNS请求,需要从业务层面上设计从发送端到HTTP Endpoint的安全校验机制。
- 解析推送请求的Body。如果解析正确,打印的日志包含请求的Body;如果解析错误,返回MNS 400。
- 如果验权和解析Body均正常,返回MNS 201。
- 对消息服务MNS推送消息请求做签名验证。如果错误,返回MNS 403。
- 运行以下命令:
python simple_http_notify_endpoint.py 10.101.161.**
返回结果如下:
Start Endpoint! Address: http://10.101.161.**:8080
由于simple_http_notify_endpoint.py的代码较多,请直接查看SDK中的源码。
步骤四:创建订阅
运行subscribe.py创建订阅。第一个参数指定接收消息的HTTP Endpoint,使用步骤三中脚本输出的Address;第二个参数指定订阅的主题名称,如果步骤二中指定了主题名称,这里同样指定主题名称;第三个参数指定订阅的名称,默认是MySampleTopic-Sub。更多信息,请参见Subscription。
- 运行以下命令:
python subscribe.py http://10.101.161.**:8080 MyTopic1 MyTopic1-Sub1
返回结果如下:
Create Subscription Succeed! TopicName:MyTopic1 SubName:MyTopic1-Sub1 Endpoint:http://10.101.161.**:8080
- 核心代码:
endpoint、accid、acckey和token从步骤一的配置文件中读取。
sub_endpoint = sys.argv[1] #init my_account, my_topic, my_sub my_account = Account(endpoint, accid, acckey, token) topic_name = sys.argv[2] if len(sys.argv) > 2 else "MySampleTopic" my_topic = my_account.get_topic(topic_name) sub_name = sys.argv[3] if len(sys.argv) > 3 else "MySampleTopic-Sub" my_sub = my_topic.get_subscription(sub_name) #you can get more information of SubscriptionMeta from mns/subscription.py sub_meta = SubscriptionMeta(sub_endpoint) try: topic_url = my_sub.subscribe(sub_meta) print "Create Subscription Succeed! TopicName:%s SubName:%s Endpoint:%s\n" % (topic_name, sub_name, sub_endpoint) except MNSExceptionBase, e: if e.type == "TopicNotExist": print "Topic not exist, please create topic." sys.exit(0) elif e.type == "SubscriptionAlreadyExist": print "Subscription already exist, please unsubscribe or use it directly." sys.exit(0) print "Create Subscription Fail! Exception:%s\n" % e
步骤五:发布消息
运行publishmessage.py发布多条消息到主题中。如果步骤二中指定了主题名称,这里同样通过第一个参数指定主题名称。更多信息,请参见TopicMessage。
- 运行以下命令:
python publishmessage.py MyTopic1
返回结果如下:
==========Publish Message To Topic========== TopicName:MyTopic1 MessageCount:3 Publish Message Succeed. MessageBody:I am test message 0. MessageID:F6EA56633844DBFC-1-154BDFB8059-20000**** Publish Message Succeed. MessageBody:I am test message 1. MessageID:F6EA56633844DBFC-1-154BDFB805F-20000**** Publish Message Succeed. MessageBody:I am test message 2. MessageID:F6EA56633844DBFC-1-154BDFB8062-20000****
- 核心代码:
endpoint、accid、acckey和token从步骤一的配置文件中读取。
#init my_account, my_topic my_account = Account(endpoint, accid, acckey, token) topic_name = sys.argv[1] if len(sys.argv) > 1 else "MySampleTopic" my_topic = my_account.get_topic(topic_name) #publish some messages msg_count = 3 print "%sPublish Message To Topic%s\nTopicName:%s\nMessageCount:%s\n" % (10*"=", 10*"=", topic_name, msg_count) for i in range(msg_count): try: msg_body = "I am test message %s." % i msg = TopicMessage(msg_body) re_msg = my_topic.publish_message(msg) print "Publish Message Succeed. MessageBody:%s MessageID:%s" % (msg_body, re_msg.message_id) except MNSExceptionBase,e: if e.type == "TopicNotExist": print "Topic not exist, please create it." sys.exit(1) print "Publish Message Fail. Exception:%s" % e
步骤六:查看HTTP Endpoint接收消息
在步骤五中,多条消息被发布到了主题中,消息服务MNS会将发布的消息推送给步骤三启动的HTTP Endpoint。HTTP Endpoint在接收到消息推送请求后,会记录两种日志:access_log和endpoint_log。
- access_log
- 启动HTTP Endpoint的地方会打印access_log,显示推送消息请求的基本信息,从左往右依次是:
RequestTime RequestVersion ReturnCode URI HTTPVersion RequestLength Host Agent MNSRequestID MNSVersion
。 - 除打印到屏幕上,access_log会写到日志文件中,文件名格式是access_log.$port,本文对应的日志文件是access_log.8080。
- 运行以下命令查看步骤五发布消息对应的推送请求access_log:
python simple_http_notify_endpoint.py
返回结果如下:
Start Endpoint! Address: http://10.101.161.**:8080 [17/May/2016 17:10:56]"POST" "201" "/notifications" "HTTP/1.1" "495" "10.101.161.**:8080" "Aliyun Notification Service Agent" "573AE020B2B71CFC6801A6EF" "2015-06-06" [17/May/2016 17:10:56]"POST" "201" "/notifications" "HTTP/1.1" "495" "10.101.161.**:8080" "Aliyun Notification Service Agent" "573AE020B2B71CFC6801A712" "2015-06-06" [17/May/2016 17:10:56]"POST" "201" "/notifications" "HTTP/1.1" "495" "10.101.161.**:8080" "Aliyun Notification Service Agent" "573AE020B2B71CFC6801A704" "2015-06-06"
- 启动HTTP Endpoint的地方会打印access_log,显示推送消息请求的基本信息,从左往右依次是:
- endpoint_log
- 记录每个请求的详细信息,包含完整的Header、Body以及解析后消息各属性的信息。
- 日志的文件名格式是endpoint_log.$port,本文对应的日志文件是endpoint_log.8080。
- 运行以下命令查看步骤五发布消息对应的推送请求的endpoint_log:
cat endpoint_log.8080
返回结果如下:
... [2016-05-17 17:10:56] [root] [INFO] [simple_http_notify_endpoint.py:47] [1096657216] Notify Message Succeed! MessageMD5 : 075C3D4AEB2D2F2D6A4C17C9D6DBBEBB TopicOwner : 126912835662**** PublishTime : 1463476256857 Subscriber : 126912835662**** MessageTag : SubscriptionName : MyTopic1-Sub1 MessageId : F6EA56633844DBFC-1-154BDFB8059-20000**** Message : I am test message 0. TopicName : MyTopic1 [2016-05-17 17:10:56] [root] [INFO] [simple_http_notify_endpoint.py:47] [1123260736] Notify Message Succeed! MessageMD5 : 3BCFB142A3CC597F5D409BFE9DB1B885 TopicOwner : 126912835662**** PublishTime : 1463476256866 Subscriber : 126912835662**** MessageTag : SubscriptionName : MyTopic1-Sub1 MessageId : F6EA56633844DBFC-1-154BDFB8062-20000**** Message : I am test message 2. TopicName : MyTopic1 [2016-05-17 17:10:56] [root] [INFO] [simple_http_notify_endpoint.py:47] [1112770880] Notify Message Succeed! MessageMD5 : 8356BC7FFBD22CC971BE7FF7427202B6 TopicOwner : 126912835662**** PublishTime : 1463476256863 Subscriber : 126912835662**** MessageTag : SubscriptionName : MyTopic1-Sub1 MessageId : F6EA56633844DBFC-1-154BDFB805F-20000**** Message : I am test message 1. TopicName : MyTopic1
步骤七:删除主题
运行deletetopic.py删除主题。如果步骤二中指定了主题名称,这里同样通过第一个参数指定主题名称。
- 运行以下命令:
python deletetopic.py MyTopic1
返回结果如下:
Delete Topic Succeed! TopicName:MyTopic1
- 核心代码:
#init my_account, my_topic my_account = Account(endpoint, accid, acckey, token) topic_name = sys.argv[1] if len(sys.argv) > 1 else "MySampleTopic" my_topic = my_account.get_topic(topic_name) try: my_topic.delete() print "Delete Topic Succeed! TopicName:%s\n" % topic_name except MNSExceptionBase, e: print "Delete Topic Fail! Exception:%s\n" % e