由于OpenEdx安装复杂,一个简化安装的方法是使用云或者虚拟化的镜像功能,但镜像在重新部署后会遇到IP地址改变的问题,这个过程会导致OpenEdx的RabbitMQ(消息服务)丢失配置,并出现如下的错误信息,当前使用的OpenEdx为ginkgo.2版本。
#/edx/var/log/lms/edx.log
May 13 22:17:49 ginkgoedxdev [service_variant=lms][celery.worker.consumer][env:sandbox] ERROR [ginkgoedxdev 2216] [consumer.py:364] – consumer: Cannot connect to amqp://ce
lery:**@127.0.0.1:5672//: [Errno 104] Connection reset by peer.
Trying again in 26.00 seconds…
May 13 22:18:13 ginkgoedxdev [service_variant=lms][celery.worker.consumer][env:sandbox] ERROR [ginkgoedxdev 2214] [consumer.py:364] – consumer: Cannot connect to amqp://ce
lery:**@127.0.0.1:5672//: [Errno 104] Connection reset by peer.
该问题的也会导致课程的选择、填空等问题当提交时返回报错信息。因此猜想对选择、填空问题的判题涉及到了消息队列机制。报错信息如下:
2019-05-13 09:06:51,737 WARNING 2530 [courseware.module_render] module_render.py:1002 – Module encountered an error while processing AJAX call
Traceback (most recent call last):
File “/edx/app/edxapp/edx-platform/lms/djangoapps/courseware/module_render.py”, line 982, in _invoke_xblock_handler
resp = instance.handle(handler, req, suffix)
File “/edx/app/edxapp/venvs/edxapp/local/lib/python2.7/site-packages/xblock/mixins.py”, line 89, in handle
return self.runtime.handle(self, handler_name, request, suffix)
File “/edx/app/edxapp/edx-platform/common/lib/xmodule/xmodule/x_module.py”, line 1339, in handle
return super(MetricsMixin, self).handle(block, handler_name, request, suffix=suffix)
File “/edx/app/edxapp/venvs/edxapp/local/lib/python2.7/site-packages/xblock/runtime.py”, line 1029, in handle
results = handler(request, suffix)
File “/edx/app/edxapp/edx-platform/common/lib/xmodule/xmodule/x_module.py”, line 883, in xmodule_handler
response_data = self.handle_ajax(suffix, request_post)
File “/edx/app/edxapp/edx-platform/common/lib/xmodule/xmodule/capa_module.py”, line 93, in handle_ajax
result = handlers[dispatch](data)
File “/edx/app/edxapp/edx-platform/common/lib/xmodule/xmodule/capa_base.py”, line 1255, in submit_problem
published_grade = self.publish_grade()
File “/edx/app/edxapp/edx-platform/common/lib/xmodule/xmodule/capa_base.py”, line 1135, in publish_grade
‘only_if_higher’: only_if_higher,
File “/edx/app/edxapp/edx-platform/lms/djangoapps/courseware/module_render.py”, line 474, in publish
only_if_higher=event.get(‘only_if_higher’),
File “/edx/app/edxapp/venvs/edxapp/local/lib/python2.7/site-packages/django/dispatch/dispatcher.py”, line 189, in send
response = receiver(signal=self, sender=sender, **named)
File “/edx/app/edxapp/edx-platform/lms/djangoapps/grades/signals/handlers.py”, line 176, in score_published_handler
score_db_table=ScoreDatabaseTableEnum.courseware_student_module,
File “/edx/app/edxapp/venvs/edxapp/local/lib/python2.7/site-packages/django/dispatch/dispatcher.py”, line 189, in send
response = receiver(signal=self, sender=sender, **named)
File “/edx/app/edxapp/edx-platform/lms/djangoapps/grades/signals/handlers.py”, line 206, in problem_raw_score_changed_handler
score_db_table=kwargs[‘score_db_table’],
File “/edx/app/edxapp/venvs/edxapp/local/lib/python2.7/site-packages/django/dispatch/dispatcher.py”, line 189, in send
response = receiver(signal=self, sender=sender, **named)
File “/edx/app/edxapp/edx-platform/lms/djangoapps/grades/signals/handlers.py”, line 230, in enqueue_subsection_update
countdown=RECALCULATE_GRADE_DELAY,
File “/edx/app/edxapp/venvs/edxapp/local/lib/python2.7/site-packages/celery_utils/logged_task.py”, line 26, in apply_async
result = super(LoggedTask, self).apply_async(args=args, kwargs=kwargs, **options)
File “/edx/app/edxapp/venvs/edxapp/local/lib/python2.7/site-packages/celery/app/task.py”, line 559, in apply_async
**dict(self._get_exec_options(), **options)
File “/edx/app/edxapp/venvs/edxapp/local/lib/python2.7/site-packages/celery/app/base.py”, line 353, in send_task
reply_to=reply_to or self.oid, **options
File “/edx/app/edxapp/venvs/edxapp/local/lib/python2.7/site-packages/celery/app/amqp.py”, line 305, in publish_task
**kwargs
File “/edx/app/edxapp/venvs/edxapp/local/lib/python2.7/site-packages/kombu/messaging.py”, line 172, in publish
routing_key, mandatory, immediate, exchange, declare)
File “/edx/app/edxapp/venvs/edxapp/local/lib/python2.7/site-packages/kombu/connection.py”, line 470, in _ensured
interval_max)
File “/edx/app/edxapp/venvs/edxapp/local/lib/python2.7/site-packages/kombu/connection.py”, line 382, in ensure_connection
interval_start, interval_step, interval_max, callback)
File “/edx/app/edxapp/venvs/edxapp/local/lib/python2.7/site-packages/kombu/utils/__init__.py”, line 246, in retry_over_time
return fun(*args, **kwargs)
File “/edx/app/edxapp/venvs/edxapp/local/lib/python2.7/site-packages/kombu/connection.py”, line 250, in connect
return self.connection
File “/edx/app/edxapp/venvs/edxapp/local/lib/python2.7/site-packages/kombu/connection.py”, line 756, in connection
self._connection = self._establish_connection()
File “/edx/app/edxapp/venvs/edxapp/local/lib/python2.7/site-packages/kombu/connection.py”, line 711, in _establish_connection
conn = self.transport.establish_connection()
File “/edx/app/edxapp/venvs/edxapp/local/lib/python2.7/site-packages/kombu/transport/pyamqp.py”, line 116, in establish_connection
conn = self.Connection(**opts)
File “/edx/app/edxapp/venvs/edxapp/local/lib/python2.7/site-packages/amqp/connection.py”, line 180, in __init__
(10, 30), # tune
File “/edx/app/edxapp/venvs/edxapp/local/lib/python2.7/site-packages/amqp/abstract_channel.py”, line 67, in wait
self.channel_id, allowed_methods, timeout)
File “/edx/app/edxapp/venvs/edxapp/local/lib/python2.7/site-packages/amqp/connection.py”, line 241, in _wait_method
channel, method_sig, args, content = read_timeout(timeout)
File “/edx/app/edxapp/venvs/edxapp/local/lib/python2.7/site-packages/amqp/connection.py”, line 330, in read_timeout
return self.method_reader.read_method()
File “/edx/app/edxapp/venvs/edxapp/local/lib/python2.7/site-packages/amqp/method_framing.py”, line 189, in read_method
raise m
ProcessingError: \u5f88\u62b1\u6b49\uff0c\u5728\u5904\u7406\u4f60\u7684\u8bf7\u6c42\u65f6\u51fa\u73b0\u9519\u8bef\u3002\u8bf7\u91cd\u65b0\u52a0\u8f7d\u4f60\u7684\u9875\u9762\u5e76\u518d\u6b21\u5c1d\u8bd5\u64cd\u4f5c\u3002
错误堆栈信息太多,难以定位。后查询发现,可能是rabbitmq丢失配置导致的。进入超级用户,输入如下命令:
root@ginkgoedxdev:/edx/var/log/supervisor# rabbitmqctl list_users
Listing users …
celery [administrator]
admin [administrator]
edx [administrator]
guest [administrator]
如果没有celery、admin和edx这三个用户,则说明遇到了rabbitmq丢失用户信息的情况,解决方法就是手动添加进入。OpenEdx的Ginkgo.2版本已经给rabbitmq生成了随机的密码,不再像老版本使用固定的密码了。查找下ansible的安装脚本内容(属于configuration仓库):
#blob/open-release/ginkgo.2/playbooks/roles/rabbitmq/defaults/main.yml
RABBIT_USERS:
– name: ‘admin’
password: “{{ RABBIT_ADMIN_PASSWORD }}”
– name: ‘edx’
password: ‘edx’
– name: ‘celery’
password: ‘celery’
RABBITMQ_VHOSTS:
– ‘/’
在上述文件中看到了每个用户的用户名和密码,但其实ginkgo.2已经用的不是默认的密码,在OpenEdx初始安装的过程中,有个“generate-passwords.sh”文件,会产生密钥相关的文件和密钥模板文件“passwords-template.yml”。内容如下:
#my-passwords.yml
….
RABBIT_ADMIN_PASSWORD: ‘GyEbqKia1ZlO8CRce7GTVPGmgKQ2eQ0wjlP’
XQUEUE_RABBITMQ_PASS: ‘YLl9QQKjd2y9ffXFJDjooeUMPvwmf0jKUUJ’
EDXAPP_CELERY_PASSWORD: ‘SFRtLbvHN3xzgeR79aJUhTGWneZ8mJi0UNc’
…
RABBIT_USERS:
– name: ‘admin’
password: “{{ RABBIT_ADMIN_PASSWORD }}”
– name: ‘edx’
password: “{{ XQUEUE_RABBITMQ_PASS }}”
– name: ‘celery’
password: “{{ EDXAPP_CELERY_PASSWORD }}”
在rabbitmq上添加用户并设置权限即可。命令如下:
#rabbitmqctl add_user admin GyEbqKia1ZlO8CRce7GTVPGmgKQ2eQ0wjlP #添加用户
#rabbitmqctl add_user edx YLl9QQKjd2y9ffXFJDjooeUMPvwmf0jKUUJ
#rabbitmqctl add_user celery SFRtLbvHN3xzgeR79aJUhTGWneZ8mJi0UNc
#rabbitmqctl set_user_tags admin administrator #设置用户类别
#rabbitmqctl set_user_tags edx administrator
#rabbitmqctl set_user_tags celery administrator
#rabbitmqctl set_permissions -p / admin “.*” “.*” “.*” #设置权限
#rabbitmqctl set_permissions -p / edx”.*” “.*” “.*”
#rabbitmqctl set_permissions -p / celery”.*” “.*” “.*”
#service rabbitmq-server restart #重启rabbitmq
上述配置完成后,相应的报错就消失了。OpenEdx选择填空题功能模块是在“common/lib/xmodule/xmodule/capa_module.py”模块内实现的,具体调用的流程还不清楚,但过程涉及到了消息队列,因此rabbitmq配置关系到选择填空模块是否正常运行。