• [其他] 使用自定义镜像导入模型
    这里给大家介绍一个基于ModelArts平台使用自定义镜像导入模型的样例,帮助您快速熟悉平台的使用方法。 使用自定义镜像导入模型时,需要您熟悉ModelArts的使用,并具备一定的开发经验。详细步骤如下所示: 1. [准备工作] 2. [制作自定义镜像] 3. [本地验证镜像] 4. [上传镜像至SWR服务] 5. [选择从容器镜像中导入模型] 6. [将模型部署为在线服务] #### 准备工作 - 已注册华为云帐号,且在使用ModelArts前检查帐号状态,帐号不能处于欠费或冻结状态。 - 当前帐号已完成访问授权的配置。如未完成,请参考[使用委托授权](https://support.huaweicloud.com/prepare-modelarts/modelarts_08_0007.html)**。**针对之前使用访问密钥授权的用户,建议清空授权,然后使用委托进行授权。 #### 制作自定义镜像 以linux x86\_x64架构的主机为例,您可以购买相同规格的ECS或者应用本地已有的主机进行自定义镜像的制作。 1. 安装Docker,可参考[Docker官方文档](https://docs.docker.com/engine/install/binaries/#install-static-binaries)。可参考以下方式安装docker。 curl -fsSL get.docker.com -o get-docker.sh sh get-docker.sh 2. 获取基础镜像。本示例以Ubuntu18.04为例。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202104/30/213518aqz6jrzwbj4lijbc.png) 3. 新建文件夹“self-define-images”,在该文件夹下编写自定义镜像的“Dockerfile”文件和应用服务代码“test\_app.py”。本样例代码中,应用服务代码采用了flask框架。 文件结构如下所示 self-define-images/ --Dockerfile --test\_app.py - “Dockerfile” From ubuntu:18.04 # 配置华为云的源,安装 python、python3-pip 和 Flask RUN cp -a /etc/apt/sources.list /etc/apt/sources.list.bak && \\ sed -i "s@http://.\*security.ubuntu.com@http://repo.huaweicloud.com@g" /etc/apt/sources.list && \\ sed -i "s@http://.\*archive.ubuntu.com@http://repo.huaweicloud.com@g" /etc/apt/sources.list && \\ apt-get update && \\ apt-get install -y python3 python3-pip && \\ pip3 install --trusted-host https://repo.huaweicloud.com -i https://repo.huaweicloud.com/repository/pypi/simple Flask # 拷贝应用服务代码进镜像里面 COPY test\_app.py /opt/test\_app.py # 指定镜像的启动命令 CMD python3 /opt/test\_app.py - “test\_app.py” from flask import Flask, request import json app = Flask(\_\_name\_\_) @app.route('/greet', methods=\['POST'\]) def say\_hello\_func(): print("----------- in hello func ----------") data = json.loads(request.get\_data(as\_text=True)) print(data) username = data\['name'\] rsp\_msg = 'Hello, {}!'.format(username) return json.dumps({"response":rsp\_msg}, indent=4) @app.route('/goodbye', methods=\['GET'\]) def say\_goodbye\_func(): print("----------- in goodbye func ----------") return '\\nGoodbye!\\n' @app.route('/', methods=\['POST'\]) def default\_func(): print("----------- in default func ----------") data = json.loads(request.get\_data(as\_text=True)) return '\\n called default func !\\n {} \\n'.format(str(data)) # host must be "0.0.0.0", port must be 8080 if \_\_name\_\_ == '\_\_main\_\_': app.run(host="0.0.0.0", port=8080) ** 说明**:modelarts 平台会将请求转发至自定义镜像起的服务的8080端口,故容器内的服务监听的端口必须是8080,如 test\_app.py文件所示。 4. 进入“self-define-images”文件夹,执行以下命令构建自定义镜像“test:v1”。 docker build -t test:v1 . 5. 您可以使用“docker images”查看您构建的自定义镜像。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202104/30/213536vg7tqkpohwdvcmk5.png) #### 本地验证镜像 1. 在本地环境执行以下命令启动自定义镜像 docker run -it -p 8080:8080 test:v1 **图1** 启动自定义镜像 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202104/30/213548yl7on8hmasbrw69z.png) 2. 另开一个终端,执行以下命令验证自定义镜像的三个API接口功能。 curl -X POST -H "Content-Type: application/json" --data '{"name":"Tom"}' 127.0.0.1:8080/ curl -X POST -H "Content-Type: application/json" --data '{"name":"Tom"}' 127.0.0.1:8080/greet curl -X GET 127.0.0.1:8080/goodbye 如果验证自定义镜像功能成功,结果如下图所示。 **图2** 校验接口 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202104/30/213600ox7rkubw0hnlq**.png) #### 上传镜像至SWR服务 1. 登录容器镜像服务控制台,选择区域为“华北-北京四”。 **图3** 容器镜像服务控制台 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202104/30/213613ahwvvxnskd0mpzvm.png) 2. 单击右上角“创建组织”,输入组织名称“deep-learning”完成组织创建。 **图4** 创建组织 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202104/30/213628ikbibje2r3ykvugc.png) 3. 单击右上角“登录指令”,获取登录访问指令。 **图5** 登录指令 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202104/30/213636fgwbc484fyhb3ozo.png) 4. 以root用户登录本地环境,输入登录访问指令。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202104/30/213644gtlpha4pobhz0rrz.png) 5. 上传镜像至容器镜像服务镜像仓库。 1. 使用docker tag命令给上传镜像打标签。 sudo docker tag test:v1 swr.cn-north-4.myhuaweicloud.com/deep-learning/test:v1 2. 使用docker push命令上传镜像。 sudo docker push swr.cn-north-4.myhuaweicloud.com/deep-learning/test:v1 **图6** 上传镜像 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202104/30/2136523mivemj52fktl5x4.png) 6. 完成镜像上传后,在“容器镜像服务控制台>我的镜像”页面可查看已上传的自定义镜像。 **图7** 已上传的自定义镜像 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202104/30/213700fosbmxshzdyaxa3y.png) #### 选择从容器镜像中导入模型 1. 登录ModelArts管理控制台,在左侧导航栏中选择“模型管理 > 模型”,默认进入“我的模型”列表。 2. 单击导入进入“导入模型”页面,参考填写相关信息。 - 基本信息设置:模型名称设置为“model-test”。 **图8** 名称与描述 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202104/30/213713ng1fetipclrgrwil.png) - 元模型来源:选择“从容器镜像中选择”。 **图9** 模型来源配置 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202104/30/213720o9f3ygnhytfvc4pv.png) - 容器镜像所在的路径:选择已制作好的自有镜像。 **图10** 选择已制作好的自有镜像 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202104/30/2137280bsimjw8vdynxfip.png) - 部署类型勾选在线服务。 **图11** 部署类型设置 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202104/30/213737no5nz7lz8krf1vm8.png) - 配置文件:选择“在线编辑”。编辑完成后单击“保存”。 本样例的配置文件如下所示 { "model\_algorithm": "test\_001", "model\_type": "Image", "apis": \[{ "protocol": "http", "url": "/", "method": "post", "request": { "Content-type": "application/json" }, "response": { "Content-type": "application/json" } }, { "protocol": "http", "url": "/greet", "method": "post", "request": { "Content-type": "application/json" }, "response": { "Content-type": "application/json" } }, { "protocol": "http", "url": "/goodbye", "method": "get", "request": { "Content-type": "application/json" }, "response": { "Content-type": "application/json" } } \] } 图12 配置文件设置 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202104/30/214128ufsbv4bjisvljwsb.png) 3. 确认信息填写无误,单击“立即创建”,完成模型导入。 在模型列表中,您可以查看刚导入的模型及其对应的版本。当模型状态变更为“正常”时,表示模型导入成功。 #### 将模型部署为在线服务 1. 登录ModelArts管理控制台,在左侧导航栏中选择“部署上线 > 在线服务”。 2. 单击部署,进入“部署”页面,参考填写相关信息。确认信息无误后,单击下一步。 - 基本信息设置。 **图13** 名称与描述 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202104/30/213756npk4b3dxu3zlrqxv.png) ```js 选择模型来源为“我的模型”,模型选择上一步骤创建的“model-test”。 ``` 图14 作业参数配置 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202104/30/214147ntdfpuw0h3pcuxmt.png) 3. 确认填写信息无误后,根据界面提示完成在线服务的部署。部署服务一般需要运行一段时间,根据您选择的数据量和资源不同,部署时间将耗时几分钟到几十分钟不等。 4. 在线服务创建成功后,您可以在服务详情页查看服务详情。 **图15** 调用指南 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202104/30/213811bnkaz7ljs08uasbl.png) ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202104/30/2138246vnjgiirgnpjr8aq.png) 5. 单击“预测”页签,您可以输入以下示例访问在线服务。 {"hello":"my name is modelarts"} **图16** 访问在线服务 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202104/30/213834gkn147kmzu35o3ev.png) ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202104/30/213839zl2ma84p10ia7oin.png)
  • [新手课堂] 为什么要破坏双亲委派模型?
    原因其实很简单,就是使用双亲委派模型无法满足需求了,因此只能破坏它,这边以面试常问的 Tomcat 为例。我们知道 Tomcat 容器可以同时部署多个 Web 应用程序,多个 Web 应用程序很容易存在依赖同一个 jar 包,但是版本不一样的情况。例如应用1和应用2都依赖了 spring ,应用1使用的 3.2.* 版本,而应用2使用的是 4.3.* 版本。如果遵循双亲委派模型,这个时候使用哪个版本了?其实使用哪个版本都不行,很容易出现兼容性问题。因此,Tomcat 只能选择破坏双亲委派模型。
  • [云计算周刊] 云原生安全的五个建议
    基于容器和无服务器平台的云原生应用在正在快速地被全球的组织所部署。虽然说云原生应用会带来易延展性、无与伦比的韧性、以及快捷的开发速度,云原生应用同样会带来挑战。云原生应用会有大量的可移动成分,并且基于那些短暂的架构组件。这就会给运营和维护产生难度;除此以外,自然还有安全隐患。云原生安全需要新的解决思路、策略和工具。这里,有五个可以帮助改善企业云原生安全的小建议。什么是云原生?云原生应用为云而创建,而且整个软件开发生命周期——开发、部署、测试和升级,都会在云环境完成。“云”的概念不局限于公有云,也可以意味着远程和本地资源都有的混合云或者超过一个云供应商的多云环境。云原生计算基金会(CNCF)认为三种工具应该用于云原生计算中:容器化、微服务结构和动态编排。容器化意味着软件和其关联依赖绑定,从而实现软件可移动、可扩展;动态编排包括了使用Kubernetes等工具管理云端容器;而微服务结构能够优化资源。容器能够被另一项云原生计算能力——无服务器功能所替代。云原生的安全挑战云原生应用给基础设施和应用安全带来了额外挑战。以下是一些关键挑战:多个需要保护的实体:DevOps团队和基础设施团队会使用微服务来运行云原生应用。在过去,多个进程或者软件功能会在一个虚拟机上运行。现在,每个进程或者能力都会被包装成分离的容器或者无服务器功能。每个实体都易于被攻破,因此需要全开发周期的防护。多样的结构:云原生系统会涉及很多公有云和私有云、云服务、以及应用结构。每个结构都有不同的隐患和安全需求。安全团队必须理解这一复杂的攻击面,并且为每个不同的结构找到解决方案。不断变化的环境:公有云和私有云环境在持续变化。快速的软件发布周期意味着微服务应用的每个组件都必须每日进行升级。另外,使用不可变性和基础设施即代码意味着应用会被持续分解并重构。安全团队会发现很难在不减缓发布周期的情况下,保护这些技术应用。如何保护云原生应用有多种保护云原生应用的方式,包括:安全左移、在函数和容器级别应用边界安全、贯彻最小角色和最低权限、保护应用依赖,以及安全共责。1. 安全左移许多企业依然在使用已有的工具,却无法处理云原生应用环境的速度、规模和动态网络。如果再加上无服务器功能,会让整个基础设施变得更抽象,让问题更严重。网络攻击者会寻找容器和无服务器代码中的隐患,以及云基础设施中的错误配置,以接入包含敏感信息的实体,再用它们提升权限,攻击其他实体。另一个问题是企业在用CI/CD工具持续开发、测试和发布应用。当使用容器部署云原生应用的时候,开发者会从本地或者公共库当中获取镜像,但一般不会检查这些镜像是否包含安全隐患。一种解决方案是给安全团队提供一些工具,阻止不受信任的镜像进入CI/CD管道,以及启用一些机制让不受信任的镜像在进入生产前就避免产生安全问题。通过在开发流程早期扫描镜像的漏洞、恶意软件成分等,开发者可以贯彻安全标准。2. 在函数和容器级别应用边界安全在无服务器应用中,系统会被分解成几个能从不同资源接受项目触发的可调用组件。这就给了攻击者更大的攻击选择,以及更多实施恶意行为的途径。一个很重要的方式是使用为云原生环境而制作的API和应用安全工具。除此以外,一个很普遍的操作是在功能级别使用边界安全——识别功能是否被一个和平时不同的来源所触发,然后监控事件触发中存在的异常情况。在容器化环境里,一个重要点是在不同级别都要实现安全——编排控制面板、物理主机、pod和容器。编排的一些最佳安全实践包括节点隔离、限制和监测容器之间的流量、以及对API服务器使用第三方认证机制。3. 最小角色与最低权限云原生资源之间会有大量频繁的交互。如果能够对每个无服务器功能或者容易都能配置一些独特的许可,就能有极大概率提升安全性。可以通过基于每个函数使用IAM,或者对容器进行颗粒度的许可,加强接入控制。花一点时间创建最小角色,或者为每个函数或容器创建一系列的许可。这就确保了即使云原生结构中有一个点失陷,其造成的危害也是最小的,并且会防止其他元件产生提权问题。4. 保护应用依赖无服务器函数和应用的代码经常从npm或者PyPI的库中获取有依赖关系的包。为了保护应用的依赖,就需要包括完整开源组件以及其漏洞数据库的自动化工具。同样,还需要能够在开发流程中触发安全行为的云原生编排工具。通过持续运作这些工具,就可以防范产线上运行的有隐患的代码包或者容器。5. 安全共责在开发者、DevOps和安全团队之间建立亲密的关系。开发者并不是安全专家,但他们可以被教导安全操作知识,从而确保他们可以安全地编写代码。安全团队应该知道应用是如何开发、测试和部署的,还有哪些工具在流程中被使用,从而安全团队能够在这些流程中有效地加入安全元素。云原生要求各种企业管理安全和开发的方式,因此尽快让不同团队减少隔阂至关重要。云原生的启用对企业来说是一个形成合作和共享文化的罕见契机。结论这篇文章提及了云原生面临的挑战,包括大量需要保护的实体,以及持续变化的环境和结构。同样,也给出了五个能够改善云原生环境的最佳实践:安全左移,在问题进入产线前进行规避。在函数和容器级别应用边界安全。对云原生应用中的实体实行最小角色和最低权限。保护好应用依赖。鼓励开发、运营和安全团队之间的安全共责。点评业务节奏加快使得无服务器应用等云原生应用会越来越多被企业所启用,云原生的安全也会更多被注意。不难发现,本文提到的五个安全建议中,软件安全相关的建议占了大部分:无论是安全左移、应用依赖的防护、还是实现DevSecOps整个安全协同,最终都离不开开发安全相关。这一点来看,DevSecOps和API安全的重要性都会随着云原生的使用进一步地提升。来源:https://netsecurity.51cto.com/art/202108/677745.htm
  • [容器专区] LTE0映射不进去容器
    【功能模块】容器模块【操作步骤&问题现象】1、主机把按要求添加映射,保存重启,但LTE0映射不进去容器2、本来主机有LTE0映射之后主机的LTE0也没了,关机等一段时间重新启动,主机的LTE0就有了【截图信息】【日志信息】(可选,上传日志内容或者附件)
  • [技术干货] 对象
    对象定义你可以使用字符来定义和创建 JavaScript 对象:实例var person = {firstName:"John", lastName:"Doe", age:50, eyeColor:"blue"};定义 JavaScript 对象可以跨越多行,空格跟换行不是必须的:实例var person = {    firstName:"John",    lastName:"Doe",    age:50,    eyeColor:"blue"};对象属性可以说 "JavaScript 对象是变量的容器"。但是,我们通常认为 "JavaScript 对象是键值对的容器"。键值对通常写法为 name : value (键与值以冒号分割)。键值对在 JavaScript 对象通常称为 对象属性。Note    JavaScript 对象是属性变量的容器。对象键值对的写法类似于:PHP 中的关联数组Python 中的字典C 语言中的哈希表Java 中的哈希映射Ruby 和 Perl 中的哈希表访问对象属性你可以通过两种方式访问对象属性:实例 1person.lastName;实例 2person["lastName"];对象方法对象的方法定义了一个函数,并作为对象的属性存储。对象方法通过添加 () 调用 (作为一个函数)。该实例访问了 person 对象的 fullName() 方法:实例name = person.fullName();如果你要访问 person 对象的 fullName 属性,它将作为一个定义函数的字符串返回:实例name = person.fullName; Note    JavaScript 对象是属性和方法的容器。在随后的教程中你将学习到更多关于函数,属性和方法的知识。访问对象方法你可以使用以下语法创建对象方法:methodName : function() {    // 代码 }你可以使用以下语法访问对象方法:实例objectName.methodName()通常 fullName() 是作为 person 对象的一个方法, fullName 是作为一个属性。如果使用 fullName 属性,不添加 (), 它会返回函数的定义:实例objectName.methodName
  • [热门活动] 【鲲鹏直播间】鲲鹏应用使能套件第五站——KAE加速引擎让数据加密更安全//提问帖
    直播时间:2021/8/16 19:30-20:30直播嘉宾:华为鲲鹏计算架构&设计专家/黄老师直播链接:https://bbs.huaweicloud.com/live/kunpeng_live/202108161930.html直播简介:本次直播将介绍鲲鹏BoostKit加速库全景,基于BoostKit加速库在WEB、大数据和分布式存储等典型应用场景性能优化实践。参与直播互动赢礼品登录直播平台并签到,您将获得2轮抽奖机会:第一轮:抽取5名幸运观众送出PVC手提包一个第二轮:抽取5名幸运观众送出定制雨伞一把有奖问答:直播过程中进行提问,小助手会在直播间推送3个问题,最先回答正确的3位用户将获得有线耳机一副。(同一实名认证用户不可重复获奖)回答格式:1A2B3C题目可选答;每个用户每题仅一次作答机会,多次回答的以第一次回答的为准;不加题号只发答案的回复不计入有效回答;答题活动于直播当日23:59截止,之后作答无效。问题1(单选题)以下哪个不是大数据的组件?A.ZookeeperB.StormC.KafkaD.Mariadb问题2(单选题)HDFS是一种()框架。A.分布式资源调度B.分布式存储C.分布式计算D.分布式数据库问题3(多选题)以下哪些为Docker容器技术的特点?A.独立的微服务形式B.满足大规模分布式应用快速上线的需求 C.高并发、高性能 D.轻量级、交付快 注意:请直播抽奖的获奖用户在直播页面填写收货信息;问题回答正确的获奖者会由版主私信获奖者提供姓名、收货地址以及手机号,3个工作日内未回复私信则视为放弃奖品;问答获奖用户需在华为云进行实名认证,请于获奖后3个工作日内完成实名认证,否则视为放弃奖励;同一身份信息只能获奖一次;多个账号参与活动的,只能获一次奖励。
  • [技术干货] K8s中的持久卷
    在NFS的基础之上,为了简便运维与管理,增加了持久卷的概念。PersistentVolume(PV):对存储资源创建和使用的抽象,使得存储作为集群中的资源管理PersistentVolumeClaim(PVC):让用户不需要关心具体的Volume实现细节。注:图片截取自李振良老师的视频课程上图是PV、PVC的使用逻辑,通俗的理解:一个企业雇一帮人工作(nfs),选个小组长(pv),再来个团队长(pvc),这样消费者就不会直接面对生产者,企业好管理,用户的服务也有保证。其实就是软件世界的官僚机构~PV使用方式:静态供给,需要K8s运维工程师提前创建一堆PV,供开发者使用。示例:[root@k8s-node2 /]# cat pv.yamlapiVersion: v1kind: PersistentVolumemetadata:  name: my-pvspec:  capacity:    storage: 5Gi  accessModes:    - ReadWriteMany  nfs:    path: /ifs/kubernetes    server: 192.168.0.21[root@k8s-node2 /]# cat deployment-pvc.yamlkind: DeploymentapiVersion: apps/v1metadata:  name: deployment-pvcspec:  selector:    matchLabels:      app: nginx-pvc  replicas: 2  template:    metadata:     labels:      app: nginx-pvc    spec:      containers:      - name: nginx        image: nginx        volumeMounts:         - name: wwwroot           mountPath: /usr/share/nginx/html        ports:        - containerPort: 80      volumes:       - name: wwwroot         persistentVolumeClaim:           claimName: my-pvc---apiVersion: v1kind: PersistentVolumeClaimmetadata:  name: my-pvcspec:  accessModes:   - ReadWriteMany  resources:   requests:    storage: 5Gi[root@k8s-node2 /]# 容器应用和卷需求模板写在了一个depolyment-pvc.yaml中,数据卷的定义写在了pv.yaml中。root@k8s-node2 /]# kubectl apply -f deployment-pvc.yamldeployment.apps/deployment-pvc createdpersistentvolumeclaim/my-pvc created[root@k8s-node2 /]# kubectl get pod -o wideNAME                              READY   STATUS    RESTARTS   AGE   IP               NODE        NOMINATED NODE   READINESS GATESdeployment-pvc-84df7c6f46-b98wx   1/1     Running   0          55m   10.244.169.144   k8s-node2   <none>           <none>deployment-pvc-84df7c6f46-d787b   1/1     Running   0          55m   10.244.169.143   k8s-node2   <none>           <none>nginx-6799fc88d8-z76rk            1/1     Running   2          45h   10.244.169.142   k8s-node2   <none>           <none>[root@k8s-node2 /]# curl 10.244.169.144hello  //上一个实验中的index.html文件[root@k8s-node2 /]# cd ifs[root@k8s-node2 ifs]# cd kubernetes[root@k8s-node2 kubernetes]# echo hello world>index.html[root@k8s-node2 kubernetes]# curl 10.244.169.144    hello world[root@k8s-node2 kubernetes]#
  • [技术干货] IOC 容器的初始化过程
      最近复习了一遍Spring IOC容器的初始化过程,结合书籍《Spring源码深度解析》总结了一下,IOC容器的初始化过程,大概分为以下三点:1、定位资源:  定位相关的配置文件,扫描相关注解2、加载资源:  将配置信息加载到内存中3、注册:  根据载入的配置信息,初始化对象,并将其装载至容器中POM文件<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>springTest</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <!-- https://mvnrepository.com/artifact/org.springframework/spring-context --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.0.2.RELEASE</version> </dependency> </dependencies> </project>测试代码public class ServiceB { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml"); Object serviceA = context.getBean("serviceA"); System.out.println(serviceA); }xml配置<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:cache="http://www.springframework.org/schema/cache" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd"> <context:component-scan base-package="com.donkeys.spring"/> <bean id="serviceA" class="com.donkeys.spring.service.ServiceA"></bean> </beans>ClassPathXmlApplicationContext构造方法 public ClassPathXmlApplicationContext( String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException { super(parent); //根据传入的配置文件名称,调用父类的setConfigLocations方法,解析配置文件路径, setConfigLocations(configLocations); //refresh = true //refresh() 方法会重启整个容器 if (refresh) { refresh(); } }  构造方法中一共做了2件事,首先是设置配置文件的路径,然后对整个容器进行刷新。  这里我们重点关注refresh()方法;进入refresh()方法AbstractApplicationContext类的refresh()方法@Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. //为刷新前做准备 prepareRefresh(); // Tell the subclass to refresh the internal bean factory. //获取IOC容器,这里就是处理资源定位以配置文件加载/注册的方法 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. registerBeanPostProcessors(beanFactory); // Initialize message source for this context. initMessageSource(); // Initialize event multicaster for this context. initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. onRefresh(); // Check for listener beans and register them. registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } // Destroy already created singletons to avoid dangling resources. destroyBeans(); // Reset 'active' flag. cancelRefresh(ex); // Propagate exception to caller. throw ex; } finally { // Reset common introspection caches in Spring's core, since we // might not ever need metadata for singleton beans anymore... resetCommonCaches(); } } }  这里主要关注**obtainFreshBeanFactory()**方法/** * Tell the subclass to refresh the internal bean factory. * @return the fresh BeanFactory instance * @see #refreshBeanFactory() * @see #getBeanFactory() */ protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { //刷新IOC容器 //这里使用了委派设计模式,父类定义了抽象的refreshBeanFactory方法,具体调用实现调用子类的refreshBeanFactory方法 refreshBeanFactory(); //获取一个新的容器 ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (logger.isDebugEnabled()) { logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory); } return beanFactory; }  **obtainFreshBeanFactory()**方法总共干了2件事,  重置容器,refreshBeanFactory()方法中会设置相关标志,清除旧的容器,同时为Spring上下文生成一个新的容器,获取一个新的容器AbstractRefreshableApplicationContext的refreshBeanFactory()方法  下面我们进入**refreshBeanFactory()**方法/** * This implementation performs an actual refresh of this context's underlying * bean factory, shutting down the previous bean factory (if any) and * initializing a fresh bean factory for the next phase of the context's lifecycle. * 该方法会将之前的bean工厂全部关闭,并初始化一个全新的bean 工厂类 用于Spring 上下文的生命周期 * bean工厂就是IOC容器 */ @Override protected final void refreshBeanFactory() throws BeansException { //判断是否之前也有容器 //如果有就销毁掉 if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try { //创建一个新的工厂 DefaultListableBeanFactory beanFactory = createBeanFactory(); beanFactory.setSerializationId(getId()); customizeBeanFactory(beanFactory); //读取Bean对象的定义 //这里也是使用的委派设计模式 loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } }  这里创建了新的容器工厂,同时将新的工厂传入了loadBeanDefinitions()方法中,下面来看一下在loadBeanDefinitions方法中具体做了什么操作。AbstractXmlApplicationContext的 loadBeanDefinitions(DefaultListableBeanFactory beanFactory)方法  在AbstractRefreshableApplicationContext类的refreshBeanFactory方法中,调用了loadBeanDefinitions方法,但是这个方法它的一个抽象方法,具体实现应由子类去实现,我们在程序启动时,使用的ClassPathXmlApplicationContext类。根据文章开头的类图可以知道,这里会调用子类AbstractXmlApplicationContext的loadBeanDefinitions方法去完成本次加载@Override protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException { // Create a new XmlBeanDefinitionReader for the given BeanFactory. //使用默认的beanFactory去创建 XmlBeanDefinitionReader XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); // Configure the bean definition reader with this context's // resource loading environment. //设置资源的加载环境 beanDefinitionReader.setEnvironment(this.getEnvironment()); //设置资源读取器 beanDefinitionReader.setResourceLoader(this); //设置实体解析器 beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); // Allow a subclass to provide custom initialization of the reader, // then proceed with actually loading the bean definitions. //初始化 bean对象定义读取器 initBeanDefinitionReader(beanDefinitionReader); //使用初始化完成的读取器,调用loadBeanDefinitions方法 loadBeanDefinitions(beanDefinitionReader); }  总的来说,这里只干了一件事,那就是初始化配置//设置资源读取器 beanDefinitionReader.setResourceLoader(this); //初始化 bean对象定义读取器 initBeanDefinitionReader(beanDefinitionReader);  设置资源读取器,这里设置的资源读取器就是当前这个对象本身  通过类图我们可以发现我们这个类的顶级父类ApplicationContext,继承自DefaultResourceLoader这个类,该类实现了ResourceLoader接口,说明这个类的实例化对象本身是具有资源读取器的功能的  初始化bean对象定义读取器,这里设置xml文件的校验方式  下面我们继续看**loadBeanDefinitions(XmlBeanDefinitionReader reader)**方法protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException { //从子类对象中获取到资源定位 Resource[] configResources = getConfigResources(); if (configResources != null) { //XmlBeanDefinitionReader 读取器调用其父类的 reader.loadBeanDefinitions(configResources); } String[] configLocations = getConfigLocations(); if (configLocations != null) { reader.loadBeanDefinitions(configLocations); } }  先看这一行//这行代码的具体实现是由子类完成的,通过类图可以知道AbstractXmlApplicationContext的子类为ClassPathXmlApplicationContext //这里主要将我们最开始在构造方法中设置好的配置文件进行返回 Resource[] configResources = getConfigResources();  再看这一行//如果返回的配置文件不为空,就将返回的已经封装好的资源文件进行读取, if (configResources != null) { //XmlBeanDefinitionReader 读取器调用其父类的 reader.loadBeanDefinitions(configResources); }  至此。资源文件定位过程已经加载完成。后续就是读取和注册。整个IOC容器加载过程中最重要的是读取过程,我们可以从刚刚的定位过程来看,虽然叫定位过程,但是其实就是一个配置文件读取器的初始化过程,这个过程会设置相关的解析策略以及校验策略。最终读取器生成后,就可以将我们早早设置好的配置文件载入然后进行读取。
  • [容器专区] 使用eciot-ova编译出来的容器安装到设备上没有ipv4
    【功能模块】容器编译【操作步骤&问题现象】1、根据AR-CORE-220E开发指南容器制作步骤编译出容器;2、安装到AR-CORE-220E设备上;3、使用container status查看容器状态,此时容器ip是ipv6地址;4、等待几分钟后,再次查看,容器ip仍旧是ipv6地址【截图信息】【日志信息】(可选,上传日志内容或者附件)
  • [技术干货] MindSpore解读评注对ccsrc\pipeline\jit\parse\python_adapter.cc的部分注释
    对ccsrc/minddata/dataset/include/dataset的注释 DataHelper,一个通用的数据帮助类,这里是mind数据集包含的数据集数据助手 知识浅薄,还有许多未理解之处,欢迎各位纠正、讨论 路径:mindsspore/ccsrc/minddata/dataset/include/dataset#include "minddata/dataset/include/dataset/data_helper.h"//mind数据集包含的数据集数据助手//DataHelper,一个通用的数据帮助类#include <algorithm>//算法(Algorithm)为一个计算的具体步骤,常用于计算、数据处理和自动推理。C++ 算法库(Algorithms library)为 C++ 程序提供了大量可以用来对容器及其它序列进行算法操作的函数。//这些组件可以为函数或函数模板,大部份由头文件 <algorithm> 提供,一小部份位于 <numeric>、<cstdlib> 中。#include <iostream>//输入输出流#include <map>//map 是一种关联容器, 提供一对一的关联, 关联的形式为: KEY----VALUE(键值对),另外关键字不能重复。//map 也可看做是 关键字映射的集合, 即,map中不可出现重复的关键字,每条映射的关键字都是不同的。#include "minddata/dataset/util/json_helper.h"//在当前文件下导入头文件#include "include/api/status.h"namespace mindspore {//命名空间mindsporenamespace dataset {//命名空间数据集// Create a numbered json file from image folder//从图像文件夹创建编号的json文件Status DataHelper::CreateAlbumIF(const std::vector<char> &in_dir, const std::vector<char> &out_dir){  //建立矢量字符文件 在目录中和输出方向的常量  auto jh = JsonHelper();  return jh.CreateAlbum(CharToString(in_dir), CharToString(out_dir));  //字符到字符串 图表输入目录,图表输出目录  //创建文件     返回文件}// A print method typically used for debugging//通常用于调试的打印方法void DataHelper::Print(std::ostream &out) const {//输出流  out << "  Data Helper"      << "\n";}///状态数据助手 更新数组如果数据类型是后面的就将数据进行相应处理并返回数据再更新数组//输入文件char类型存入容器char键值char     输出文件char//vector 本质上是一个动态数组,它的元素是连续存储的,这意味着不仅可以通过迭代器访问元素,还可以使用指向元素的常规指针来对其进行访问。还可以将指向 vector 元素的指针传递给任何需要指向数组元素的指针的函数。Status DataHelper::UpdateArrayIF(const std::vector<char> &in_file, const std::vector<char> &key,                                 const std::vector<std::vector<char>> &value, const std::vector<char> &out_file) {  auto jh = JsonHelper();//Json帮助程序 auto有两种用途:自动类型推断和返回值占位。   //auto自动类型推断,用于从初始化表达式中推断出变量的数据类型。  return jh.UpdateArray(CharToString(in_file), CharToString(key), VectorCharToString(value), CharToString(out_file));  //制图返回更新后的数组}//输入数据类型为char 建立char容器及key bool类型转化 输出charStatus DataHelper::UpdateArrayIF(const std::vector<char> &in_file, const std::vector<char> &key,                                 const std::vector<bool> &value, const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateArray(CharToString(in_file), CharToString(key), value, CharToString(out_file));  //返回更新后的数组}//输入数据类型为char 建立容器keyint8_t类型(8进制整型数)与值 输出charStatus DataHelper::UpdateArrayIF(const std::vector<char> &in_file, const std::vector<char> &key,                                 const std::vector<int8_t> &value, const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateArray(CharToString(in_file), CharToString(key), value, CharToString(out_file));  //返回更新后的数组}//输入数据类型为char 建立容器keyuint8_t类型(无符号8进制整型数)与值 输出charStatus DataHelper::UpdateArrayIF(const std::vector<char> &in_file, const std::vector<char> &key,                                 const std::vector<uint8_t> &value, const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateArray(CharToString(in_file), CharToString(key), value, CharToString(out_file));  //返回更新后的数组}//输入数据类型为char 建立容器keyint16_t类型(16进制整型数)与值 输出charStatus DataHelper::UpdateArrayIF(const std::vector<char> &in_file, const std::vector<char> &key,                                 const std::vector<int16_t> &value, const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateArray(CharToString(in_file), CharToString(key), value, CharToString(out_file));  //返回更新后的数组}//输入数据类型为char 建立容器keyuint16_t类型(无符号16进制整型数)与值 输出charStatus DataHelper::UpdateArrayIF(const std::vector<char> &in_file, const std::vector<char> &key,                                 const std::vector<uint16_t> &value, const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateArray(CharToString(in_file), CharToString(key), value, CharToString(out_file));  //返回更新后的数组}//输入数据类型为char 建立容器keyint32_t类型(32进制整型数)与值 输出charStatus DataHelper::UpdateArrayIF(const std::vector<char> &in_file, const std::vector<char> &key,                                 const std::vector<int32_t> &value, const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateArray(CharToString(in_file), CharToString(key), value, CharToString(out_file));  //返回更新后的数组}//输入数据类型为char 建立容器key输出uint32_t类型(无符号32进制整型数)与值 输出charStatus DataHelper::UpdateArrayIF(const std::vector<char> &in_file, const std::vector<char> &key,                                 const std::vector<uint32_t> &value, const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateArray(CharToString(in_file), CharToString(key), value, CharToString(out_file));  //返回更新后的数组}//输入数据类型为char 建立容器key int64_t类型(64进制整型数)与值 输出charStatus DataHelper::UpdateArrayIF(const std::vector<char> &in_file, const std::vector<char> &key,                                 const std::vector<int64_t> &value, const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateArray(CharToString(in_file), CharToString(key), value, CharToString(out_file));  //返回更新后的数组}//输入数据类型为char 建立容器key uint64_t类型(无符号64进制整型数)与值 输出charStatus DataHelper::UpdateArrayIF(const std::vector<char> &in_file, const std::vector<char> &key,                                 const std::vector<uint64_t> &value, const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateArray(CharToString(in_file), CharToString(key), value, CharToString(out_file));  //返回更新后的数组}//输入数据类型为char 建立容器key float类型(单精度浮点数)与值来转化 输出charStatus DataHelper::UpdateArrayIF(const std::vector<char> &in_file, const std::vector<char> &key,                                 const std::vector<float> &value, const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateArray(CharToString(in_file), CharToString(key), value, CharToString(out_file));  //返回更新后的数组}//输入数据类型为char 建立容器key double类型(双精度浮点数)与值 输出charStatus DataHelper::UpdateArrayIF(const std::vector<char> &in_file, const std::vector<char> &key,                                 const std::vector<double> &value, const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateArray(CharToString(in_file), CharToString(key), value, CharToString(out_file));  //返回更新后的数组}//输入数据类型为char 建立容器key char类型(字符)与值 输出charStatus DataHelper::UpdateValueIF(const std::vector<char> &in_file, const std::vector<char> &key,                                 const std::vector<char> &value, const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateValue(CharToString(in_file), CharToString(key), CharToString(value), CharToString(out_file));  //返回更新值}//输入数据类型为char 建立容器key bool类型(布尔类型) 常量布尔值 输出charStatus DataHelper::UpdateValueIF(const std::vector<char> &in_file, const std::vector<char> &key,                                 const bool &value, const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateValue(CharToString(in_file), CharToString(key), value, CharToString(out_file));  //返回更新值}//输入数据类型为char 建立容器char和key 常量int8_t类型与值 输出charStatus DataHelper::UpdateValueIF(const std::vector<char> &in_file, const std::vector<char> &key,                                 const int8_t &value,const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateValue(CharToString(in_file), CharToString(key), value, CharToString(out_file));  //返回更新值}//输入数据类型为char 建立容器char和key 常量uint8_t类型与值 输出charStatus DataHelper::UpdateValueIF(const std::vector<char> &in_file, const std::vector<char> &key, const uint8_t &value,                                 const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateValue(CharToString(in_file), CharToString(key), value, CharToString(out_file));  //返回更新值}//输入数据类型为char 建立容器char和key 常量int16_t类型与值 输出charStatus DataHelper::UpdateValueIF(const std::vector<char> &in_file, const std::vector<char> &key, const int16_t &value,                                 const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateValue(CharToString(in_file), CharToString(key), value, CharToString(out_file));  //返回更新值}//输入数据类型为char 建立容器char和key 常量uint16_t类型与值 输出charStatus DataHelper::UpdateValueIF(const std::vector<char> &in_file, const std::vector<char> &key, const uint16_t &value,                                 const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateValue(CharToString(in_file), CharToString(key), value, CharToString(out_file));  //返回更新值}//输入数据类型为char 建立容器char和key 常量int32_t类型与值 输出charStatus DataHelper::UpdateValueIF(const std::vector<char> &in_file, const std::vector<char> &key, const int32_t &value,                                 const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateValue(CharToString(in_file), CharToString(key), value, CharToString(out_file));  //返回更新值}//输入数据类型为char 建立容器char和key 常量uint32_t类型与值 输出charStatus DataHelper::UpdateValueIF(const std::vector<char> &in_file, const std::vector<char> &key, const uint32_t &value,                                 const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateValue(CharToString(in_file), CharToString(key), value, CharToString(out_file));  //返回更新值}//输入数据类型为char 建立容器char和key 常量int64_t类型与值 输出charStatus DataHelper::UpdateValueIF(const std::vector<char> &in_file, const std::vector<char> &key, const int64_t &value,                                 const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateValue(CharToString(in_file), CharToString(key), value, CharToString(out_file));  //返回更新值}//输入数据类型为char 建立容器char和key 常量uint64_t类型与值 输出charStatus DataHelper::UpdateValueIF(const std::vector<char> &in_file, const std::vector<char> &key, const uint64_t &value,                                 const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateValue(CharToString(in_file), CharToString(key), value, CharToString(out_file));  //返回更新值}//输入数据类型为char 建立容器char和key 常量float类型与值 输出charStatus DataHelper::UpdateValueIF(const std::vector<char> &in_file, const std::vector<char> &key, const float &value,                                 const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateValue(CharToString(in_file), CharToString(key), value, CharToString(out_file));  //返回更新值}//输入数据类型为char 建立容器char和key 常量double类型与值 输出charStatus DataHelper::UpdateValueIF(const std::vector<char> &in_file, const std::vector<char> &key, const double &value,                                 const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateValue(CharToString(in_file), CharToString(key), value, CharToString(out_file));  //返回更新值}//输入数据类型为char 建立容器char和key 常量char类型与值 输出charStatus DataHelper::RemoveKeyIF(const std::vector<char> &in_file, const std::vector<char> &key,                               const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.RemoveKey(CharToString(in_file), CharToString(key), CharToString(out_file));  //删除密钥}//输入常量无符号字符张量地址 常量张量大小 地址 常量缓冲区大小size_t DataHelper::DumpData(const unsigned char *tensor_addr, const size_t &tensor_size, void *addr,                            const size_t &buffer_size) {  auto jh = JsonHelper();  return jh.DumpData(tensor_addr, tensor_size, addr, buffer_size);  //返回转储数据包括张量地址 张量大小 地址 缓冲区大小}}  // namespace dataset}  ————————————————原文链接:https://blog.csdn.net/qq_53904578/article/details/119347996
  • [技术干货] MindSpore解读评注对ccsrc/minddata/dataset/include/dataset的注释
    对ccsrc/minddata/dataset/include/dataset的注释 DataHelper,一个通用的数据帮助类,这里是mind数据集包含的数据集数据助手 知识浅薄,还有许多未理解之处,欢迎各位纠正、讨论 路径:mindsspore/ccsrc/minddata/dataset/include/dataset#include "minddata/dataset/include/dataset/data_helper.h"//mind数据集包含的数据集数据助手//DataHelper,一个通用的数据帮助类#include <algorithm>//算法(Algorithm)为一个计算的具体步骤,常用于计算、数据处理和自动推理。C++ 算法库(Algorithms library)为 C++ 程序提供了大量可以用来对容器及其它序列进行算法操作的函数。//这些组件可以为函数或函数模板,大部份由头文件 <algorithm> 提供,一小部份位于 <numeric>、<cstdlib> 中。#include <iostream>//输入输出流#include <map>//map 是一种关联容器, 提供一对一的关联, 关联的形式为: KEY----VALUE(键值对),另外关键字不能重复。//map 也可看做是 关键字映射的集合, 即,map中不可出现重复的关键字,每条映射的关键字都是不同的。#include "minddata/dataset/util/json_helper.h"//在当前文件下导入头文件#include "include/api/status.h"namespace mindspore {//命名空间mindsporenamespace dataset {//命名空间数据集// Create a numbered json file from image folder//从图像文件夹创建编号的json文件Status DataHelper::CreateAlbumIF(const std::vector<char> &in_dir, const std::vector<char> &out_dir){  //建立矢量字符文件 在目录中和输出方向的常量  auto jh = JsonHelper();  return jh.CreateAlbum(CharToString(in_dir), CharToString(out_dir));  //字符到字符串 图表输入目录,图表输出目录  //创建文件     返回文件}// A print method typically used for debugging//通常用于调试的打印方法void DataHelper::Print(std::ostream &out) const {//输出流  out << "  Data Helper"      << "\n";}///状态数据助手 更新数组如果数据类型是后面的就将数据进行相应处理并返回数据再更新数组//输入文件char类型存入容器char键值char     输出文件char//vector 本质上是一个动态数组,它的元素是连续存储的,这意味着不仅可以通过迭代器访问元素,还可以使用指向元素的常规指针来对其进行访问。还可以将指向 vector 元素的指针传递给任何需要指向数组元素的指针的函数。Status DataHelper::UpdateArrayIF(const std::vector<char> &in_file, const std::vector<char> &key,                                 const std::vector<std::vector<char>> &value, const std::vector<char> &out_file) {  auto jh = JsonHelper();//Json帮助程序 auto有两种用途:自动类型推断和返回值占位。   //auto自动类型推断,用于从初始化表达式中推断出变量的数据类型。  return jh.UpdateArray(CharToString(in_file), CharToString(key), VectorCharToString(value), CharToString(out_file));  //制图返回更新后的数组}//输入数据类型为char 建立char容器及key bool类型转化 输出charStatus DataHelper::UpdateArrayIF(const std::vector<char> &in_file, const std::vector<char> &key,                                 const std::vector<bool> &value, const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateArray(CharToString(in_file), CharToString(key), value, CharToString(out_file));  //返回更新后的数组}//输入数据类型为char 建立容器keyint8_t类型(8进制整型数)与值 输出charStatus DataHelper::UpdateArrayIF(const std::vector<char> &in_file, const std::vector<char> &key,                                 const std::vector<int8_t> &value, const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateArray(CharToString(in_file), CharToString(key), value, CharToString(out_file));  //返回更新后的数组}//输入数据类型为char 建立容器keyuint8_t类型(无符号8进制整型数)与值 输出charStatus DataHelper::UpdateArrayIF(const std::vector<char> &in_file, const std::vector<char> &key,                                 const std::vector<uint8_t> &value, const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateArray(CharToString(in_file), CharToString(key), value, CharToString(out_file));  //返回更新后的数组}//输入数据类型为char 建立容器keyint16_t类型(16进制整型数)与值 输出charStatus DataHelper::UpdateArrayIF(const std::vector<char> &in_file, const std::vector<char> &key,                                 const std::vector<int16_t> &value, const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateArray(CharToString(in_file), CharToString(key), value, CharToString(out_file));  //返回更新后的数组}//输入数据类型为char 建立容器keyuint16_t类型(无符号16进制整型数)与值 输出charStatus DataHelper::UpdateArrayIF(const std::vector<char> &in_file, const std::vector<char> &key,                                 const std::vector<uint16_t> &value, const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateArray(CharToString(in_file), CharToString(key), value, CharToString(out_file));  //返回更新后的数组}//输入数据类型为char 建立容器keyint32_t类型(32进制整型数)与值 输出charStatus DataHelper::UpdateArrayIF(const std::vector<char> &in_file, const std::vector<char> &key,                                 const std::vector<int32_t> &value, const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateArray(CharToString(in_file), CharToString(key), value, CharToString(out_file));  //返回更新后的数组}//输入数据类型为char 建立容器key输出uint32_t类型(无符号32进制整型数)与值 输出charStatus DataHelper::UpdateArrayIF(const std::vector<char> &in_file, const std::vector<char> &key,                                 const std::vector<uint32_t> &value, const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateArray(CharToString(in_file), CharToString(key), value, CharToString(out_file));  //返回更新后的数组}//输入数据类型为char 建立容器key int64_t类型(64进制整型数)与值 输出charStatus DataHelper::UpdateArrayIF(const std::vector<char> &in_file, const std::vector<char> &key,                                 const std::vector<int64_t> &value, const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateArray(CharToString(in_file), CharToString(key), value, CharToString(out_file));  //返回更新后的数组}//输入数据类型为char 建立容器key uint64_t类型(无符号64进制整型数)与值 输出charStatus DataHelper::UpdateArrayIF(const std::vector<char> &in_file, const std::vector<char> &key,                                 const std::vector<uint64_t> &value, const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateArray(CharToString(in_file), CharToString(key), value, CharToString(out_file));  //返回更新后的数组}//输入数据类型为char 建立容器key float类型(单精度浮点数)与值来转化 输出charStatus DataHelper::UpdateArrayIF(const std::vector<char> &in_file, const std::vector<char> &key,                                 const std::vector<float> &value, const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateArray(CharToString(in_file), CharToString(key), value, CharToString(out_file));  //返回更新后的数组}//输入数据类型为char 建立容器key double类型(双精度浮点数)与值 输出charStatus DataHelper::UpdateArrayIF(const std::vector<char> &in_file, const std::vector<char> &key,                                 const std::vector<double> &value, const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateArray(CharToString(in_file), CharToString(key), value, CharToString(out_file));  //返回更新后的数组}//输入数据类型为char 建立容器key char类型(字符)与值 输出charStatus DataHelper::UpdateValueIF(const std::vector<char> &in_file, const std::vector<char> &key,                                 const std::vector<char> &value, const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateValue(CharToString(in_file), CharToString(key), CharToString(value), CharToString(out_file));  //返回更新值}//输入数据类型为char 建立容器key bool类型(布尔类型) 常量布尔值 输出charStatus DataHelper::UpdateValueIF(const std::vector<char> &in_file, const std::vector<char> &key,                                 const bool &value, const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateValue(CharToString(in_file), CharToString(key), value, CharToString(out_file));  //返回更新值}//输入数据类型为char 建立容器char和key 常量int8_t类型与值 输出charStatus DataHelper::UpdateValueIF(const std::vector<char> &in_file, const std::vector<char> &key,                                 const int8_t &value,const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateValue(CharToString(in_file), CharToString(key), value, CharToString(out_file));  //返回更新值}//输入数据类型为char 建立容器char和key 常量uint8_t类型与值 输出charStatus DataHelper::UpdateValueIF(const std::vector<char> &in_file, const std::vector<char> &key, const uint8_t &value,                                 const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateValue(CharToString(in_file), CharToString(key), value, CharToString(out_file));  //返回更新值}//输入数据类型为char 建立容器char和key 常量int16_t类型与值 输出charStatus DataHelper::UpdateValueIF(const std::vector<char> &in_file, const std::vector<char> &key, const int16_t &value,                                 const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateValue(CharToString(in_file), CharToString(key), value, CharToString(out_file));  //返回更新值}//输入数据类型为char 建立容器char和key 常量uint16_t类型与值 输出charStatus DataHelper::UpdateValueIF(const std::vector<char> &in_file, const std::vector<char> &key, const uint16_t &value,                                 const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateValue(CharToString(in_file), CharToString(key), value, CharToString(out_file));  //返回更新值}//输入数据类型为char 建立容器char和key 常量int32_t类型与值 输出charStatus DataHelper::UpdateValueIF(const std::vector<char> &in_file, const std::vector<char> &key, const int32_t &value,                                 const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateValue(CharToString(in_file), CharToString(key), value, CharToString(out_file));  //返回更新值}//输入数据类型为char 建立容器char和key 常量uint32_t类型与值 输出charStatus DataHelper::UpdateValueIF(const std::vector<char> &in_file, const std::vector<char> &key, const uint32_t &value,                                 const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateValue(CharToString(in_file), CharToString(key), value, CharToString(out_file));  //返回更新值}//输入数据类型为char 建立容器char和key 常量int64_t类型与值 输出charStatus DataHelper::UpdateValueIF(const std::vector<char> &in_file, const std::vector<char> &key, const int64_t &value,                                 const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateValue(CharToString(in_file), CharToString(key), value, CharToString(out_file));  //返回更新值}//输入数据类型为char 建立容器char和key 常量uint64_t类型与值 输出charStatus DataHelper::UpdateValueIF(const std::vector<char> &in_file, const std::vector<char> &key, const uint64_t &value,                                 const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateValue(CharToString(in_file), CharToString(key), value, CharToString(out_file));  //返回更新值}//输入数据类型为char 建立容器char和key 常量float类型与值 输出charStatus DataHelper::UpdateValueIF(const std::vector<char> &in_file, const std::vector<char> &key, const float &value,                                 const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateValue(CharToString(in_file), CharToString(key), value, CharToString(out_file));  //返回更新值}//输入数据类型为char 建立容器char和key 常量double类型与值 输出charStatus DataHelper::UpdateValueIF(const std::vector<char> &in_file, const std::vector<char> &key, const double &value,                                 const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.UpdateValue(CharToString(in_file), CharToString(key), value, CharToString(out_file));  //返回更新值}//输入数据类型为char 建立容器char和key 常量char类型与值 输出charStatus DataHelper::RemoveKeyIF(const std::vector<char> &in_file, const std::vector<char> &key,                               const std::vector<char> &out_file) {  auto jh = JsonHelper();  return jh.RemoveKey(CharToString(in_file), CharToString(key), CharToString(out_file));  //删除密钥}//输入常量无符号字符张量地址 常量张量大小 地址 常量缓冲区大小size_t DataHelper::DumpData(const unsigned char *tensor_addr, const size_t &tensor_size, void *addr,                            const size_t &buffer_size) {  auto jh = JsonHelper();  return jh.DumpData(tensor_addr, tensor_size, addr, buffer_size);  //返回转储数据包括张量地址 张量大小 地址 缓冲区大小}}  // namespace dataset————————————————原文链接:https://blog.csdn.net/qq_53904578/article/details/119318187
  • [热门活动] 直播梳理-场景+应用,带你硬核解析云原生GIS
    2021年4月1日北京超图软件股份有限公司资深产品经理周世杰老师做客华为云云市场直播间,给大家带来了《场景+应用,带你硬核解析云原生GIS》的主题分享。其实在之前我是不太了解什么是GIS的,非常感谢这次的科普直播,让我不仅了解到了GIS技术,还了解到了相关的产品案例,大有裨益,本文就带大家一起梳理一下直播的内容。GIS是Geographic Information System的简称,即地理信息系统,那云原生GIS又是什么?云原生是一种构建和运行应用程序的方法,是一套技术体系和方法论。云原生GIS是面向环境设计的,基于微服务架构思想的,以容器位部署载体的,可自动化编排、运维管理的,更弹性、更稳定、更新更实时的GIS软件体系架构。也就是以云原生的方式构建和运行的 GIS 应用。云原生GIS有什么优势?1)更稳定:服务可自动恢复 ;故障可自动转移;保证服务永久在线。2)更便捷: 内置存储资源池:Redis、MySQL、MongoDB、HDFS 、 Elasticsearch、HBase、PostGIS、PostgreSQL内置计算资源池:Spark、Hadoop YARN内置流数据环境:Kafka集群3)更弹性:资源更集约计算更高效 云原生GIS的典型应用场景:1)GIS服务数量多云原生设计的初衷就是为了解决大数据时代所带来的数据量 不断增大引起的数据发布不成功、数据加载困难等问题。当用户有成百上千的服务实例时,如果发布在一个iServer或 iServer集群中,服务器的承受力问题和服务崩溃、重启所带来的种种,都是亟待解决的问题。这种情况使用云原生GIS,对服务按 照数据源类型、服务类型、访问频率等进行分类调度到不同的节点, 就可以化解上述问题。2)数据种类多,体积大数据种类多,发布出来的服务数量也会很多,造成的问题跟上述第一个场景一样。 数据的体积比较大的情况下,查询、分析、加载等过程都会 比较耗资源,如果采用传统方式发布,不仅访问该服务会比较慢, 而且也会拖慢其他服务。所以当数据种类多、体积大或服务类型复杂时,都适用于云原生GIS环境,对这类服务进行独立调度和横向伸缩。3)局部平滑升级、故障恢复困难云原生的优势就是更新快、升级快,可以快速更新单个微服务,而不会影响其他功能。 在项目生产过程中,有需要上线一些新功能时,如果采用传统方式往往需要做大量手工配置工作,且存在风险。而在云原生GIS中,用户只需要使用新镜像,就可以滚动更新该服务,从而便捷、平滑稳定的升级新功能。再配合灰度发布让服务上线更加严谨。4)关注微服务、创新随着应用程序的功能日益丰富和强大,微服务应运而生,成为新型软件架构。 云原生GIS是由多个功能小而专注、独立部署的微服务组合出的大型GIS应用程序。各个微服务的开发彼此独立,可以根据功能需求每个微服务使用最适合的技术栈或开发语言。当用户考虑升级整体技术栈时,可以考虑云原生创新应用。5)对高可用关注度高云原生GIS的部署是多节点集群方式搭建,一个节点故障,服务会自动转移到其他存活的节点;如果其中一个服务异常,系统会自动重建一个新的服务来替代异常的服务,因为是基于容器技术,替代过程可以达到秒级替代;基于微服务的横向扩展能力,保证了服务高效稳定。6)机器/VM比较多云原生GIS环境下,所有服务都是由Kubernetes统一管理调 度,用户需要做的就是把这些机器加入Kubernetes集群即可。 云原生GIS会全面监控物理机、容器等资源使用情况,并把服务部署调度到当前最优的机器来运行。 后续有采购新机器,只需要“一键”加入Kubernetes集群即可。 当有机器从Kubernetes中移除后,它上面的服务会自动迁移到其他机器,不需要人工干预。 云原生GIS环境搭建需要的包-华为云:直播链接:https://bbs.huaweicloud.com/live/marketplace_live/202104011900.html超图云GIS管理服务器平台:https://marketplace.huaweicloud.com/contents/1bdc29fb-2828-4aa3-b799-acb09538c1a8?marketplace_live_20210401
  • [容器专区] 【AR502H】【.ova容器包生成】请问怎么生成.ova容器包?我已经生成了base和buster镜像,再制作容器包时失败
  • [容器专区] 【arcore】【容器制作功能】第三方库没有被打包进容器
    【功能模块】把第三方库打包进容器【操作步骤&问题现象】1,用build_sdk_base.sh制作了基础镜像2,自己编译出来了第三方的库(.so和.a),不是按照文档脚本制作,库是测试可用的,库没有问题3,修改了createdeb文件,把所有的库都打包成deb文件执行命令:./Todeb  库文件夹 库名目的:库文件夹里面的DEBIAN文件和第三方库(.so或.a)打包成deb文件,然后分别放到sdk和ova文件夹下(问题1:必须把deb文件放到这两个文件夹下吗,制作sdk,应该和ova没有关系吧)4,用build_sdk.sh制作出编译镜像,并安装(问题2:这一步后,第三方库应该也已经被打包进编译镜像了吧,但是怎么确定打包的.so成功被打包进镜像了,目前/usr/loca/lib和/usr/lib下都没有)5,在制作出的编译环境里面执行build_ova.sh制作出容器,这一步执行过程在附件日志(问题3:安装到核心板上,没有找到第三方库,目前/usr/loca/lib和/usr/lib下都没有,应该在哪里)问题4:上面的第3步,是否可用把所有的.so和.a文件都放到一个文件夹中,一次性打包成.deb,还是必须是分开制作成.deb,然后都放到sdk目录下?问题5:请帮忙看下附件日志,还有一些警告,请问哪些警告可以忽略,哪些不能忽略,必须解决?问题6:第1步制作的交叉编译环境,应该就是华为提供的交叉编译镜像吧?root@2b2df3265563:/data/502H/eciot-ova# cat Todeb #!/bin/bash if [ $# != 1 ];then echo "Usage: $0 appdir package architecture version email description " exit fi DIR=$1 PACKAGE=$1 if [[ ! -d $DIR ]]; then mkdir $DIR fi cp ./my_lib/${PACKAGE} $DIR/ ARCH=arm64 VERSION=1.0 INSTALLED_SIZE=`du -s $DIR | awk '{print $1}'` EMAIL=guoyanzhang@orena.com.cn DESC=orena cd $DIR if [[ ! -d "DEBIAN" ]]; then mkdir DEBIAN fi #md5sum `find . -type f` > DEBIAN/md5sums echo "Package: $PACKAGE" > DEBIAN/control echo "Version: $VERSION" >> DEBIAN/control echo "Architecture: $ARCH" >> DEBIAN/control echo "Depends: " >> DEBIAN/control echo "Installed-Size: $INSTALLED_SIZE " >> DEBIAN/control echo "Priority: optional" >> DEBIAN/control echo "Maintainer: $EMAIL" >> DEBIAN/control echo "Description: $DESC" >> DEBIAN/control chmod 755 -R DEBIAN #dpkg -b . ../${PACKAGE}_${VERSION}_${ARCH}.deb cd .. pwd debName=${PACKAGE}_${VERSION}_${ARCH}.deb dpkg -b $DIR ./${debName} echo ${debName} cp ./${debName} ./custom_deb/ova/${ARCH} mv ./${debName} ./custom_deb/sdk/【截图信息】五【日志信息】(可选,上传日志内容或者附件)无
  • [技术干货] K8s configMap原理介绍
    给容器内应用程序传递参数的实现方式:1. 将配置文件直接打包到镜像中,不推荐使用,因为变更配置不够灵活,配置过程也繁琐。2. 使用环境变量来给Pod应用传参修改配置。3.挂载存储卷: 我们可将配置信息直接放到存储卷中,自动挂载存储卷到配置文件目录,来实现给Pod中应用提供不同的配置。4. 使用configMap存储参数。configMap的作用:  一个configMap资源其实就是一系列配置信息的集合,存放在etcd中;它是K8s中的标准组件,通过两种方式实现给Pod传递配置参数:  A. 将环境变量直接定义在configMap中,Pod启动时,通过env来引用configMap中定义的环境变量。  B. 将一个完整配置文件封装到configMap中,然后通过共享卷的方式挂载到Pod中,读取配置文件实现给应用传参。应用示例:首先定义一个configmap的资源文件。vi configmap-demo.yamlapiVersion: v1kind: ConfigMapmetadata:   name: configmap-demo   data:     abc: "123"        #键值key-value的方式设置参数     cde: "456"     redis.properties: | #”|“代表多行数据     port: 6379     host: 192.168.31.10再定义一个使用configmap的测试容器的yaml文件。vi configmap-demo-pod.yamlapiVersion: v1kind: Podmetadata:   name: configmap-demo-podspec:   containers:   - name: demo   image: nginx   env:   - name: ABCD   valueFrom:   configMapKeyRef:   name: configmap-demo   key: abc   - name: CDEF   valueFrom:   configMapKeyRef:   name: configmap-demo   key: cde   volumeMounts:   - name: config   mountPath: "/config"   readOnly: truevolumes:- name: configconfigMap:  name: configmap-demo  items:  - key: "redis.properties"  path: "redis.properties"[k8s-master~]#kubectl apply -f configmap-demo.yaml[k8s-master~]#kubectl apply -f configmap-demo-pod.yaml[k8s-master~]#kubectl exec -it configmap-demo-pod --bash 进入容器bashroot@configmap-demo-pod:/#echo $abc123root@configmap-demo-pod:/#cat /config/redis.properties port: 6379 host: 192.168.31.10