drf 和 cmdb總結

 

drf

  1. 什麼是restful規範?css

    它是一套規範(協議),它作了一些規則,讓數據交互遵循這個規則。
    對我來講最明顯的是他的method不一樣作不一樣的操做,以前增刪改查要位數4個url。
    詳細:
    1. https代替http,保證數據傳輸時安全。
    2. 在url中通常要體現api標識,這樣看到url就知道他是一個api。
    http://www.luffycity.com/api/....(建議,由於他不會存在跨域的問題)
    http://api.luffycity.com/....
    假設:
    前段:https://www.luffycity.com/home
    後端:https://www.luffycity.com/api/
    3. 在接口中要體現版本
    http://www.luffycity.com/api/v1....(建議,由於他不會存在跨域的問題)
    注意:版本還能夠放在請求頭中
    http://www.luffycity.com/api/
    accept: ...

    4. restful也稱爲面向資源編程,視網絡上的一切都是資源,對資源能夠進行操做,因此通常資源都用名詞。
    http://www.luffycity.com/api/user/

    5. 若是要加入一些篩選條件,能夠添加在url中
    http://www.luffycity.com/api/user/?page=1&type=9

    6. 根據method不一樣作不一樣操做。

    7. 返回給用戶狀態碼
    - 200,成功
    - 300,301永久 /302臨時
    - 400,403拒絕 /404找不到
    - 500,服務端代碼錯誤

    不少公司:
                  def get(self,request,*args,**kwargs):
                      result = {'code':1000,'data':None,'error':None}
                      try:
                          val = int('你好')
                      except Exception as e:
                          result['code'] = 10001
                          result['error'] = '數據轉換錯誤'

                      return Response(result)
           
    8. 返回值
    GET http://www.luffycity.com/api/user/
    [
    {'id':1,'name':'alex','age':19},
    {'id':1,'name':'alex','age':19},
    ]
    POST http://www.luffycity.com/api/user/
    {'id':1,'name':'alex','age':19}

    GET http://www.luffycity.com/api/user/2/
    {'id':2,'name':'alex','age':19}

    PUT http://www.luffycity.com/api/user/2/
    {'id':2,'name':'alex','age':19}

    PATCH https//www.luffycity.com/api/user/2/
    {'id':2,'name':'alex','age':19}

    DELETE https//www.luffycity.com/api/user/2/

    9. 操做異常時,要返回錯誤信息

    {
              error: "Invalid API key"
          }
    10. 對於下一個請求要返回一些接口:Hypermedia AP
    {
    'id':2,
    'name':'alex',
    'age':19,
    'depart': "http://www.luffycity.com/api/user/30/"
    }
  2. drf提供了那些功能?前端

    路由
    url     -> UserView.as_view({"get":"list","post":'create'})
    url(\d+) -> UserView.as_view({"get":"retrive","patch/put/delete/})

    router = routers.DefaultRouter()
    router.register(r'users', views.UserView)
    視圖
    APIView
    ListAPIView/CreateAPIView
    ModelViewSet
    版本
    局部配置
    全局配置
    認證
      當用戶發來請求時,找到認證的全部類並實例化成爲對象列表,而後將對象列表封裝到新的request對象中。
      之後在視同中調用request.user
      在內部會循環認證的對象列表,並執行每一個對象的authenticate方法,該方法用於認證,他會返回兩個值分別會賦值給request.user/request.auth
    權限
    節流,如何實現?
    在緩衝存在相似於一個字典的結構:
    {
    用戶標識:[11231212,12323123,123123123]
    }
    解析器,解析請求體中的數據,將其變成咱們想要的格式。request.data
    篩選器(過濾器)
    分頁
    序列化,對對象或對象列表(queryset)進行序列化操做以及表單驗證的功能。
    渲染器
  3. drf組件認證的實現過程?linux

    from django.conf.urls import url,include
    from django.contrib import admin
    from . import views
    urlpatterns = [
       url(r'^login/$', views.LoginView.as_view()),
       url(r'^order/$', views.OrderView.as_view()),
       url(r'^user/$', views.UserView.as_view()),
    ]

    import uuid
    from django.shortcuts import render
    from django.views import View
    from django.views.decorators.csrf import csrf_exempt
    from django.utils.decorators import method_decorator
    from rest_framework.versioning import URLPathVersioning
    from rest_framework.views import APIView
    from rest_framework.response import Response

    from . import models

    class LoginView(APIView):

       def post(self,request,*args,**kwargs):
           user_object = models.UserInfo.objects.filter(**request.data).first()
           if not user_object:
               return Response('登陸失敗')
           random_string = str(uuid.uuid4())
           user_object.token = random_string
           user_object.save()
           return Response(random_string)

    class MyAuthentication:
       def authenticate(self, request):
           """
          Authenticate the request and return a two-tuple of (user, token).
          """
           token = request.query_params.get('token')
           user_object = models.UserInfo.objects.filter(token=token).first()
           if user_object:
               return (user_object,token)
           return (None,None)

    class OrderView(APIView):
       authentication_classes = [MyAuthentication, ]
       def get(self,request,*args,**kwargs):
           print(request.user)
           print(request.auth)
           return Response('order')

    class UserView(APIView):
       authentication_classes = [MyAuthentication,]
       def get(self,request,*args,**kwargs):
           print(request.user)
           print(request.auth)
           return Response('user')

    源碼分析:
    import uuid
    from django.shortcuts import render
    from django.views import View
    from django.views.decorators.csrf import csrf_exempt
    from django.utils.decorators import method_decorator
    from rest_framework.versioning import URLPathVersioning
    from rest_framework.views import APIView
    from rest_framework.response import Response

    from . import models

    class LoginView(APIView):

       def post(self,request,*args,**kwargs):
           user_object = models.UserInfo.objects.filter(**request.data).first()
           if not user_object:
               return Response('登陸失敗')
           random_string = str(uuid.uuid4())
           user_object.token = random_string
           user_object.save()
           return Response(random_string)

    class MyAuthentication:
       def authenticate(self, request):
           """
          Authenticate the request and return a two-tuple of (user, token).
          """
           token = request.query_params.get('token')
           user_object = models.UserInfo.objects.filter(token=token).first()
           if user_object:
               return (user_object,token)
           return (None,None)

    class OrderView(APIView):
       authentication_classes = [MyAuthentication, ]
       def get(self,request,*args,**kwargs):
           print(request.user)
           print(request.auth)
           return Response('order')

    class UserView(APIView):
       authentication_classes = [MyAuthentication,]
       def get(self,request,*args,**kwargs):
           print(request.user)
           print(request.auth)
           return Response('user')



    class APIView(View):
       authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
       
    def dispatch(self, request, *args, **kwargs):
           """
          `.dispatch()` is pretty much the same as Django's regular dispatch,
          but with extra hooks for startup, finalize, and exception handling.
          """
           # ###################### 第一步 ###########################
           """
          request,是django的request,它的內部有:request.GET/request.POST/request.method
          args,kwargs是在路由中匹配到的參數,如:
              url(r'^order/(\d+)/(?P<version>\w+)/$', views.OrderView.as_view()),
              http://www.xxx.com/order/1/v2/
          """
           self.args = args
           self.kwargs = kwargs


           """
          request = 生成了一個新的request對象,此對象的內部封裝了一些值。
          request = Request(request)
              - 內部封裝了 _request = 老的request
              - 內部封裝了 authenticators = [MyAuthentication(), ]
          """
           request = self.initialize_request(request, *args, **kwargs)
           self.request = request

    def initialize_request(self, request, *args, **kwargs):
           """
          Returns the initial request object.
          """
           parser_context = self.get_parser_context(request)

           return Request(
               request,
               parsers=self.get_parsers(),
               authenticators=self.get_authenticators(), # [MyAuthentication(),]
               negotiator=self.get_content_negotiator(),
               parser_context=parser_context
          )

       def get_authenticators(self):
           """
          Instantiates and returns the list of authenticators that this view can use.
          """
           return [ auth() for auth in self.authentication_classes ]
       
    class LoginView(APIView):
       authentication_classes = []
       def post(self,request,*args,**kwargs):
           user_object = models.UserInfo.objects.filter(**request.data).first()
           if not user_object:
               return Response('登陸失敗')
           random_string = str(uuid.uuid4())
           user_object.token = random_string
           user_object.save()
           return Response(random_string)

    class OrderView(APIView):
       # authentication_classes = [TokenAuthentication, ]
       def get(self,request,*args,**kwargs):
           print(request.user)
           print(request.auth)
           if request.user:
               return Response('order')
           return Response('滾')

    class UserView(APIView):
       同上
  4. drf組件中權限的實現過程?ajax

    from rest_framework.permissions import BasePermission
    from rest_framework import exceptions

    class MyPermission(BasePermission):
       message = {'code': 10001, 'error': '你沒權限'}
       def has_permission(self, request, view):
           """
          Return `True` if permission is granted, `False` otherwise.
          """
           if request.user:
               return True

           # raise exceptions.PermissionDenied({'code': 10001, 'error': '你沒權限'})
           return False

       def has_object_permission(self, request, view, obj):
           """
          Return `True` if permission is granted, `False` otherwise.
          """
           return False
           






    class OrderView(APIView):
       permission_classes = [MyPermission,]
       def get(self,request,*args,**kwargs):
           return Response('order')


    class UserView(APIView):
       permission_classes = [MyPermission, ]
       def get(self,request,*args,**kwargs):
           return Response('user')


    REST_FRAMEWORK = {
       "PAGE_SIZE":2,
       "DEFAULT_PAGINATION_CLASS":"rest_framework.pagination.PageNumberPagination",
       "DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.URLPathVersioning",
       "ALLOWED_VERSIONS":['v1','v2'],
       'VERSION_PARAM':'version',
       "DEFAULT_AUTHENTICATION_CLASSES":["kka.auth.TokenAuthentication",]
    }      
           
           
    源碼分析:
    class APIView(View):
       permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES
       
       def dispatch(self, request, *args, **kwargs):
           封裝request對象
           self.initial(request, *args, **kwargs)
           經過反射執行視圖中的方法

    def initial(self, request, *args, **kwargs):
           版本的處理
           # 認證
           self.perform_authentication(request)

           # 權限判斷
           self.check_permissions(request)
           
           
           self.check_throttles(request)
           
       def perform_authentication(self, request):
           request.user

       def check_permissions(self, request):
           # [對象,對象,]
           for permission in self.get_permissions():
               if not permission.has_permission(request, self):
                   self.permission_denied(request, message=getattr(permission, 'message', None))
       def permission_denied(self, request, message=None):
           if request.authenticators and not request.successful_authenticator:
               raise exceptions.NotAuthenticated()
           raise exceptions.PermissionDenied(detail=message)
           
       def get_permissions(self):
           return [permission() for permission in self.permission_classes]
       
    class UserView(APIView):
       permission_classes = [MyPermission, ]
       
       def get(self,request,*args,**kwargs):
           return Response('user')
  5. drf組件中節流的實現方式?算法

    -實現原理?
    頻率限制在認證、權限以後
    - 匿名用戶,用IP做爲用戶惟一標記,但若是用戶換代理IP,沒法作到真正的限制。
    - 登陸用戶,用用戶名或用戶ID作標識。
    具體實現:
    在django的緩存中 = {
           throttle_anon_1.1.1.1:[100121340,],
           1.1.1.2:[100121251,100120450,]
      }


       限制:60s能訪問3次
       來訪問時:
           1.獲取當前時間 100121280
           2.100121280-60 = 100121220,小於100121220全部記錄刪除
           3.判斷1分鐘之內已經訪問多少次了? 4
           4.沒法訪問
       停一會
       來訪問時:
           1.獲取當前時間 100121340
           2.100121340-60 = 100121280,小於100121280全部記錄刪除
           3.判斷1分鐘之內已經訪問多少次了? 0
           4.能夠訪問

    -具體流程?
    from rest_framework.views import APIView
    from rest_framework.response import Response

    from rest_framework.throttling import AnonRateThrottle,BaseThrottle

    class ArticleView(APIView):
       throttle_classes = [AnonRateThrottle,]
       def get(self,request,*args,**kwargs):
           return Response('文章列表')

    class ArticleDetailView(APIView):
       def get(self,request,*args,**kwargs):
           return Response('文章列表')
           
           
    class BaseThrottle:
       """
      Rate throttling of requests.
      """

       def allow_request(self, request, view):
           """
          Return `True` if the request should be allowed, `False` otherwise.
          """
           raise NotImplementedError('.allow_request() must be overridden')

       def get_ident(self, request):
           """
          Identify the machine making the request by parsing HTTP_X_FORWARDED_FOR
          if present and number of proxies is > 0. If not use all of
          HTTP_X_FORWARDED_FOR if it is available, if not use REMOTE_ADDR.
          """
           xff = request.META.get('HTTP_X_FORWARDED_FOR')
           remote_addr = request.META.get('REMOTE_ADDR')
           num_proxies = api_settings.NUM_PROXIES

           if num_proxies is not None:
               if num_proxies == 0 or xff is None:
                   return remote_addr
               addrs = xff.split(',')
               client_addr = addrs[-min(num_proxies, len(addrs))]
               return client_addr.strip()

           return ''.join(xff.split()) if xff else remote_addr

       def wait(self):
           """
          Optionally, return a recommended number of seconds to wait before
          the next request.
          """
           return None


    class SimpleRateThrottle(BaseThrottle):
       """
      A simple cache implementation, that only requires `.get_cache_key()`
      to be overridden.

      The rate (requests / seconds) is set by a `rate` attribute on the View
      class. The attribute is a string of the form 'number_of_requests/period'.

      Period should be one of: ('s', 'sec', 'm', 'min', 'h', 'hour', 'd', 'day')

      Previous request information used for throttling is stored in the cache.
      """
       cache = default_cache
       timer = time.time
       cache_format = 'throttle_%(scope)s_%(ident)s'
       scope = None
       THROTTLE_RATES = api_settings.DEFAULT_THROTTLE_RATES

       def __init__(self):
           if not getattr(self, 'rate', None):
               self.rate = self.get_rate()
           self.num_requests, self.duration = self.parse_rate(self.rate)

       def get_cache_key(self, request, view):
           """
          Should return a unique cache-key which can be used for throttling.
          Must be overridden.

          May return `None` if the request should not be throttled.
          """
           raise NotImplementedError('.get_cache_key() must be overridden')

       def get_rate(self):
           """
          Determine the string representation of the allowed request rate.
          """
           if not getattr(self, 'scope', None):
               msg = ("You must set either `.scope` or `.rate` for '%s' throttle" %
                      self.__class__.__name__)
               raise ImproperlyConfigured(msg)

           try:
               return self.THROTTLE_RATES[self.scope]
           except KeyError:
               msg = "No default throttle rate set for '%s' scope" % self.scope
               raise ImproperlyConfigured(msg)

       def parse_rate(self, rate):
           """
          Given the request rate string, return a two tuple of:
          <allowed number of requests>, <period of time in seconds>
          """
           if rate is None:
               return (None, None)
           num, period = rate.split('/')
           num_requests = int(num)
           duration = {'s': 1, 'm': 60, 'h': 3600, 'd': 86400}[period[0]]
           return (num_requests, duration)

       def allow_request(self, request, view):
           """
          Implement the check to see if the request should be throttled.

          On success calls `throttle_success`.
          On failure calls `throttle_failure`.
          """
           if self.rate is None:
               return True

           # 獲取請求用戶的IP
           self.key = self.get_cache_key(request, view)
           if self.key is None:
               return True

           # 根據IP獲取他的全部訪問記錄,[]
           self.history = self.cache.get(self.key, [])

           self.now = self.timer()

           # Drop any requests from the history which have now passed the
           # throttle duration
           while self.history and self.history[-1] <= self.now - self.duration:
               self.history.pop()
           if len(self.history) >= self.num_requests:
               return self.throttle_failure()
           return self.throttle_success()

       def throttle_success(self):
           """
          Inserts the current request's timestamp along with the key
          into the cache.
          """
           self.history.insert(0, self.now)
           self.cache.set(self.key, self.history, self.duration)
           return True

       def throttle_failure(self):
           """
          Called when a request to the API has failed due to throttling.
          """
           return False

       def wait(self):
           """
          Returns the recommended next request time in seconds.
          """
           if self.history:
               remaining_duration = self.duration - (self.now - self.history[-1])
           else:
               remaining_duration = self.duration

           available_requests = self.num_requests - len(self.history) + 1
           if available_requests <= 0:
               return None

           return remaining_duration / float(available_requests)


    class AnonRateThrottle(SimpleRateThrottle):
       """
      Limits the rate of API calls that may be made by a anonymous users.

      The IP address of the request will be used as the unique cache key.
      """
       scope = 'anon'

       def get_cache_key(self, request, view):
           if request.user.is_authenticated:
               return None  # Only throttle unauthenticated requests.

           return self.cache_format % {
               'scope': self.scope,
               'ident': self.get_ident(request)
          }
         
  6. 什麼是jwt?優點?django

    通常在先後端分離時,用於作用戶認證(登陸)使用的技術。
    jwt的實現原理:
    - 用戶登陸成功以後,會給前端返回一段token。
    - token是由.分割的三段組成。
    - 第一段:類型和算法信心
    - 第二段:用戶信息+超時時間
    - 第三段:hs256(前兩段拼接)加密 + base64url
    - 之後前端再次發來信息時
    - 超時驗證
    - token合法性校驗
    優點:
    - token只在前端保存,後端只負責校驗。
    - 內部集成了超時時間,後端能夠根據時間進行校驗是否超時。
    - 因爲內部存在hash256加密,因此用戶不能夠修改token,只要一修改就認證失敗。
  7. drf中 GenericAPIView 的做用?編程

    GenericAPIView,橋樑,內部定義:get_queryset/get_serilizer/get_page...

    ListAPIView,CreateAPIView,RetrieveAPIView,UpdateAPIView,DestroyAPIView
  8. 先後端分離項目:跨域問題json

    因爲瀏覽器具備「同源策略」的限制。
    若是在同一個域下發送ajax請求,瀏覽器的同源策略不會阻止。
    若是在不一樣域下發送ajax,瀏覽器的同源策略會阻止。


    #### 解決跨域:CORS

    ```
    本質在數據返回值設置響應頭

    from django.shortcuts import render,HttpResponse

    def json(request):
      response = HttpResponse("JSONasdfasdf")
      response['Access-Control-Allow-Origin'] = "*"
      return response
       
    ```



    #### 跨域時,發送了2次請求?

    在跨域時,發送的請求會分爲兩種:

    - 簡單請求,發一次請求。

    設置響應頭就能夠解決 from django.shortcuts import render,HttpResponse後端

    def json(request): response = HttpResponse("JSONasdfasdf") response['Access-Control-Allow-Origin'] = "*" return responseapi


    - 複雜請求,發兩次請求。

    - 預檢
    - 請求

    @csrf_exempt def put_json(request): response = HttpResponse("JSON複雜請求") if request.method == 'OPTIONS': # 處理預檢 response['Access-Control-Allow-Origin'] = "*" response['Access-Control-Allow-Methods'] = "PUT" return response elif request.method == "PUT": return response


    ```
    條件:
      一、請求方式:HEAD、GET、POST
      二、請求頭信息:
          Accept
          Accept-Language
          Content-Language
          Last-Event-ID
          Content-Type 對應的值是如下三個中的任意一個
                                  application/x-www-form-urlencoded
                                  multipart/form-data
                                  text/plain

    注意:同時知足以上兩個條件時,則是簡單請求,不然爲複雜請求
    ```

    #### 總結

    1. 因爲瀏覽器具備「同源策略」的限制,因此在瀏覽器上跨域發送Ajax請求時,會被瀏覽器阻止。
    2. 解決跨域
      - 不跨域
      - CORS(跨站資源共享,本質是設置響應頭來解決)。
        - 簡單請求:發送一次請求
        - 複雜請求:發送兩次請求
  9. 序列化器中如何自定義字段?

    展現特殊的數據(choices、FK、M2M)可以使用
    depth 
    source,無需加括號,在源碼內部會去判斷是否可執行,若是可執行自動加括號。【fk/choice】 
    SerializerMethodField,定義鉤子方法。【m2m】
    

cmdb

  1. 爲何要開發cmdb?

    服務器資產信息的採集。
    原來用的Excel維護,愈來愈不許確。
    自動進行資產信息的採集以及變動。
    系統開發出來時候,能夠自動化採集資產信息,而且給其餘系統提供數據支持。
  2. cmdb架構以及實現?

    中控機,基於paramiko鏈接遠程服務器執行命令進行採集;參考django的中間件的源碼、工廠模式、反射 進行可插拔的式插件的管理;經過父類中的異常對子類中的方法進行約束; 單利模式處理日誌; 錯誤堆棧信息; 基於線程池作併發;
    API,負責資產信息的入庫以及資產變動處理(Q查詢); 給其餘系統提供數據支持,而且要作資產變動記錄,爲了之後搭建運維自動化平臺,能夠爲其餘系統提供restful接口作數據支持。
    管控平臺,資產信息的管理 + 報表。  
  3. 資產採集方式?

    - paramiko
    - agent
    - ansible/saltstack
  4. cmdb資產多久採集一次?

    1天採集一次, cmdb採集的是物理機的資產信息,硬件資產不會常常進行變更。
  5. cmdb技術點?

    1. - 類的約束

      - 經過字符串的形式導入一個模塊
     import importlib
    module = importlib.import_module("xxx.xx.xx.csss")
    ```
    • 反射,經過字符串形式去操做對象中屬性

      getattr
      setattr
      delattr
      hasattr
    • 線程池的應用

    • 導入包時,自動加載 __init__.py

    • requests模塊的應用

      requests.get(url='...')

      requests.post(url="...",data={})

      requests.post(url="...",json={})
    • 項目中容易被修改的值,能夠放在配置文件中。

    • 開放封閉原則

      配置開放
      源碼封閉
    • 工廠模式:簡單工廠

      mode = "email"
      class Email(object):
      def send(self):
      pass

      class Wechat(object):
      def send(self):
      pass

      class Message(object):
      def send(self):
      pass
      def run():
      instance = None
      if mode == 'email':
      instance = Email()
      elif mode == 'wechat':
      instance = Wechat()
      elif mode == 'message':
      insance = Message()

      if not instance:
      print('配置異常')
      instance.send()

      run()
    • 工廠模式:工廠方法/抽象工廠

      mode = "xxx.xx.Email"
      class Email(object):
      def send(self):
      pass

      class Wechat(object):
      def send(self):
      pass

      class Message(object):
      def send(self):
      pass
      def run():
      根據反射到類,並實例化。
      instance.send()
      run()
  6. 大家公司有多少臺服務器?

    100臺左右物理機。
  7. 獲取資產的命令?

    - 內存信息
    sudo dmidecode -q -t 17 2>/dev/null
    注意:linux上要提早安裝 yum install dmidecode
    - 硬盤(安裝MegaCli)
    sudo MegaCli -PDList -aALL
    - 網卡
    sudo ip link show
    sudo ip addr show
    - 主板
    sudo dmidecode -t1
    - CPU
    cat /proc/cpuinfo
相關文章
相關標籤/搜索