docker build -t seasonzhang/meeting_booking:1.5.13 .
docker push seasonzhang/meeting_booking:1.5.13
设置环境变量和默认值
"""
Django settings for classroom_management project.
Generated by 'django-admin startproject' using Django 3.2.7.
For more information on this file, see
https://docs.djangoproject.com/en/3.2/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/3.2/ref/settings/
"""
from pathlib import Path
import os
from django.utils.translation import gettext_lazy as _
# debug模式
DJANGO_DEBUG = os.environ.get('DJANGO_DEBUG', True)
# 设定redis是否使用
REDIS_FALSE_TRUE = os.environ.get('REDIS_FALSE_TRUE', False)
REDIS_LOCATION = os.environ.get('REDIS_LOCATION',"redis://default:redis654321@10.41.241.169:30394")
CELERY_FALSE_TRUE = os.environ.get('CELERY_FALSE_TRUE', False)
# 设定数据库是否使用MYSQL
MYSQL_OR_NOT = os.environ.get('MYSQL_OR_NOT', False)
MYSQL_IP = os.environ.get('MYSQL_IP', '10.41.241.169')
MYSQL_PORT = os.environ.get('MYSQL_PORT', '30031')
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-by14)kf_gs_minl3x(47v1!7fk39!i-q@p=nd)!pl-=eamtde^'
# SECURITY WARNING: don't run with debug turned on in production!
# SECURITY WARNING: don't run with debug turned on in production!
if DJANGO_DEBUG == True or DJANGO_DEBUG == 'True':
DEBUG = True
elif DJANGO_DEBUG == False or DJANGO_DEBUG == 'False':
DEBUG = False
# DEBUG = True
# DEBUG = False
ALLOWED_HOSTS = ['*']
# Application definition
INSTALLED_APPS = [
'simpleui',
'myclassroom',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'django_celery_beat',
]
if REDIS_FALSE_TRUE:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',### 多语言中间件
'django.middleware.cache.UpdateCacheMiddleware',#redis中间件
'django.middleware.common.CommonMiddleware',
'django.middleware.cache.FetchFromCacheMiddleware',#redis中间件
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
else:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',### 多语言中间件
#'django.middleware.cache.UpdateCacheMiddleware',#redis中间件
'django.middleware.common.CommonMiddleware',
#'django.middleware.cache.FetchFromCacheMiddleware',#redis中间件
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'classroom_management.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'classroom_management.wsgi.application'
# Database
# https://docs.djangoproject.com/en/3.2/ref/settings/#databases
if MYSQL_OR_NOT:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', # 数据库引擎
'NAME': 'season', # 数据库名,先前创建的
'USER': 'root', # 用户名,可以自己创建用户
'PASSWORD': '123456', # 密码
'HOST': MYSQL_IP, # mysql服务所在的主机ip
'PORT': MYSQL_PORT, # mysql服务端口
}
}
else:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
#'NAME': BASE_DIR / 'db.sqlite3',
'NAME': Path(__file__).resolve().parent /'SQL' /'db.sqlite3',
}
}
# Password validation
# https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/3.2/topics/i18n/
# 修改中文,Django内部设置zh_Hans方法指向中文
LANGUAGE_CODE = 'zh-hans'
# LANGUAGE_CODE = 'en-us'
LANGUAGES = [
('zh-hans', _('Chinese')),
('en', _('English')),
]
# 修改中国时区
TIME_ZONE = 'Asia/Shanghai'
LANGUAGE_CODE = 'zh-hans'
USE_I18N = True
USE_L10N = True
USE_TZ = True
#USE_TZ = False
LOCALE_PATHS = (
os.path.join(BASE_DIR, 'locale'),
)
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.2/howto/static-files/
# 通过url直接访问我在项目中的静态文件
STATIC_URL = '/static/'
# 部署静态文件时(pyhtonmanage.pycollectstatic)所有的静态文静聚合的目录
STATIC_ROOT = os.path.join(BASE_DIR, "/static/")
# STATICFILES_DIRS告诉django,首先到STATICFILES_DIRS里面寻找静态文件,其次再到各个app的static文件夹里面找
STATICFILES_DIRS = (
os.path.join(BASE_DIR, "static"),
)
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
# Default primary key field type
# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
LOGIN_URL = '/user_login/'
DATE_FORMAT = 'Y-m-d'
# Django Rest Framework框架设置信息
# 分页设置
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
# 每页显示多少条数据
'PAGE_SIZE': 10000
}
# K8S redis
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": REDIS_LOCATION,
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"PASSWORD":"redis654321",
"SOCKET_CONNECT_TIMEOUT": 5, # in seconds
"SOCKET_TIMEOUT": 5, # r/w timeout in seconds
}
}
}
CELERY_BROKER_URL = REDIS_LOCATION
CELERY_RESULT_BACKEND = REDIS_LOCATION
CELERY_ACCEPT_CONTENT = ['application/json']
CELERY_RESULT_SERIALIZER = 'json'
CELERY_TASK_SERIALIZER = 'json'
CELERY_TIMEZONE = 'Asia/Shanghai'
CELERYD_MAX_TASKS_PER_CHILD = 10
CELERYD_LOG_FILE = os.path.join(BASE_DIR, "logs", "celery_work.log")
CELERYBEAT_LOG_FILE = os.path.join(BASE_DIR, "logs", "celery_beat.log")
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
kompose.cmd: kompose convert
kompose.version: 1.24.0 (7c629530)
creationTimestamp: null
labels:
io.kompose.service: meeting-booking-web
name: meeting-booking-web
spec:
replicas: 1
selector:
matchLabels:
io.kompose.service: meeting-booking-web
strategy:
type: Recreate
template:
metadata:
annotations:
kompose.cmd: kompose convert
kompose.version: 1.24.0 (7c629530)
creationTimestamp: null
labels:
io.kompose.service: meeting-booking-web
spec:
containers:
- command:
- /bin/sh
- /code/package/start.sh
image: seasonzhang/meeting_booking:1.5.13
imagePullPolicy: IfNotPresent
name: meeting-booking-web
ports:
- containerPort: 8000
resources:
requests:
cpu: 500m
memory: 500Mi
limits:
cpu: 500m
memory: 500Mi
- image: redis
name: myredis
command:
- redis-server
- '--requirepass'
- 'redis654321' # 初始密码
ports:
- containerPort: 6379
resources:
requests:
cpu: 100m
memory: 100Mi
limits:
cpu: 200m
memory: 200Mi
- command:
- /bin/sh
- /code/package/start-beat.sh
image: seasonzhang/meeting_booking:1.5.13
name: meeting-booking-beat
resources:
requests:
cpu: 100m
memory: 100Mi
limits:
cpu: 200m
memory: 200Mi
- command:
- /bin/sh
- /code/package/start-celery.sh
image: seasonzhang/meeting_booking:1.5.13
name: meeting-booking-celery
resources:
requests:
cpu: 100m
memory: 100Mi
limits:
cpu: 200m
memory: 200Mi

meeting-booking-web的环境变量

meeting-booking-celery的环境变量

svc

ingress

情形说明:设定meeting-booking-web的环境变量后,没有设定meeting-booking-celery的环境变量,结果meeting-booking-celery一直读取默认值。debug花费了我一周时间。







所以邮件的内容不能在部署在racher中的应用admin后台更改!
所以邮件的内容不能在部署在racher中的应用admin后台更改!
所以邮件的内容不能在部署在racher中的应用admin后台更改!



步骤1:建立临时PVC

步骤2:COPY SQLite给PVC

cp /code/package/classroom_management/SQL/db.sqlite3 /data2/

步骤3:部署应用时挂临时PVC(可选)
步骤4:将临时PVC改到celery的容器

步骤5:发送异步邮件来测试

步骤6:查看PVC
meeting-booking-web的PVC

meeting-booking-beat的PVC

目前我没有解法,但是不影响celery异步邮件发送。
[2022-10-20 13:56:15,162: WARNING/MainProcess] send_apply_email
[2022-10-20 13:56:15,167: ERROR/MainProcess] Task myclassroom.ExchangeEmailSent.send_apply_email[e324fcc7-11a3-42c0-b00b-39a5f88232bd] raised unexpected: DatabaseError("DatabaseWrapper objects created in a thread can only be used in that same thread. The object with alias 'default' was created in thread id 140050967925680 and this is thread id 140050872465712.")
Traceback (most recent call last):
File "/usr/local/lib/python3.8/site-packages/celery/app/trace.py", line 412, in trace_task
R = retval = fun(*args, **kwargs)
File "/usr/local/lib/python3.8/site-packages/celery/app/trace.py", line 704, in __protected_call__
return self.run(*args, **kwargs)
File "/code/package/myclassroom/ExchangeEmailSent.py", line 169, in send_apply_email
print('webmail_items.first().hradmin_namelist',webmail_items.first().hradmin_namelist.strip("'").split(';'))
File "/usr/local/lib/python3.8/site-packages/django/db/models/query.py", line 674, in first
for obj in (self if self.ordered else self.order_by('pk'))[:1]:
File "/usr/local/lib/python3.8/site-packages/django/db/models/query.py", line 280, in __iter__
self._fetch_all()
File "/usr/local/lib/python3.8/site-packages/django/db/models/query.py", line 1324, in _fetch_all
self._result_cache = list(self._iterable_class(self))
File "/usr/local/lib/python3.8/site-packages/django/db/models/query.py", line 51, in __iter__
results = compiler.execute_sql(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size)
File "/usr/local/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 1173, in execute_sql
cursor = self.connection.cursor()
File "/usr/local/lib/python3.8/site-packages/django/utils/asyncio.py", line 26, in inner
return func(*args, **kwargs)
File "/usr/local/lib/python3.8/site-packages/django/db/backends/base/base.py", line 259, in cursor
return self._cursor()
File "/usr/local/lib/python3.8/site-packages/django/db/backends/base/base.py", line 237, in _cursor
return self._prepare_cursor(self.create_cursor(name))
File "/usr/local/lib/python3.8/site-packages/django/db/backends/base/base.py", line 227, in _prepare_cursor
self.validate_thread_sharing()
File "/usr/local/lib/python3.8/site-packages/django/db/backends/base/base.py", line 552, in validate_thread_sharing
raise DatabaseError(
django.db.utils.DatabaseError: DatabaseWrapper objects created in a thread can only be used in that same thread. The object with alias 'default' was created in thread id 140050967925680 and this is thread id 140050872465712.
我发现我把beat的环境变量和PVC设完之后,celery的多线程报错也消失了


设完之后,不报错了!
Task myclassroom.ExchangeEmailSent.send_agree_email[29042ebf-4618-479b-bfee-de640622ee78] succeeded in 0.3765974959824234s: None