国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

深入研究Openstack Nova組件對象模型以及數據庫訪問機制

開發 開發工具 OpenStack
本文首先介紹了Openstack Nova組件數據庫訪問的發展歷程,然后基于源碼分析了當前Nova訪問數據庫的過程,最后解釋了Nova使用軟刪除的原因。

[[193547]]

1. 背景

介紹在Openstack G版以前,Nova的所有服務(包括nova-compute服務)都是直接訪問數據庫的,數據庫訪問接口在nova/db/api.py模塊中實現,而該模塊只是調用了IMPL的方法,即該模塊只是一個代理,真正實現由IMPL實現,IMPL是一個可配置的動態加載驅動模塊,通常使用Python sqlalchemy庫實現,對應的代碼為nova.db.sqlalchemy.api:

  1. _BACKEND_MAPPING = {'sqlalchemy''nova.db.sqlalchemy.api'

該模塊不僅實現了model的CRUD操作,還封裝了一些高級API,比如:

  • instance_get_all: 獲取所有虛擬機實例。
  • instance_update: 更新虛擬機熟悉。

這種直接訪問數據庫的設計至少存在以下兩個問題:

  • 所有服務與數據模型耦合,當數據模型變更時,可能需要涉及所有代碼的調整,并難以支持版本控制。
  • 所有的主機都能訪問數據庫,大大增加了數據庫的暴露風險。

為了實現Nova服務與數據庫訪問解耦,從G版本開始引入了nova-conductor服務,該服務的一個重要作用就是訪問數據庫,其它服務訪問數據庫時需要向nova-conductor發起RPC請求,由nova-conductor代理請求數據庫。

以上方式基本解決了服務與數據庫訪問解耦,并且防止其它服務直接訪問數據庫,但仍然沒有解決對象模型的版本控制。從I版本開始引入了對象模型的概念,所有的對象模型定義在nova/objects。在此之前訪問數據庫是直接調用數據庫的model的,比如更新一個flavor一個字段,調用Flavor的update方法(由sqlalchemy)實現。引入對象模型后,相當于在服務與數據庫之間又添加了一級對象層,各個服務直接和資源對象交互,資源對象再和數據庫接口交互,數據庫返回時也會相應的轉化為對象模型中的對象。

對象模型的對象不僅封裝了數據庫訪問,還支持了版本控制。每個對象都會維護一個版本號,發起RPC請求時必須指定對象的版本號。新版本的對象通常能夠兼容舊版本對象,比如nova-conductor升級了使用對象模型版本為1.2,但nova-compute服務可能還沒有升級完成,仍然使用的是1.1版本,此時請求返回時會把conductor的返回的對象轉化為1.1版本兼容的對象。

目前Cinder服務還是直接訪問數據庫,目前已經在社區有對應的BP關于增加cinder-conductor服務Create conductor service for cinder like nova-conductor, 該BP于2013年6月提出,到當前最新版本N還尚未實現。

2. Nova配置

以上我們介紹了nova-conductor以及對象模型的背景,我們了解到所有服務訪問數據庫都必須通過RPC調用nova-conductor服務請求,但這并不是強制的,如果不考慮數據庫訪問安全,你仍然可以使用本地訪問方式,nova-compute服務可以直接訪問數據庫而不發起nova-conductor RPC調用。我們看nova-compute服務的初始化,它位于nova/cmd/compute.y:

  1. def main(): 
  2.     # ... 
  3.     if not CONF.conductor.use_local: 
  4.         cmd_common.block_db_access('nova-compute'
  5.         objects_base.NovaObject.indirection_api = \ 
  6.             conductor_rpcapi.ConductorAPI() 
  7.     else
  8.         LOG.warning(_LW('Conductor local mode is deprecated and will ' 
  9.                         'be removed in a subsequent release')) 
  10.     # ... 

因此在/etc/nova.conf配置文件中可以配置是否直接訪問數據庫。以上indirection_api是Nova對象模型的一個字段,初始化為None。

如果設置use_local為true,則indirection_api為None,否則將初始化為conductor_rpcapi.ConductorAPI,從這里我們也可以看出調用conductor的入口。

我們可能會想到說在對象模型訪問數據庫時會有一堆if-else來判斷是否使用use_local,事實上是否這樣呢,我們接下來將分析源碼,從而理解Openstack的設計理念。

3. 源碼分析

3.1 nova-compute源碼分析

本小節主要以刪除虛擬機為例,分析nova-compute在刪除虛擬機時如何操作數據庫的。刪除虛擬機的API入口為nova/compute/manager.py的_delete_instance方法,方法原型為:

  1. _delete_instance(self, context, instance, bdms, quotas) 

該方法有4個參數,context是上下文信息,包含用戶、租戶等信息,instance就是我們上面提到的對象模型中Instance對象實例,bdms是blockDeviceMappingList對象實例,保存著block設備映射列表,quotas是nova.objects.quotas.Quotas對象實例,保存該租戶的quota信息。

該方法涉及的數據庫操作代碼為:

  1. instance.vm_state = vm_states.DELETED 
  2. instance.task_state = None 
  3. instance.power_state = power_state.NOSTATE 
  4. instance.terminated_at = timeutils.utcnow() 
  5. instance.save() 
  6. system_meta = instance.system_metadata 
  7. instance.destroy() 

從代碼中可以看到,首先更新instance的幾個字段,然后調用save()方法保存到數據庫中,最后調用destroy方法刪除該實例(注意,這里的刪除并不一定是真的從數據庫中刪除記錄,也有可能僅僅做個刪除的標識)。

我們先找到以上的save()方法,它位于nova/object/instance.py模塊中,方法原型為:

  1. @base.remotable 
  2. save(self, expected_vm_state=None, 
  3.      expected_task_state=None, admin_state_reset=False

save方法會記錄需要更新的字段,并調用db接口保存到數據庫中。關鍵是該方法的wrapper remotable,這個注解(python不叫注解,不過為了習慣這里就叫注解吧)非常重要,該方法在oslo中定義:

  1. def remotable(fn): 
  2.     """Decorator for remotable object methods.""" 
  3.     @six.wraps(fn) 
  4.     def wrapper(self, *args, **kwargs): 
  5.         ctxt = self._context 
  6.         if ctxt is None: 
  7.             raise exception.OrphanedObjectError(method=fn.__name__, 
  8.                                                 objtype=self.obj_name()) 
  9.         if self.indirection_api: 
  10.             updates, result = self.indirection_api.object_action( 
  11.                 ctxt, self, fn.__name__, args, kwargs) 
  12.             for key, value in six.iteritems(updates): 
  13.                 if key in self.fields: 
  14.                     field = self.fields[key
  15.                     # NOTE(ndipanov): Since VersionedObjectSerializer will have 
  16.                     # deserialized any object fields into objects already, 
  17.                     # we do not try to deserialize them again here. 
  18.                     if isinstance(value, VersionedObject): 
  19.                         setattr(self, key, value) 
  20.                     else
  21.                         setattr(self, key
  22.                                 field.from_primitive(self, key, value)) 
  23.             self.obj_reset_changes() 
  24.             self._changed_fields = set(updates.get('obj_what_changed', [])) 
  25.             return result 
  26.         else
  27.             return fn(self, *args, **kwargs) 
  28.  
  29.     wrapper.remotable = True 
  30.     wrapper.original_fn = fn 
  31.     return wrapper 

從代碼看到,當indirection_api不為None時會調用indirection_api的object_action方法,由前面我們知道這個值由配置項use_local決定,當use_local為False時indirection_api為conductor_rpcapi.ConductorAPI。從這里了解到對象并不是通過一堆if-else來判斷是否使用use_local的,而是通過@remotable注解實現的,remotable封裝了if-else,當使用local時直接調用原來對象實例的save方法,否則調用indirection_api的object_action方法。

注意: 除了@remotable注解,還定義了@remotable_classmethod注解,該注解功能和@remotable類似,僅僅相當于又封裝了個@classmethod注解。

3.2 RPC調用

前面我們分析到調用conductor_rpcapi.ConductorAPI的object_action方法,該方法在nova/conductor/rpcapi.py中定義:

  1. def object_action(self, context, objinst, objmethod, args, kwargs): 
  2.         cctxt = self.client.prepare() 
  3.         return cctxt.call(context, 'object_action', objinst=objinst, 
  4.                           objmethod=objmethod, args=args, kwargs=kwargs) 

rpcapi.py封裝了client端的所有RPC調用方法,從代碼上看,發起了RPC server端的object_action同步調用。此時nova-compute工作順利轉接到nova-conductor,并堵塞等待nova-conducor返回。

3.3 nova-conductor源碼分析

nova-conductor RPC server端接收到RPC請求后調用manager.py的object_action方法(nova/conductor/manager.py):

  1. def object_action(self, context, objinst, objmethod, args, kwargs): 
  2.        """Perform an action on an object.""" 
  3.        oldobj = objinst.obj_clone() 
  4.        result = self._object_dispatch(objinst, objmethod, args, kwargs) 
  5.        updates = dict() 
  6.        # NOTE(danms): Diff the object with the one passed to us and 
  7.        # generate a list of changes to forward back 
  8.        for name, field in objinst.fields.items(): 
  9.            if not objinst.obj_attr_is_set(name): 
  10.                # Avoid demand-loading anything 
  11.                continue 
  12.            if (not oldobj.obj_attr_is_set(nameor 
  13.                    getattr(oldobj, name) != getattr(objinst, name)): 
  14.                updates[name] = field.to_primitive(objinst, name
  15.                                                   getattr(objinst, name)) 
  16.        # This is safe since a field named this would conflict with the 
  17.        # method anyway 
  18.        updates['obj_what_changed'] = objinst.obj_what_changed() 
  19.        return updates, result 

該方法首先調用obj_clone()方法備份原來的對象,主要為了后續統計哪些字段更新了。然后調用了_object_dispatch方法:

  1. def _object_dispatch(self, target, method, args, kwargs): 
  2.         try: 
  3.             return getattr(target, method)(*args, **kwargs) 
  4.         except Exception: 
  5.             raise messaging.ExpectedException() 

該方法利用反射機制通過方法名調用,這里我們的方法名為save方法,因此顯然調用了target.save()方法,即最終還是調用的instance.save()方法,不過此時已經是在conductor端調用了.

又回到了nova/objects/instance.py的save方法,有人會說難道這不會無限遞歸RPC調用嗎?顯然不會,這是因為nova-conductor的indirection_api為None,在@remotable中肯定走else分支。

4. 思考一個問題

還記得在_delete_instance方法的數據庫調用代碼嗎?這里再貼下代碼:

  1. instance.vm_state = vm_states.DELETED 
  2. instance.task_state = None 
  3. instance.power_state = power_state.NOSTATE 
  4. instance.terminated_at = timeutils.utcnow() 
  5. instance.save() 
  6. system_meta = instance.system_metadata 
  7. instance.destroy() 

有人會說instance記錄都要刪了,直接調用destory方法不得了,前面一堆更新字段然后save方法是干什么的。這是因為Nova在處理刪除記錄時使用的是軟刪除策略,即不會真正得把記錄徹底刪除,而是在記錄中有個deleted字段標記是否已經被刪除。這樣的好處是方便以后審計甚至數據恢復。

5. 總結

本文首先介紹了Openstack Nova組件數據庫訪問的發展歷程,然后基于源碼分析了當前Nova訪問數據庫的過程,最后解釋了Nova使用軟刪除的原因。

責任編輯:武曉燕 來源: 51CTO專欄
相關推薦

2010-08-26 15:48:21

DB2優化數據庫

2010-11-23 16:35:59

MySQL刪除多表數據

2011-12-15 10:43:20

JavaNIO

2015-05-13 09:57:14

C++靜態庫與動態庫

2011-06-01 10:58:54

Android Service

2010-08-03 17:36:55

DB2數據庫

2012-01-18 11:24:18

Java

2022-05-11 09:03:05

CSS容器文本換行

2018-12-24 15:00:58

混合云多云云采用

2010-11-18 17:24:27

Oracle旋轉ins

2009-10-20 10:17:50

綜合布線系統驗收

2022-04-19 08:28:34

main函數

2010-06-21 13:07:14

2010-11-26 11:57:35

MySQL結果字符串

2010-05-31 17:45:50

MySQL行鎖

2017-06-06 11:29:23

Java異常研究與分析

2016-01-12 18:04:55

Java異常研究

2011-03-16 17:26:22

動態數據庫

2013-01-07 13:38:56

Android開發布局長度單位

2023-11-03 08:25:28

數據結構Java
點贊
收藏

51CTO技術棧公眾號

成人午夜激情网| 日韩一区二区三区国产| 国产一区啦啦啦在线观看| 91麻豆精品国产91久久久更新资源速度超快| 九七影院理伦片| 亚洲三级 欧美三级| 尤物视频一区二区| 久色婷婷小香蕉久久| 偷拍自拍一区| 国产资源在线观看入口av| 污黄视频在线看| 日韩av高清在线看片| 国产精品乱码| 欧美激情区在线播放| 欧美日韩三级一区二区| 国产亚洲精品7777| 亚洲免费福利| 国产免费久久| 欧美男男freegayvideosroom| 婷婷久久综合九色综合绿巨人| 亚洲综合丁香| 色综合久久中文| 黄色影院在线看| 黄页网站在线观看| 尤物av无码色av无码| 国产伦精品一区二区三区免费视频| 欧美不卡一区| 一本色道88久久加勒比精品| 亚洲国产精品成人综合| 性做久久久久久久免费看| 69av一区二区三区| 久久久精品国产| 亚洲一区二区三区xxx视频| 一区二区三区国| 亚洲三级电影网站| 久久99精品久久久久久久久久久久| 欧美系列电影免费观看 | 国产三区精品| 中文日本在线观看| 91精选福利| 奇米精品一区二区三区| 日韩精品一线二线三线| 亚洲999一在线观看www| 国产91|九色| 色天天综合狠狠色| 亚洲国产精品成人va在线观看| 色婷婷久久一区二区三区麻豆| 国产精品激情偷乱一区二区∴| 国产成人超碰人人澡人人澡| 久久婷婷一区| 激情自拍一区| 天天精品视频| 你微笑时很美电视剧整集高清不卡| a屁视频一区二区三区四区| 怡红院在线观看| 国产人成在线观看| 天堂影视av| 国产日韩专区在线| 亚洲精品一二| 国内亚洲精品| 亚洲精品a区| 日韩av免费| 欧美一区二区在线| 中文字幕一区二区三区四区不卡| 狠狠色丁香九九婷婷综合五月 | 宅男宅女性影片资源在线1| 欧美精品aaaa| 男人和女人啪啪网站| 隔壁人妻偷人bd中字| 免费成人深夜夜行网站视频| 亚洲精品一区二| 色综合久久av| 欧洲亚洲一区| 欧洲一区二区在线| 欧美日韩一区二区三区在线视频| 国产精品区一区二区三在线播放 | 亚洲美女av电影| 精品久久久久一区二区国产| 欧美美女黄视频| 另类专区亚洲| 精品亚洲成a人| 亚洲欧美国产精品| 一本久道久久综合| 美女露胸视频在线观看| 在线播放不卡| 欧美哺乳videos| 欧美福利精品| 7m精品国产导航在线| av观看在线| 日本不卡影院| 男女在线观看视频| 福利在线导航136| 欧美aa在线| 美丽的姑娘在线观看免费动漫| 久久不射网站| 精品亚洲一区二区三区在线观看| 国产一区二区不卡视频在线观看| 毛片网站大全| 中日韩男男gay无套| 亚洲第一偷拍| 国产在线日韩| 久久一本综合频道| 美国一区二区三区在线播放| 国产精品亚洲一区二区三区妖精| 成人永久看片免费视频天堂| 久久免费的精品国产v∧| 亚洲欧洲日韩在线| 欧美日韩在线第一页| 欧美精品 日韩| 亚洲国产成人久久综合一区| 亚洲天天在线日亚洲洲精| 免费成人高清视频| 亚洲第一av色| 午夜丝袜av电影| 免费国产在线视频| av有码在线观看| 在线观看三级视频欧美| 久久综合国产精品| 国产一区二区三区毛片| 羞羞的视频网站| 国产91精品露脸国语对白| 操一操视频一区| 97精品国产97久久久久久| 日韩亚洲精品视频| 中文字幕日韩精品有码视频| 日韩三级成人av网| 中文字幕欧美专区| 欧美精品videosex牲欧美| 亚洲欧美激情插| 欧美日韩亚洲一区二| 这里只有精品免费| 国产丝袜精品第一页| 欧美美女18p| 国产精品久久久久久久天堂| 国产精品国产亚洲精品看不卡15 | 一区二区电影| 国内精品久久久久久久影视简单| 婷婷色综合网| 韩日精品视频| 波多野结衣中文在线| 日韩国产大片| 欧美肉体xxxx裸体137大胆| 久久精品日韩欧美| 99国产精品久久久久久久久久 | 欧美性生活一级片| 中文字幕一区二区三区乱码图片| 久久一区国产| 国产成人福利片| 蜜桃视频欧美| 久久精品久久久| 视频在线观看91| 中文av一区二区| 色综合久久99| 一本色道久久综合狠狠躁篇的优点 | 91精品电影| 免费xxxx性欧美18vr| 免费短视频成人日韩| 亚洲成人精选| 国产精品一二三区在线| 亚洲免费视频成人| 亚洲精品suv精品一区二区| 97精品免费视频| 欧美日韩精品免费在线观看视频| 老司机激情视频| 日本一级在线观看| 刘亦菲一区二区三区免费看| 日韩欧美一区二区三区免费看| 美女看a上一区| 一区二区三区在线免费观看| 91久久线看在观草草青青| 99视频一区二区三区| 天天综合天天做天天综合| 国产一区二区三区在线观看网站| 国产精品人人做人人爽| 亚洲小视频在线播放| 三级av在线播放| 精品一区二区三区视频在线播放| 国产精品大片免费观看| 国产欧美日韩三级| 亚洲精品在线观看网站| 国产日韩欧美成人| 国产在线视频综合| 91九色在线porn| 国产精品qvod| 国产一区在线看| 亚洲欧美国产77777| 国产aⅴ精品一区二区三区色成熟| 久久久国产精品| 91香蕉视频mp4| 欧美亚男人的天堂| 97视频在线观看免费| 天堂精品视频| 性网站在线看| 欧美成年网站| 激情欧美一区二区三区在线观看| 欧美三级免费观看| 51视频国产精品一区二区| 女人色极品影院| 黄色成年人视频在线观看| 99视频在线视频|