本文節選左耳朵耗子相關文章,與讀者共勉! 本質上來說,程式員是手藝人,有手藝的人就能做出別人做不出來的東西,而付費也是一件很自然的事了。那麼,這個問題就成了,如何讓自己的“手藝”更為值錢的問題了。 千里之行,積於跬步 任何一件成功的大事,都是通過一個一個的小成功達到的。所以,你得確保你有一個一個的小 ...
1.欄位加密--django-mirage-field
一個django模型欄位,在保存到資料庫時對數據進行加密,在從資料庫獲取數據時進行解密。它使資料庫中的數據始終加密。
A Django model fields collection that encrypt your data when save to and decrypt when get from database. It keeps data always encrypted in database. Base on AES, it supports query method like get()
and filter()
in Django.
Mirage can also migrate data from origin column to encrypted column in database with a good performance.
需要導入的模塊為;
from mirage.crypto import Crypto
案例:
from mirage.crypto import Crypto c = Crypto() # key is optional, default will use settings.SECRET_KEY ###密鑰是可選的,預設情況下將使用settings.secret處的key c.encrypt('some_address') # -bYijegsEDrmS1s7ilnspA== c.decrypt('-bYijegsEDrmS1s7ilnspA==') # some_address
https://github.com/luojilab/django-mirage-field
https://www.cnpython.com/pypi/django-mirage-field
2.SQL Server 語句不能完整執行的問題
變動的文件為/sql/engines/mssql.py,修改的方法是 execute_check 和 execute 。
在split_sql = [f"""use [{db_name}]"""] 代碼行後面,添加以下語句:
split_sql = split_sql + ['SET NOCOUNT ON;'] #### 解決SQL Server 語句出現更新失敗的情況,失敗指執行不報錯,但是SQL語句完全沒有執行或只執行了部分語句。
參考網址 ; https://www.cnpython.com/qa/402147
3. 其中Redis 的安裝
Redis安裝包下載路徑 如下:
https://redis.io/download
如果下載的版本是 redis-5.0.14.tar.gz
redis 的啟動命令:
./redis-server /XXXXX/redis-5.0.14/redis.conf
密碼設置可參照
https://www.cnblogs.com/xincha/p/16165760.html
4. 非同步調用 async_task
很多地方 是非同步調用的,使用的是django_q中的async_task。
from django_q.tasks import async_task
關於async_task的運行環境,其設置來自於settings.py. 在.../archery/settings.py中設置.
Welcome to Django Q 【官方文檔】
https://django-q.readthedocs.io/en/latest/index.html
5.get_object_or_404
get_object_or_404 是Django的django.shortcuts的方法,用來查詢數據,或者拋出一個DoesNotExist的異常。
用的是ORM中的get方法。
Def get_object_or_404(klass,*args,**kwargs):
需要三個參數:
klass 是一個model對象或者是一個mange.query 對象
*args和**kwargs 是查詢使用到的參數(在klass中查詢)。
6.GoInception相容功能變數名稱 可能遇到的問題
我們知道GoInception是支持IP,例如在備份伺服器上,備份庫的命名格式為:IP_PORT_庫名,例如127_0_0_1_3306_test。
如果需要支持相容功能變數名稱,則下麵的三個問題需要留意:
(1)資料庫的命名規則時不能超過64位,如果是功能變數名稱_埠_庫名,很容易超過64位。如果依照這功能變數名稱_埠_庫名 去找這個資料庫,則這個資料庫可能不存在不存在。
(2)大家想下,goinception在執行的時候, 它產生了一個備份庫,那個這個備份庫的名字是什麼呢? 原來它是做了一個截取,是 保留 功能變數名稱_埠_庫名 命名的後面的64位。
(3)字元串特殊轉換,當功能變數名稱(其實IP也是這個規則) 中含有. 或 – 字元時,自動轉換為_,然後再拼湊備份庫。
7.判斷對象是否有指定的屬性
hasattr() 函數用於判斷對象是否包含對應的屬性。
hasattr(object, name)
- object -- 對象。
- name -- 字元串,屬性名。
如果對象有該屬性返回 True,否則返回 False。
8.多線程併發執行的解決思路
目前 Archery是不支持分片的,即不支持併發。這與應用場景不符,限制了使用場景,迫切需要二開。
我們首先先看下分庫分表的類型。
(1)多實例多庫。即根據業務需要和資源限制,分片規則是部署在多個實例上,並且一個實例上部署了多個資料庫,當然資料庫的名字是不能一樣的。
例如,訂單庫,根據設計和部署要求,訂單分了64個分庫,每個集群上部署了4個庫;即orderdb1,orderdb2,orderdb3,orderdb4 這四個庫部署在了MHA集群1上,4個分庫共用一個DB實例,類似 orderdb5,orderdb6,orderdb7,orderdb8這四個庫部署在了MHA集群2上,這四個庫共用另一個DB實例 。。。。。。依次類推
(2)多實例單庫。即根據業務和資源需要,分片規則是部署在多個實例上,並且一個實例上只部署一個DB,此時資料庫的名字可以一樣的。
例如,物流信息庫,物理庫分了32庫,部署了32套mha集群,每套集群上只有一個資料庫。在所有的集群上的db名字可以一樣(不強求)。
(3)單實例多庫。即分庫了,但是所有的資料庫都在一個實例上(一個mha集群上),當然此時資料庫的名字是不能一樣的。
(4)單實例單庫多表。即分表未分庫。這種情況,我們是不建議的,應該捨棄,多線程併發執行的解決方案不考慮這種情況。因為這種不容易擴展,當性能有壓力時,還是不能橫向擴展的,即不能很快的部署到多個集群上。擴展,需要研發、測試、SRE 配合。
分庫分表工單執行與多並非解決思路:
只要表相同(表名相同、表結構相同),在提交時判斷生成多任務工單。按照DB實例(集群)個數生成一級子任務,按照DB資料庫生成二級子任務。一級子任務併發執行,屬於統一個一級子任務的二級任務串列執行。這也符合我們收到操作的習慣,還可以避免單個實例上多個庫同時執行而遇到資源不夠的情況。判斷多任務還是單任務,是依據提交的工單需要在單個實例上執行還是要多個實例上執行(即實在一個mha集群上執行還是在單個mha集群上執行),多個實例上執行,就是多任務,需要併發;單個實例上執行就是單任務,無需併發。
但是需要註意,各個子任務對應的SQL語句,即要執行的語句是一樣的。
9.多併發--ThreadPoolExecutor
導入主要模塊
from concurrent.futures import ThreadPoolExecutor
結構偽代碼:
def 執行工單的方法: thread_counter = workflow_detail.task1_counter ##創建的最大線程數有工單的一級子任務數據決定 task_pool = [] executor = ThreadPoolExecutor(max_workers=thread_counter) ##設置最大線程池 ###根據一級子任務進行拆解工單 for i in range(1,thread_counter+1)###註意range(),預設是從0開始;另外,計數到stop結束,單步包括stop,所有結束值設置為thread_counter+1 task_name = workflow_detail.task1_counter(i) ###偽代碼,即子任務對應的工單具體內容 task_pool.append(task_name) for result in executor.map(execute_multtask_fun,task_pool) execute_result = result def execute_multtask_fun(task_name); """供多線程調用的單個方法""" 處理一個一級子任務的代碼
註意的是:按照我們多線程併發執行的解決思路,各個子任務對應的SQL語句,即要執行的語句是一樣的。
多線程的知識,可以參照:
《線程池ThreadPoolExecutor類的使用》
https://blog.51cto.com/u_12004792/3138599
10.LDAP登陸設置(AD賬戶登錄)
在 archery/settings.py中設置,
# LDAP ENABLE_LDAP = False if ENABLE_LDAP: import ldap from django_auth_ldap.config import LDAPSearch AUTHENTICATION_BACKENDS = ( 'django_auth_ldap.backend.LDAPBackend', # 配置為先使用LDAP認證,如通過認證則不再使用後面的認證方式 'django.contrib.auth.backends.ModelBackend', # django系統中手動創建的用戶也可使用,優先順序靠後。註意這2行的順序 ) AUTH_LDAP_SERVER_URI = "ldap://xxx" AUTH_LDAP_USER_DN_TEMPLATE = "cn=%(user)s,ou=xxx,dc=xxx,dc=xxx" # ldap認證的另一種方式,使用時註釋AUTH_LDAP_USER_DN_TEMPLATE """ AUTH_LDAP_BIND_DN = "cn=xxx,ou=xxx,dc=xxx,dc=xxx" AUTH_LDAP_BIND_PASSWORD = "***********" AUTH_LDAP_USER_SEARCH = LDAPSearch('ou=xxx,dc=xxx,dc=xxx',ldap.SCOPE_SUBTREE, '(cn=%(user)s)',) """ AUTH_LDAP_ALWAYS_UPDATE_USER = True # 每次登錄從ldap同步用戶信息 AUTH_LDAP_USER_ATTR_MAP = { # key為archery.sql_users欄位名,value為ldap中欄位名,用戶同步信息 "username": "cn", "display": "displayname", "email": "mail" }
需要特別指出的是:
參考;
https://archerydms.com/modules/auth/
https://blog.csdn.net/oscar999/article/details/121216835
檢驗是改進的基礎,持續驗證,持續改進。