草庐IT

SQL Archery 代码说明及优化(一)

东山絮柳仔 2023-04-15 原文

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"
    }

需要特别指出的是:

11.DEBUG=False静态文件无法访问

静态文件不能加载导致的问题:

(1)页面排版不正常,css文件不能正常加载;

(2)通过url不能访问静态文件,如图片等。

解决方案

在urls.py文件中,添加以下代码:

from django.views import static ##新增
from django.conf import settings ##新增
from django.conf.urls import url ##新增

urlpatterns = [
    ......
    ## 以下是新增
    url(r'^static/(?P<path>.*)$', static.serve,{'document_root': settings.STATIC_ROOT}, name='static'),
]

 特别注意

此时 login 登录访问时,调用的static可能还会有302 异常,需要进一步设置。

在.../common/middleware/check_login_middleware.py文件中,修改 url例外 规则

....
##调整前
##IGNORE_URL_RE = r'/admin/\w*'
##调整后
IGNORE_URL_RE = r'(/admin/\w*|/static/\w*)'
.....

 

参考

https://archerydms.com/modules/auth/

https://blog.csdn.net/oscar999/article/details/121216835 

https://zhuanlan.zhihu.com/p/151855280

 

检验是改进的基础,持续验证,持续改进。

有关SQL Archery 代码说明及优化(一)的更多相关文章

  1. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  2. ruby-on-rails - Rails 源代码 : initialize hash in a weird way? - 2

    在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has

  3. ruby-on-rails - 浏览 Ruby 源代码 - 2

    我的主要目标是能够完全理解我正在使用的库/gem。我尝试在Github上从头到尾阅读源代码,但这真的很难。我认为更有趣、更温和的踏脚石就是在使用时阅读每个库/gem方法的源代码。例如,我想知道RubyonRails中的redirect_to方法是如何工作的:如何查找redirect_to方法的源代码?我知道在pry中我可以执行类似show-methodmethod的操作,但我如何才能对Rails框架中的方法执行此操作?您对我如何更好地理解Gem及其API有什么建议吗?仅仅阅读源代码似乎真的很难,尤其是对于框架。谢谢! 最佳答案 Ru

  4. ruby - 模块嵌套代码风格偏好 - 2

    我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的

  5. ruby - 寻找通过阅读代码确定编程语言的ruby gem? - 2

    几个月前,我读了一篇关于ruby​​gem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:

  6. ruby - Net::HTTP 获取源代码和状态 - 2

    我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur

  7. 程序员如何提高代码能力? - 2

    前言作为一名程序员,自己的本质工作就是做程序开发,那么程序开发的时候最直接的体现就是代码,检验一个程序员技术水平的一个核心环节就是开发时候的代码能力。众所周知,程序开发的水平提升是一个循序渐进的过程,每一位程序员都是从“菜鸟”变成“大神”的,所以程序员在程序开发过程中的代码能力也是根据平时开发中的业务实践来积累和提升的。提高代码能力核心要素程序员要想提高自身代码能力,尤其是新晋程序员的代码能力有很大的提升空间的时候,需要针对性的去提高自己的代码能力。提高代码能力其实有几个比较关键的点,只要把握住这些方面,就能很好的、快速的提高自己的一部分代码能力。1、多去阅读开源项目,如有机会可以亲自参与开源

  8. 7个大一C语言必学的程序 / C语言经典代码大全 - 2

    嗨~大家好,这里是可莉!今天给大家带来的是7个C语言的经典基础代码~那一起往下看下去把【程序一】打印100到200之间的素数#includeintmain(){ inti; for(i=100;i 【程序二】输出乘法口诀表#includeintmain(){inti;for(i=1;i 【程序三】判断1000年---2000年之间的闰年#includeintmain(){intyear;for(year=1000;year 【程序四】给定两个整形变量的值,将两个值的内容进行交换。这里提供两种方法来进行交换,第一种为创建临时变量来进行交换,第二种是不创建临时变量而直接进行交换。1.创建临时变量来

  9. git使用常见问题(提交代码,合并冲突) - 2

    文章目录git常用命令(简介,详细参数往下看)Git提交代码步骤gitpullgitstatusgitaddgitcommitgitpushgit代码冲突合并问题方法一:放弃本地代码方法二:合并代码常用命令以及详细参数gitadd将文件添加到仓库:gitdiff比较文件异同gitlog查看历史记录gitreset代码回滚版本库相关操作远程仓库相关操作分支相关操作创建分支查看分支:gitbranch合并分支:gitmerge删除分支:gitbranch-ddev查看分支合并图:gitlog–graph–pretty=oneline–abbrev-commit撤消某次提交git用户名密码相关配置g

  10. spring.profiles.active和spring.profiles.include的使用及区别说明 - 2

    转自:spring.profiles.active和spring.profiles.include的使用及区别说明下文笔者讲述spring.profiles.active和spring.profiles.include的区别简介说明,如下所示我们都知道,在日常开发中,开发|测试|生产环境都拥有不同的配置信息如:jdbc地址、ip、端口等此时为了避免每次都修改全部信息,我们则可以采用以上的属性处理此类异常spring.profiles.active属性例:配置文件,可使用以下方式定义application-${profile}.properties开发环境配置文件:application-dev

随机推荐