• [技术干货] 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类去加载Sping的配置文件,所以先给出该类类图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容器加载过程中最重要的是读取过程,我们可以从刚刚的定位过程来看,虽然叫定位过程,但是其实就是一个配置文件读取器的初始化过程,这个过程会设置相关的解析策略以及校验策略。最终读取器生成后,就可以将我们早早设置好的配置文件载入然后进行读取。————————————————
  • [教程] K8S--运行nginx容器
    运行容器(1)运行Nginx应用运行Nginx应用。[root@master ~]# cat nginx.yamlapiVersion: apps/v1 kind: Deployment metadata:   name: nginxspec:  replicas: 1   selector:     matchLabels:       app: nginx  template:     metadata:      labels:         app: nginx    spec:       containers:      - name: nginxapp-container        image: nginx:latest        imagePullPolicy: IfNotPresent        ports:         - name: nginxapp          containerPort: 80[root@master ~]# kubectl create -f nginx.yamldeployment.apps/nginx created(2)查看Pods验证Pods是否正常运行。[root@master ~]# kubectl get podsNAME                    READY   STATUS    RESTARTS   AGEnginx-75dcbbc897-c4xbp        1/1       Running    0            93s……(3)开放端口使用expose将service的80端口开放出去。[root@master ~]# kubectl expose deploy/nginx --port 80service/nginx exposed(4)测试Nginx应用[root@master ~]# kubectl get svcNAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGEkubernetes       ClusterIP     10.96.0.1         <none>        443/TCP   3h18mnginx           ClusterIP     10.100.220.6      <none>        80/TCP    9s[root@master ~]#  curl 10.100.220.6:80……<h1>Welcome to nginx!</h1><p>If you see this page, the nginx web server is successfully installed andworking. Further configuration is required.</p><p>For online documentation and support please refer to<a href="http://nginx.org/">nginx.org</a>.<br/>Commercial support is available at<a href="http://nginx.com/">nginx.com</a>.</p><p><em>Thank you for using nginx.</em></p></body></html>使用curl工具可以成功获取到Nginx网页信息,说明80端口已开放成功。3.3.Kubernetes运维(1)Node的隔离与恢复在硬件升级、硬件维护等情况下,需要将某些Node隔离。使用kubectl cordon <node_name>命令可禁止Pod调度到该节点上(单节点不需执行),在其上运行的Pod并不会自动停止,管理员需要手动停止在该Node上运行的Pod。[root@master ~]# kubectl cordon node查看Node的状态,可以观察到在node的状态中增加了一项SchedulingDisabled,对于后续创建的Pod,系统将不会再向该Node进行调度。[root@master ~]# kubectl get nodes通过kubectl uncordon命令可完成对Node的恢复。[root@master ~]# kubectl uncordon node[root@master ~]# kubectl get nodes可以看到Node节点已恢复调度,允许Pod调度到该节点上。通过kubectl drain <node>命令可实现对node节点的驱逐,该命令会删除该节点上的所有Pod(DaemonSet除外),在其他Node上重新启动它们。(2)Pod动态扩容和缩放在实际生产系统中,经常会遇到某个服务需要扩容的场景,也可能会遇到由于资源紧张或者工作负载降低而需要减少服务实例数量的场景。此时可以利用kubectl scale deployment命令来完成这些任务。通过执行下面的命令将Nginx Deployment控制的Pod副本数量从初始的1更新为5。[root@master ~]# kubectl scale deployment nginx --replicas=5deployment.extensions/nginx scaled执行kubectl get pods命令来验证Pod的副本数量增加到5。[root@master ~]# kubectl get podsNAME                    READY   STATUS    RESTARTS   AGEnginx-ccb467dc5-2f6n2   1/1     Running   0          34s......将--replicas设置为比当前Pod副本数量更小的数字,系统将会“杀掉”一些运行中的Pod,即可实现应用集群缩容。[root@master ~]# kubectl scale deployment nginx --replicas=2deployment.extensions/nginx scaled[root@master ~]# kubectl get podsNAME                    READY   STATUS    RESTARTS   AGEnginx-ccb467dc5-bl4jp   1/1     Running   0          2m50snginx-ccb467dc5-jlr4c   1/1     Running   0          5m21s(3)应用滚动升级当集群中的某个服务需要升级时,需要停止目前与该服务相关的所有Pod,然后重新拉取镜像并启动。如果集群规模比较大,这个工作就变成了一个挑战。如果采取先全部停止,然后逐步升级的方式,会导致较长时间的服务不可用。Kubernetes提供了rolling-update(滚动升级)功能来解决上述问题。滚动升级通过执行kubectl rolling-update命令一键完成,该命令创建了一个新的Deployment,然后自动控制旧的Deployment中的Pod副本数量逐渐减少到0,同时新的Deployment中的Pod副本数量从0逐步增加到目标值,最终实现了Pod的升级。注意:系统要求新的Deployment需要与旧的Deployment在相同的命名空间(Namespace)内,即不能把别人的资产偷偷转移到自家名下。下面的示例在第一次部署时使用httpd:2.2.31,然后使用滚动升级更新到httpd:2.2.32。定义httpd.yaml文件。[root@master ~]# cat httpd.yamlapiVersion: apps/v1kind: Deploymentmetadata:  name: httpdspec:  selector:     matchLabels:       app: httpd  replicas: 3  template:    metadata:      labels:        app: httpd    spec:      containers:        - name: httpd          image: httpd:2.2.31          imagePullPolicy: IfNotPresent          ports:            - containerPort: 80启动Deployment。[root@master ~]# kubectl create -f httpd.yaml deployment.apps/httpd created[root@master ~]# kubectl get podsNAME                     READY   STATUS    RESTARTS   AGEhttpd-5ddb558f47-46tf5   1/1     Running   0          49shttpd-5ddb558f47-5dg96   1/1     Running   0          49shttpd-5ddb558f47-672sk   1/1     Running   0          49s查看Deployment。[root@master ~]# kubectl get deployments httpd -o wideNAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTORhttpd    3/3      3           3        93s    httpd     httpd:2.2.31  run=httpd可以看到,IMAGES为httpd:2.2.31。把配置文件中的httpd:2.2.31改为httpd:2.2.32,再次启动。[root@master ~]# cat httpd.yaml apiVersion: apps/v1kind: Deploymentmetadata:  name: httpdspec:  selector:     matchLabels:       app: httpd  replicas: 3  template:    metadata:      labels:        app: httpd    spec:      containers:        - name: httpd          image: httpd:2.2.32          imagePullPolicy: IfNotPresent          ports:            - containerPort: 80[root@master ~]# kubectl apply -f httpd.yamlWarning: kubectl apply should be used on resource created by either kubectl create --save-config or kubectl applydeployment.apps/httpd configured再次查看Deployment。[root@master ~]# kubectl get deployments httpd -o wideNAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTORhttpd    3/3      3       3            7m53s   httpd   httpd:2.2.32  run=httpd查看Deployment的详细信息。[root@master ~]# kubectl describe deployment httpd…...Events:  Type    Reason             Age   From                   Message  ----    ------             ----  ----                   -------  Normal  ScalingReplicaSet  22m   deployment-controller  Scaled up replica set httpd-5ddb558f47 to 3  Normal  ScalingReplicaSet  15m   deployment-controller  Scaled up replica set httpd-8bdffc6d8 to 1  Normal  ScalingReplicaSet  14m   deployment-controller  Scaled down replica set httpd-5ddb558f47 to 2  Normal  ScalingReplicaSet  14m   deployment-controller  Scaled up replica set httpd-8bdffc6d8 to 2  Normal  ScalingReplicaSet  14m   deployment-controller  Scaled down replica set httpd-5ddb558f47 to 1  Normal  ScalingReplicaSet  14m   deployment-controller  Scaled up replica set httpd-8bdffc6d8 to 3  Normal  ScalingReplicaSet  13m   deployment-controller  Scaled down replica set httpd-5ddb558f47 to 0上面的日志信息就描述了滚动升级的过程:① 启动一个新版Pod。② 把旧版Pod数量降为2。③ 再启动一个新版,数量变为2。④ 把旧版Pod数量降为1。⑤ 再启动一个新版,数量变为3。⑥ 把旧版Pod数量降为0。这就是滚动的意思,始终保持副本数量为3,控制新旧Pod的交替,实现了无缝升级。kubectl apply每次更新应用时,kubernetes都会记录下当前的配置,保存为一个revision,这样就可以回滚到某个特定的版本。创建3个配置文件,内容中唯一不同的就是镜像的版本号。httpd.v1.yaml:[root@master ~]# cat httpd.v1.yaml apiVersion: apps/v1kind: Deploymentmetadata:  name: httpdspec:  selector:     matchLabels:       app: httpd  revisionHistoryLimit: 10 # 指定保留最近的几个revision  replicas: 3  template:    metadata:      labels:        app: httpd    spec:      containers:        - name: httpd          image: httpd:2.2.31          ports:            - containerPort: 80httpd.v2.yaml:[root@master ~]# cat httpd.v2.yaml apiVersion: apps/v1kind: Deploymentmetadata:  name: httpdspec:  selector:    matchLabels:       app: httpd  revisionHistoryLimit: 10 # 指定保留最近的几个revision  replicas: 3  template:    metadata:      labels:        app: httpd    spec:      containers:        - name: httpd          image: httpd:2.2.32          ports:            - containerPort: 80部署Deployment。[root@master ~]# kubectl apply -f httpd.v1.yaml --recorddeployment.apps/httpd configured[root@master ~]# kubectl apply -f httpd.v2.yaml --recorddeployment.apps/httpd configured--record的作用是将当前命令记录到revision中,可以知道每个revision对应的是哪个配置文件。查看Deployment。[root@master ~]# kubectl get deployments -o wideNAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTORhttpd    3/3        1           3      31m      httpd   httpd:2.2.32 app=httpd查看revision历史记录。[root@master ~]# kubectl rollout history deployment httpddeployment.apps/httpd REVISION  CHANGE-CAUSE1         <none>2         kubectl apply --filename=httpd.v2.yaml --record=trueCHANGE-CAUSE即-record的结果。执行如下操作,回滚到指定版本revision 1。[root@master ~]# kubectl rollout undo deployment httpd --to-revision=1deployment.extensions/httpd rolled back[root@master ~]# kubectl get deployments -o wideNAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTORhttpd    3/3       3            3      35m     httpd    httpd:2.2.31 app=httpd再次查看Deployment可以看到httpd版本已经回退了。查看revision历史记录,可以看到revision记录也发生了变化。[root@master ~]# kubectl rollout history deployment httpddeployment.extensions/httpd ......
  • [资料专区] 容器编译环境制作脚本(包含特权容器转换非特权容器工具)
    尊敬的合作伙伴:       您好,请从support网站下载最新的《边缘计算二次开发指南》,该脚本同最新的文档一起更新,本帖将不再更新,谢谢。502H:cid:link_0T2:cid:link_1AR-CORE:cid:link_2T1由于开源社区不再维护Debian 8,请使用T2系列的《二次开发指南》制作debian10的32位容器以及app
  • [技术干货] K8S故障排查途径
    这段时间一直困在k8s的深坑里,部署k8s并不困难,但是之后的运行却是反反复复的遇到各种故障。总结一下k8s故障排查的途径:kubectl describe pod/deployment/service 查看pod/deployment/service的基本信息,会有少量的出错信息,找到后用做关键字搜下,就能滤掉一波故障。tailf /var/log/messagesjournalctl -f -u kubelet查看各个组件运行的最新日志,同样,找到报错关键字搜资料。kubectl logs  <pod> -c <contrainer>进入容器查看容器的日志,这个途径有局限,就是pod上的容器必须已经跑起来了,但是大部分故障是跑不起来。kubectl get <pod> -o yaml这条命令,个人理解是把运行的pod生成一个容器。
  • [技术干货] Init Container应用实例
    InitContainers是一种专用的容器,在应用程序容器启动之前运行,可以包括一些应用程序镜像中不存在的实用工具和安装脚本,可以完成应用的必要数据初始化等工作。总的来说就是在正式的容器启动之前做一些准备工作的。挂接的volum/file等等,是容器内外交换信息的工具,而InitContainer可以视为一个在容器胜生成之前的信息灌入的流程。顾名思义,InitContainers用于初始化工作,执行完就结束,为一次性的任务。IniteContainers支持大部分应用容器配置,但不支持健康检查。应用场景:环境检查:例如确保应用容器依赖的服务启动后再启动应用容器初始化配置(给应用容器准备配置文件)示例:部署一个web网站,网站程序没有打到镜像中,而是希望从代码仓库中动态拉取放到应用容器中。root@ecs-beijing1:~# vi pod-initcontainer.yaml              ---apiVersion: v1kind: Podmetadata: name: init-demospec: initContainers:   - name: download     image: busybox     command:       - wget       - "-0"       - "/opt/index.html"       - http://www.ctnrs.com     volumeMounts:       - name: wwwroot         mountPath: "/opt" containers:   - name: nginx     image: nginx     ports:       - containerPort: 80     volumeMounts:       - name: wwwroot         mountPath: /usr/share/nginx/html volumes:  - name: wwwroot    emptyDir: {}"pod-initcontainer.yaml" 28L, 504C written                                                                         root@ecs-beijing1:~# kubectl apply -f pod-initcontainer.yamlpod/init-demo createdroot@ecs-beijing1:~# kubectl get podNAME        READY   STATUS     RESTARTS   AGEinit-demo   0/1     Init:0/1   0          33sroot@ecs-beijing1:~# kubectl exec -it init-demo --bashroot@init-demo:~#cd /usr/share/nginx/html root@init-demo:/usr/share/nginx/html# lsindex.htmlroot@init-demo:/usr/share/nginx/html# cat index.html.....    <script src="/js/jquery.min.js"></script><script src="/js/feather.min.js"></script><script src="/js/fresh.js"></script><script src="/js/jquery.panelslider.min.js"></script><script src="/js/modernizr.min.js"></script>  </body></html>页面已经下载到容器里面了。
  • [指导教程] 跨内网代理部署 TICS Agent
    原作者: FutureCity原文链接:https://bbs.huaweicloud.com/blogs/2669891 业务场景普惠金融是行业热门课题,近几年央行政策支持中小微企业发展(特别是制造业),银行也把该方向作为业务拓展重点。但小微企业的信用评估是一个难点,小微企业一般都没有大额固定资产作授信抵押,银行也缺少高质量的数据作为评价依据,小微企业的贷款普遍存在难度大、周期长、额度低等问题。政府拥有小微企业多维度的数据,如纳税、社保、用水用电等,信用评估价值高,受限于政府网络和数据安全管理要求,政府数据不能直接提供给银行。那么,有没有一种方式,在不共享数据的情况下,实现数据的分析应用,即数据可用不可见。数据隐私计算技术,可用于满足该场景需求,如华为云可信智能计算服务 TICS (Trusted Intelligent Computing Service),提供跨组织数据安全共享方案,政府无须将数据提供给银行,银行基于 TICS 的安全计算环境,运行数据分析模型,获取业务所需的分析结果。2 方案架构以政府和银行小微企业数据共享场景为例,政府数据部署在华为云数据库服务 RDS,银行数据存储在本地数据中心的 Mysql Server,通过边缘节点 IEF Edge Node 接入。TICS 服务同时支持云、边两种数据接入方式,基于华为云边缘服务 IEF 实现 TICS Agent 的远程部署和持续更新。TICS 可信聚合计算通过 TICS AGG 节点实现,AGG 提供基于 TEE 或 SGX 两种硬件隐私计算环境,也支持半同态加密、差分隐私等软件类的隐私计算能力,适用于联邦数据分析(基于标准 SQL)与联邦学习等业务场景。本方案架构设计参考下图:银行本地数据中心接入公网,有 3 种方式,不同方式下 IEF Agent 的接入配置要求说明如下:无网络限制的透明代理( NAT 网关)透明代理的工作方式类似于 NAT 网关,银行内网服务器的数据包默认全部发送给透明代理(作为网关),透明代理再将数据包转发给外网访问地址,内网应用感知不到代理的存在,故称为透明代理。该方式边缘节点的接入配置最简单,只需完成 IEF Agent 的标准配置即可,参考链接 IEF 边缘节点注册与纳管 。带网络限制的透明代理( NAT 网关)该方式下,银行对访问公网有网络限制,需要根据域名 / IP 地址和端口号,开通网络权限。需要放通的网络权限,参考 开通外网访问权限。带网络限制的普通代理和透明代理不同,普通代理是一个独立服务器,内网应用须配置代理访问地址,确保访问外网的数据包先发给代理,再由代理转发外网目的地址。本文介绍的最佳实践配置,主要针对最复杂的第 3 种场景:带网络限制的普通代理,如 squid 上网代理(其他类型的代理配置类似)。普通代理工作在 TCP/IP 协议应用层,代理的配置在应用级别生效,而非操作系统级别,本地服务器中的不同应用程序,均须添加代理配置,这一点尤其要注意。上图名词解释:TICS Service: 华为云 可信智能计算服务 管理节点,提供数据联盟管理、用户权限配置、代理管理等功能TICS AGG: TICS Aggregation Node 可信计算聚合节点,多方数据的融合计算在该节点完成TICS Agent: TICS 代理,提供数据接入管理、安全隐私规则配置、数据分析和联邦学习任务运行等功能,是 TICS 服务业务操作的关键组件,每个 TICS 数据联盟的参与方可拥有 1 个或多个 TICS AgentSWR: 华为云 容器镜像服务 Software Repository for Container,用于 IEF Agent 边缘容器镜像管理IEF Service: 华为云 边缘计算服务 Intelligent Edge Fabric 管理节点,负责边缘节点创建、管理和边缘容器应用同步操作等Edge Node: 部署 IEF Agent 的边缘节点,一般是一台硬件服务器或虚拟机IEF Agent: 部署在 Edge Node 上的边缘节点管理软件,负责与云端 IEF Service 进行通信,管理本地运行的边缘容器实例如 TICS Agent,支持实例更新、状态监控、日志管理等功能CCE: 华为云 云容器引擎 Cloud Container Engine,云上托管的 Kubernetes 集群,在本案例中,用于政务 TICS Agent 代理的部署CCE Node: CCE 节点即 Kubernetes 节点,是云端的一台虚机或裸金属服务器POD: Kubernetes 集群运行计算任务的最小单位,本案例用于部署政府侧的 TICS Agent,是 1 个或多个容器的集合,参考 POD 名词解释RDS: 华为云 托管 Mysql 数据库,本案例用于存储政务共享数据NAT: 网络地址转换网关 Network Address Translation,用于内外网通信转接,内网访问外网的网络流量均重定向到 NAT 网关,再转发给外网目的地址3 前置条件3.1 开通外网访问权限银行本地边缘节点,访问公有云的 IEF 和 TICS 服务,须开通以下网络端口:目的 IP 地址访问域名目的端口用途119.3.227.164ief2-placement.cn-north-4.myhuaweicloud.com443边缘计算 IEF 服务端49.4.115.239ief2-edgeaccess.cn-north-4.myhuaweicloud.com443边缘计算 IEF 连接网关119.3.215.28ief2-telemetry.cn-north-4.myhuaweicloud.com8065/8102/8149边缘计算 IEF 日志与计量端口49.4.112.92ief2-software-north-4.obs.cn-north-4.myhuaweicloud.com443边缘容器镜像存储49.4.112.18swr.cn-north-4.myhuaweicloud.com443容器镜像管理服务接口49.4.112.6tics.cn-north-4.myhuaweicloud.com443TICS 服务端接口49.4.112.113obs.cn-north-4.myhuaweicloud.com443OBS 服务接口139.9.118.165无域名访问地址30001~30016TICS 聚合计算节点 AGG 端口以上网络配置基于华为云北京四 Region,其他 Region IP 地址和域名均不同,须进行相应调整。参考链接 获取 IEF 云端服务 IP 地址3.2 注册华为云账号TICS 服务同一数据联盟参与方可以进行数据共享,数据联盟每个参与方都是华为云租户,因此使用 TICS 服务必须先注册华为云账号。登录 华为云官网 即可完成账号注册。3.3 申请 TICS 服务公测TICS 服务目前处于受邀公测阶段,请登录华为云 TICS 服务 ,点击 “立即体验” 按钮,即可申请公测。公测申请提交后,华为云 TICS 服务管理人员将在约 1~2 天内完成审批。3.4 加入 TICS 服务联盟任何华为云账号均可发起创建 TICS 数据联盟,公测阶段资源有限,建议参与测试的用户优先加入现有数据联盟。用户将华为云账号提供给 TICS 服务管理员(可通过华为云销售获取联系方式),由 TICS 服务管理员将账号加入到数据联盟。华为云账号格式一般为 hwxxxxxxxx (hw 加 8 位数字),登录华为云账号中心即可查看。TICS 服务管理员将账号添加到数据联盟后,用户将在 TICS 服务 “通知管理”模块收到加入数据联盟申请,选择同意即可加入该数据联盟。3.5 准备华为云费用银行采用边缘服务方式接入华为云,涉及一定的华为云费用。边缘节点部署 IEF Agent 是免费的,在 IEF Agent 运行容器实例需要收费,收费标准参考链接 IEF 服务定价。TICS Agent 部署在边缘节点上需要一个容器实例,费用为 1099 ¥/月/实例。用户可自行充值华为云账号完成测试,也可联系华为云销售申请华为云测试券,覆盖测试所需费用。注:完成实名认证的企业账号才能申请测试券,请登录华为云官网 账号中心>实名认证,参考 实名认证操作指南 完成认证。3.6 准备 IEF 边缘节点边缘节点是部署在银行本地数据中心的服务器或虚拟机,支持 X86 和鲲鹏 ARM 架构,推荐配置如下:操作系统:CentOS 7.6硬件配置:cpu >= 8 core,内存 >= 16G环境依赖:docker 18.06.3 版本IEF 边缘节点须具备外网访问权限,和云端互动时,均由边缘节点发起访问,因此边缘节点无需独立公网 IP 地址。更多边缘节点规格要求,参考 配置边缘节点环境 。4 部署 IEF Agent在边缘节点上部署 IEF Agent,须先登录华为云 IEF 服务控制台 ,选择功能模块 边缘资源>边缘节点,点击红色按钮 “注册边缘节点”,根据提示,下载边缘节点安装程序 edge-installer_1.0.0_x86_64.tar.gz 和配置文件 ief-node.tar.gz (ief-node 是节点名称),导入到边缘节点服务器。参考下面配置,在普通代理上网的环境下,完成 IEF Agent 部署和云端纳管。以 sudo 权限登录边缘节点执行如下命令解压软件包到 /opt 文件夹sudo tar -zxvf edge-installer_1.0.0_x86_64.tar.gz -C /opt解压配置文件到 /opt/IEF/Certsudo mkdir -p /opt/IEF/Cert sudo tar -zxvf 边缘节点名称.tar.gz -C /opt/IEF/Cert配置 IEF Agent 外网访问代理vi /opt/IEF/Cert/user_config http_proxy=proxy_ip:proxy_port # proxy_ip 和 proxy_port 请修改为现网的代理 IP 地址和端口号,下同 https_proxy=proxy_ip:proxy_port安装 IEF Agentcd /opt/edge_installer sudo ./installer -op=install验证边缘节点是否纳管成功登录华为云 IEF 服务控制台 边缘资源>边缘节点,查看新建边缘节点的运行状态,“运行中”表示纳管成功。更多相关配置参考 IEF 边缘节点注册与纳管。5 部署 TICS AgentTICS Agent 是部署在 边缘节点上的一个容器实例,登录华为云 TICS 服务控制台,即可发起创建 TICS Agent,华为云 IEF 服务会负责将 TICS Agent 的容器镜像(保存在 SWR 上)同步到边缘节点,完成 TICS Agent 的部署操作。参考下面配置,完成 TICS Agent 在边缘节点上的部署:配置 docker 外网访问代理从云端获取 TICS Agent的容器镜像将执行 docker pull 操作,须配置 docker 的访问代理,否则将导致镜像获取失败。sudo mkdir -p /etc/systemd/system/docker.service.d vi /etc/systemd/system/docker.service.d/http-proxy.conf [Service] Environment="HTTP_PROXY=proxy_ip:proxy_port" # proxy_ip 和 proxy_port 请修改为现网的代理 IP 地址和端口号,下同 Environment="HTTPS_PROXY=proxy_ip:proxy_port" :wq # 保存文件 # 重启 docker sudo systemctl daemon-reload sudo systemctl restart docker获取华为云账号 AK/SK访问密钥 AK/SK Access Key ID/Secret Access Key 包含访问密钥ID(AK)和秘密访问密钥(SK)两部分,是华为云账号的长期身份凭证,TICS Agent 代理部署须配置 AK/SK 信息,授予代理接入权限。AK/SK 登录华为云官网 账号中心>基本信息>管理我的凭证>访问密钥,点击“新增访问密钥”,即可下载访问密钥,文件名为 credentials.csv。详细操作指南参考 访问密钥 。注:访问密钥生成后,只能下载一次,请妥善保管。下载TICS Agent 配置登录华为云控制台 TICS 服务,选择 通知管理>下载代理配置,保存至本地,解压后得到 3 个文件,在下一步创建 TICS Agent 代理中会用到agent.p12 - 联盟配置tics_league_datacloud.json - 代理密钥truststore.jks - CA 证书创建 TICS Agent登录华为云控制台 TICS 服务,选择 代理管理>部署代理,在部署代理页面,依次完成以下操作:导入联盟配置 agent.p12上传文件 代理密钥 tics_league_datacloud.json上传文件 CA 证书 truststore.jks导入当前账号 AK/SK credentials.csv配置代理登录密码,该密码请注意保存,后面和代理登录账号 admin 一起用于代理管理页面的登录选择 IEF 边缘节点部署,纳管节点选择已创建好的 IEF 边缘节点主机路径配置边缘节点上数据保存路径,如 /home/tics,须确保该路径已创建且具备写权限点击 “立即创建” 按钮,完成代理创建操作配置 TICS Agent 外网访问代理TICS Agent 通过 java sdk 与华为云 TICS AGG 进行通信,须配置 java 访问外网的代理配置,确保与 AGG 通信正常。以 sudo 权限登录边缘节点,执行以下命令:docker ps # 查看 docker 容器实例 docker exec -ti xxxx /bin/bash # xxxx 对应 tics 容器实例 id vi /etc/hosts # 配置容器实例内部 TICS 服务域名解析 49.4.112.6 tics.cn-north-4.myhuaweicloud.com hostname # 获取当前主机名,后面配置将用到 vi /opt/cloud/tics/tics-agent-console/bin/common.sh JAVA_OPTS="-Dhttps.proxyHost=proxy_ip -Dhttps.proxyPort=proxy_port -Dhttp.nonProxyHosts=当前主机名" # proxy_ip 和 proxy_port 请修改为现网的代理 IP 地址和端口号,下同 :wq # 重启服务,使配置生效 su service sh stop.sh sh start.sh & vi /opt/cloud/tics/tics-agent-web/bin/common.sh JAVA_OPTS="-Dhttps.proxyHost=proxy_ip -Dhttps.proxyPort=proxy_port -Dhttp.nonProxyHosts=当前主机名" :wq # 重启服务,使配置生效 su service sh stop.sh sh start.sh &验证 TICS Agent 是否部署成功登录华为云控制台 TICS 服务,选择 代理管理,点击代理名进入代理管理页面,点击代理登录地址 “前往代理Agent”,打开代理登录界面,输入步骤 4 中的代理用户名 Admin 与代理登录密码,完成代理登录。登录代理页面后,查看右上角的状态符号,显示为绿色,则表示代理通信正常,代理部署成功。注:边缘节点部署方式下,TICS Agent 代理登录 IP 地址为内网 IP 地址,请确保测试使用的 PC 或笔记本,与 TICS Agent 内网网络连通性。
  • [热门活动] 华为开发者大会2021(Cloud)启幕,杭州电子科技大学分会场精彩纷呈
    4月24日-26日,华为开发者大会2021(Cloud)在全国36座城市、63个线下分会场同步启,旨在汇聚业界大咖、华为科学家、顶级技术专家、天才少年和众多开发者,搭建一个全球性的交流和实践平台,共同探讨和分享最新的ICT技术在行业的深度创新和应用。作为互联网之都,杭州近年来一直在国内数字化、信息化产业中占据着龙头地位,并保持着高速、健康的发展态势,被业内誉为“数字经济第一城”。在杭州的发展过程中,华为一直在不遗余力地通过校企合作等方式添砖加瓦。本次华为开发者大会2021(Cloud)分会场走进了杭州电子科技大学,与高校师生围绕产业创新和鲲鹏生态、技术开源等展开了深入的探讨和学习。会上,杭州电子科技大学校团委副书记杨乐发表讲话。在讲话中杨乐谈到:ICT大大改变了人们的工作、沟通、学习和生活方式。未来,联接、AI、云、计算、行业应用等多种先进技术和机会互相催化、有机融合,必将催生大量的技术创新和应用创新,为社会发展开启了充满想象的广阔前景。杭州电子科技大学将与华为携手,保持对基础研究的持续投入,鼓励自由探索,敢于质疑现有理论,勇于开拓新的方向。鲲鹏展翅,打造5G时代多样化算力底座预计2025年,全球联网的设备数量将突破1000亿,数以ZB计的海量数据,需要被分析、处理。未来十年,是计算体系架构创新的黄金十年,算力需求的不断增长,将推动计算体系架构的创新。计算体系架构创新将主要从从两个方向展开:从通用计算走向通用计算加异构计算的多样性算力创新,和从硬件到基础软件、到应用使能的全栈协同创新。基于这一趋势,2019年,华为向业界正式发布鲲鹏、昇腾计算产业战略,并坚持“硬件开放、软件开源、使能伙伴、发展人才”,开放主板,有序推进与伙伴的整机合作;操作系统openEuler、企业级数据库openGuass、全场景AI计算框架MindSpore全部如期开源,得到伙伴的积极响应和支持。会上,华为向与会成员展示了鲲鹏投资全场景芯片族布局,包含鲲鹏处理器、昇腾AI处理器、智能SSD控制器芯片、智能网卡芯片以及智能管理芯片等。共建生态,把企业级数据库能力带给用户和伙伴会上,在谈到openGauss时,华为布道师张琼指出openGauss是一款高性能、高安全、高可靠的企业级开源关系型数据库(RDBMS),且具备智能运维管理能力。截至目前,该数据库已完成了内部自用、产品化再到云&开源阶段,2021年将专注于生态构建,分享企业级数据库管理能力,促进数据库教育事业发展,引领生态建设。与此同时,华为布道师张琼还就openEuler进行了介绍。作为面向多样性计算的原生开源操作系统,openEuler定位于聚焦内核能力,释放多样化算力,加速行业应用创新。它具备操作系统完整功能集,能够原生自主演进。目前,openEuler已强力参与基础系统开源项目,成为核心成员,做到自维护、自演进,非常适合开发者学习。在此值得一提的是,会上华为布道师张晓雨还就“如何使用iSula生态链进行容器镜像构建和运行”进行了介绍。他指出,iSula 是华为自主研发的通用容器引擎,旨在统一的架构设计来满足 CT 和 IT 领域的不同需求。相比 Golang 编写的 Docker,轻量级容器具有轻、灵、巧、快的特点,不受硬件规格和架构的限制,底噪开销更小,可应用领域更为广泛。此外,他还通过实操向与会学子展示了iSula容器引擎的使用方法和iSula-build容器镜像构建工具的使用方法,帮助高校学子更好的了解到了iSula生态链对于容器镜像构建和运行的作用。作为浙江省首批重点建设的5所高校之一,杭州电子科技大学一贯坚持“以人为本,追求卓越”的育人理念,致力于培养家国情怀、国际视野、创新精神和实践能力的高素质人才。截止2020年7月,杭州电子科技大学已建设国家级人才培养模式创新实验区一个,国家级虚拟仿真实验教学中心一个,国家级实验教学示范中心三个,国家级精品课程两门,先后为国家和社会培养输送了16万余名优秀人才,获得了全国普通高等学校毕业生就业工作先进集体”“全国毕业生就业典型经验高校”等荣誉称号,为培养信息产业人才做出了卓著的贡献。近年来,华为正逐步将其已经成熟的技术进行开源,帮助更多产业开发者快速成长。通过供应链、技术等方面的优化,不断为开发者提供更加的平台。对于产业创新,质量的提升是要求也是衡量标准,全栈智能的创新技术是引擎,而拥有产业视角和创新技术的人才是关键。可以说,随着产业创新浪潮的兴起,产业开发者的时代已经来临,让我们一起,加入产业创新,加速产业创新,成为了不起的开发者!
  • [EI企业智能] 【云小课】EI第16课 ModelArts 使用自定义镜像快速迁移上云-这2种功能,你了解哪些?
    ModelArts为用户提供了多种常见的预置引擎,但是当用户对深度学习引擎、开发库有特殊需求场景的时候,预置AI引擎可能不再满足用户需求。ModelArts底层采用容器技术,您可以自行制作容器镜像上传并在ModelArts上运行。自定义镜像支持自由文本形式的命令行参数和环境变量,灵活性高,便于支持任意计算引擎的作业启动需求。当前ModelArts自定义镜像功能支持以下两种场景:创建训练作业导入模型让我们看看如何在ModelArts中使用自定义镜像创建训练作业和导入模型吧!关联服务介绍使用自定义镜像功能可能涉及以下云服务:容器镜像服务、对象存储服务、弹性云服务器。容器镜像服务:容器镜像服务(Software Repository for Container,SWR)是一种支持镜像全生命周期管理的服务, 提供简单易用、安全可靠的镜像管理功能,帮助您快速部署容器化服务。您可以通过界面、社区CLI和原生API上传、下载和管理容器镜像。ModelArts训练和导入模型使用的自定义镜像需要从SWR服务管理列表获取。您制作的自定义镜像需要上传至SWR服务。对象存储服务:对象存储服务(Object Storage Service,OBS)是一个基于对象的海量存储服务,为客户提供海量、安全、高可靠、低成本的数据存储能力。在创建训练作业和导入模型时往往存在数据交互,您需要的云上数据可以存储至OBS服务。弹性云服务器:弹性云服务器(Elastic Cloud Server,ECS)是由CPU、内存、操作系统、云硬盘组成的基础的计算组件。弹性云服务器创建成功后,您就可以像使用自己的本地PC或物理服务器一样,在云上使用弹性云服务器。在制作自定义镜像时,您可以在本地环境或者ECS上完成自定义镜像制作。在您使用自定义镜像功能时,ModelArts可能需要访问您的容器镜像服务SWR、对象存储服务OBS等依赖服务,若没有授权,这些功能将不能正常使用。建议您使用委托授权功能,将依赖服务操作权限委托给ModelArts服务,让ModelArts以您的身份使用依赖服务,代替您进行一些资源操作。详细操作参见使用委托授权。使用自定义镜像创建训练作业端到端样例可参考最佳实践-使用自定义镜像创建训练作业~1.准备工作完成访问授权的配置,详细操作参见使用委托授权。已在OBS服务中创建桶和文件夹,用于存放样例数据集以及训练代码。2.制作自定义镜像,您可以使用ECS或者应用本地已有的主机进行自定义镜像的制作。    在制作镜像用时,需满足ModelArts定义的规范。自定义镜像中不能包含恶意代码。基础镜像中的部分内容不能改变,包括“/bin”、“/sbin”、“/usr”、“/lib(64)”下的所有文件,“/etc”下的部分重要配置文件,以及“$HOME”下的ModelArts小工具。不可以新增属主为“root”且权限包含“setuid”或“setgid”位的文件。自定义镜像大小不能超过5GB。日志文件输出,为保证日志内容可以正常显示,日志信息需要打印到标准输出。     ModelArts还提供基础镜像用于自定义镜像的制作。基础镜像中有一些必要的工具,帮助用户快速实现代码下载、训练日志输出、上传日志文件至OBS等功能。3.上传镜像至SWR服务。上传镜像的详细操作可参考SWR用户指南。4.使用自定义镜像创建训练作业。使用自定义镜像导入模型端到端示例请参考使用自定义镜像导入模型~1.准备工作完成访问授权的配置,详细操作参见使用委托授权。已在OBS服务中创建桶和文件夹,用于存放数据以及相关文件。2.制作自定义镜像    在制作镜像用时,需满足ModelArts定义的规范。自定义镜像中不能包含恶意代码。自定义镜像大小不超过30GB。镜像对外接口         镜像的对外服务接口需要为8080,推理接口需与config.json文件中apis定义的url一致,当镜像启动时可以直接访问。健康检查接口         自定义镜像需要提供健康检查接口供ModelArts调用,在config.json文件中配置,参见模型配置文件编写说明。日志文件输出        为保证日志内容可以正常显示,日志信息需要打印到标准输出。镜像启动入口        如果需要部署批量服务,镜像的启动入口文件需要为“/home/run.sh”,采用CMD设置默认启动路径。镜像依赖组件        如果需要部署批量服务,镜像内需要安装python、jre/jdk、zip等组件包。3.上传镜像至SWR服务。上传镜像的详细操作可参考SWR用户指南。4.选择从容器镜像导入模型,可参考从容器镜像中选择元模型。5.将模型部署为在线服务。
  • [中间件课堂] 对新手的初级入门,什么是中间件。
    为什么写?1.很多人听过中间件,但是没见过中间件,或者根本不知道中间件是什么,傻X百科上面的定义实在是模糊,所以就有了写这片博客的冲动。定义:中间件,顾名思义存在于两个系统之间的,起到连接的设备。(1)为什么是设备? 硬件和软件在一定程度上可以互用,中间件既可以是硬件,也可以是软件,所以我说是设备,而不定义为,硬件或者软件的一种。(2)起到连接作用怎么理解?中间件可以在两个软件之间起到连接(iis服务)。可以在客户机/服务系统之间起到功能(例如web代理服务器)。2.中间件的作用:(1)一个定义:在操作系统中所有的软件,硬件,固件都可以看作文件。文件有时会具有不同的格式,表现在应用上显示为拥有不同的api接口。①中间件的第一个功能:平衡api接口,使不同的应用通过中间件能够互联。(2)统一化接口后,中间件就表现为能够在不同的接口无限制的传输数据。①中间件第二个功能:负载均衡。软件可能直接相连,也可能通过网络相连,在数据量大的时候就会产生拥塞,但是通过中间件,好像拥塞消失了。(3)搭建iis服务的时候我们可以看到,创建网站的时候,直接点击就能创建一个网站。Iis服务已经为我们做好了一切的统筹工作,而我们只需要操作就好了。①中间件的第三个功能,提供容器。为一种或者多种应用程序提供服务功能。3.中间件的特性:(1)易用性。①一般中间件为软件易于控制,易于复制,在计算机上点击,或者在命令行加载就能够使用(2)位置透明性①中间件起到的是协调的作用,故在使用的时候我们仿佛看不到中间件的存在。(3)消息传输完整性①起到容器,作用和负载均衡作用的时候,要确保的就是消息传输的完整性,如果一个消息通过你的中间件,本质改变了。那么就没有意义了。1)小提示:数据和信息。数据是承载信息的,信息是数据的抽象,世间万物都可以变成数据,破坏数据的结构就会毁坏信息。4.中间件,容器,服务器:(1)客户端--------网络---------服务器---------中间件-------数据库(2)客户端在访问的时候,如果访问静态网页就直接和服务器操作,{例如get(获取数据),post,head,opting,put,delete,trace,connect。服务器返回信息,1**(收到,继续执行),2**(成功,操作成功处理),3**(重定向,页面不在这里)4**(客户端错误),5**(服务器错误),}客户端直接和服务器作用,而不经过中间件和数据库作用。(3)客户端访问动态网页,例如php之类的网页,客户端和服务器作用完,服务器和数据库作用,中间就用到中间件。(4)中间件,包含容器(例子windowns上面的iis服务)(5)有的时候,中间件和服务器是架构在一起的(透明性)。
  • [技术干货] c++stl
    lower_bound,upper_bound和equal_range函数初识    lower_bound.(k)    返回一个迭代器,指向第一个值不小于k的元素upper_bound(k)    返回一个迭代器,指向第一个值大于k的元素equal_range(k)    返回一个迭代器pair,表示值等于k的元素的范围。若k不存在,pair两个成员均等于end()–尾迭代器    上面三个函数多用于容器中使用,但是对于普通的数组也是可以使用的,下面会讲到.    如果所查找值在容器中,lower_bound返回的迭代器将指向第一个具有给定值的元素,而upper_bound返回的迭代器指向最后一个匹配给定值的元素之后的位置。    如果元素不在容器中,则lower_bound和upper_bound会返回相等的迭代器----指向一个不影响排序的值插入位置    因此,用相同的值调用lower_bound和upper_bound会得到一个迭代器的范围,表示具有该关键字的元素范围。    当然,这两个操作返回的迭代器可能是容器的尾后迭代器。如果我们查找的元素具有容器中最大值,则此关键字的upper_bound返回尾后迭代器。如果关键字不存在,且大于容器中任何关键字,则lower_bound返回的也是尾后迭代器.
  • STL deque容器
    STL中的容器:deque容器的常用接口及用法:deque:它被称作双端数组,可以在头部和尾部插入或删除数据;deque 容器和 vector 容器的区别:1.vector 容器对头部插入、删除数据的效率较低,因为 vector 容器是单端数组,若要从头部插入或删除,得把后面的数据都往后挪或往前挪,因此数据量越大,则其时间效率越低;2.deque 容器相对 vector 容器而言,它对于头部插入数据或头部删除数据的效率就高多了,这与它的内部实现相关;3.vector 容器访问单个数据的效率要高于 deque 容器,原因也是与 deque 容器的内部实现有关;图片转自于黑马程序员,是在学习的过程中截图下来的deque 容器内部工作原理:1.deque 内部有个中控器,它维护着每段缓冲区中的内容,而缓冲区里面放着真实的数据;2.中控器维护的其实是缓冲区的地址,使得使用 deque 容器时像一段连续的内存空间;3.缓冲区的头和尾是没有插满数据的,因此可以继续添加。添加满后,则会开辟一块新的缓冲区,中控器则记录下新的缓冲区的地址;4.由于中控器维护的是地址,因此当我们访问单个元素时,内部的实现是从地址再转到缓冲区,这里的时间效率就低于 vector 容器了;
  • 云实验容器部署nginx体验
    云实验增加了许多新实验,HDC大会圆满闭幕,终于有时间做实验啦~因为最近做了很多docker和k8s的功课,想着先复习下容器的实验。可能因为上次做完了还剩20多分钟的时间,所以这次进来发现因为密钥配额的原因,实验不能进行下去,只能把实验的时间耗完然后,明天再来!
  • [认证交流] 【我与华为云认证】微认证之轻松玩转Kubernetes
    Kubernetes作为容器编排工具,简化容器管理,提升工作效率而颇受青睐,我们可以借助云容器引擎CCE平台快速搭建 Kubernetes环境,轻松玩转 Kubernetes。什么是容器?容器为Ap提供独立的、受控的运行环境,是_种轻量级的操作系统虚拟Concept for create environment for software, without disturbing the rest of the core operating system running job filesystem简单的容器: SandBox(沙盒、沙箱)Kubernetes-大海航行的舵手K8s集群主要包括两个部分: Master节点(管理节点)和Node节点(计算节点)Master节点主要还是负责管理和控制。Node节点是工作负载节点,里面是具体的容器。Master节点Master节点提供的集群控制,对集群做出全局性决策,例如调度等。通常在 master节点上不运行用户容器。Master节点包括AP| Server、 Scheduler、 Controller manager、etcdAPI Server:整个系统的对外接囗Scheduler:集群内部的资源进行调度Controller Manager:负责管理控制器etd: Kubernetes的后端存储Node节点节点组件运行在每一个Node节点上,维护运行的pod并提供 kubernetes运行时环境。Node节点包括Pod、 Docker、 kubelet、kube-proy、 Fluent、kube-dns(可选)Pod: Kubernetes最基本的操作单元;Docker:创建容器;Kubelet:负责监视指派到它所在Node上的Pod,包括创建、修改、监控、删除等Kube-proxy:负责为Pod对象提供代理  Fluent:主要负责日志收集、存储与查询。Kubernetes最小管理单元-PoDPod是 Kubernetes管理的最小基础单元。一个Pod中封装了:一个或多个紧耦合的应用容器,存储资源,独立的IP,容器运行的选项相同Pod中的任何容器都将其享相同的名称空间和本地网络。容器可以很容易地与其他容器在相同的容器中进行通信。有状态应用和无状态应用无状态应用有状态的服务,从部署开始,这些容器就开始与上游镜像不同了,时间越长它们的差异越大,每个运行的应用程序都至少有一个小状态,(差异),但对于“无状态”应用程序来说,状态(差异)很小,而目可以进行快速替换有状态应用无状态服务,易于部署且易于扩展。如果流量上升,则只需添加更多的负载平衡上游容器镜像和基础架构中正在运行的容器其实几乎没有区别;可以随时被替代,而且容器实例切换过程中几乎不需要耗费“切换成本
  • [云计算周刊] 调整云计算资源大小时要避免的10个错误
    转载自 云计算D1net 原创 Anna Anisienia组织在将业务迁移到云平台时,遇到的最常见的问题之一是成本。采用云计算,组织可以将IT成本从资本支出(硬件设备和软件许可的长期投资)转换为运营支出,因此选择正确的云服务并进行正确估算至关重要。以下将探讨在调整云计算资源大小时常见的错误和陷阱,并讨论如何避免,从而真正受益于云计算的弹性。01 遵循提升和转移方法提升和转移方法意味着组织可以将工作负载的副本移动到云平台中,而只需进行少量的更改。即使组织只将部署业务快速迁移到云平台中,这种模式也很有用,但它可能导致资源使用不足。AWS公司承认,通过创建服务来简化迁移(CloudEndure迁移和AWS服务器迁移服务)是一个困难的问题。不过,为了获得更好的资源利用率,组织最好考虑重新构建云计算解决方案。组织采用提升和转移方法,从长远来看可能会支付更多的成本,也可能会错过云计算提供商提供的许多好处。例如,当选择完全管理的AWS Aurora而不是传统的Postgres实例时,组织可以获得高达三倍的吞吐量、存储自动扩展和低延迟读取副本。这可能是Aurora成为目前最受欢迎和发展最快的AWS云服务之一的原因。02 不标记资源如果组织没有足够的数据来做出明智的决定,则很难改进。如果无法跟踪云计算资源的性能以及它们产生的成本,那么就很难优化其利用率。最好的做法是根据项目或组织单位标记资源,以将成本正确分配给相应的服务。03 未能随着时间的推移监控资源使用情况管理云计算结构并不是一次性的过程。这是监视和评估组织使用的内容、使用方式以及原因的持续实践。也许组织最初对特定应用程序的增长的假设并不完全正确,而进行更改可能会显著地降低成本。例如一个过度配置的Kubernetes集群,它的节点比需要的多很多。在这种情况下,也许转向无服务器版本(Fargate上的EKS)更有意义。保持“僵尸”资源不受监控的情况并没有人们想象的那么普遍。在规模较大的组织中,可能会发生某些项目由于不完整的移交过程而被放弃并且相应的资源保持活动状态的情况。04 总是自己做所有的事情软件工程师有时可能会自己构建定制的解决方案和服务。一种可能更好的方法是首先对现有资源进行适当的研究。例如:也许不需要在EC2上使用自托管数据库,而是使用完全托管的RDS,这可以帮助更轻松地扩展和操作实例。也许不需要这个自我管理的RabbitMQ实例,而是可以使用经过实践检验的无服务器消息队列SQS。通常情况下,如果有一个无服务器或完全托管的解决方案,那么至少在为自己的解决方案投入过多的时间和精力以进行维护之前,先考虑采用这些方案是有意义的。05 只使用自己熟悉的工具在阅读Reddit或博客的一些文章时,经常看到许多工程师不愿意使用无服务器或容器编排平台,因为他们只知道EC2和人工管理的服务器。他们认为有些新技术可能只是昙花一现,因此没有必要改变自己的方式。这意味着转移到容器编排平台、无服务器和其他云服务是没有价值的。这似乎是一种谨慎的方法。最好挑战一下这种假设,用清楚的事实、成本和性能基准来判断新技术的可用性,而不是对新技术持怀疑态度。06 没有使用无服务器和容器编排平台如果要为所管理的每个服务和工具创建一个EC2实例,则可能会陷入维护的噩梦。但是,如果将每个服务部署到Kubernetes(EKS)或Fargate(ECS)集群的容器中,那么由于容器的动态端口映射和更紧凑的资源利用(例如共享层),可以将更多的资源分配到单个服务器实例中。容器编排平台将帮助你确保实例之间的负载平衡,并使工作负载保持健康。这在某种程度上消除了猜测容量的情况。你可以指定在任何时候应该运行多少个容器实例,并且控制平台将确保它发生,就像你定义的那样。如果可以轻松地在许多容器或无服务器资源之间实现负载平衡,那么不必再猜测哪种EC2或RDS实例大小适合自己的用例。07 不考虑总拥有成本如果只考虑硬件或服务成本,你可能最终会认为许多资源在内部部署设施中运行可能更具成本效益。但是,如果加上额外的维护、升级和员工管理这些服务器的成本,那么情况就完全不同了。08 没有长远的思考如果只根据当前情况扩展资源,则可能无法考虑到未来需求的变化。如果组织的业务和数据增长更好怎么办?如果结果正好相反呢?你的应用程序仍然易于更改,并适应未知的未来情况吗?最后,你是否能够找到并保留足够的员工以长期满足这些需求?09 过度配置“以防万一”如果你要保证万无一失,可能会过度配置所有东西,以确保为应对使用高峰期做好准备。如果你可以根据过去的使用模式来证明过度配置的合理性,则这是一个很好的策略。但是,如果是出于直觉,这样做可能是一个错误的策略。从某种意义上说,云服务可以提供弹性,你可以在集群中添加节点,在更多容器之间负载均衡工作负载,或者在需要时增加CPU数量或内存。如果配置和监视正确,则无需过多配置。这并不是说正确调整大小很容易,但是有了良好的流程和自动化,这是可行的,并且可以显著节省成本,尤其是在大规模运行大量资源时。10 选择错误的数据存储有时,瓶颈不是计算资源不足,而是数据存储选择不当。最好考虑一下:你是否需要丰富的查询语言(SQL),还是应用程序只需简单的键值存储即可(例如DynamoDB)。首先是否需要数据库,也许一个简单的S3数据转储就足够了。它自然取决于用例,但是数据库通常是构成任何可扩展架构的主要瓶颈。如何解决云计算资源大小问题?提高云计算资源利用率的一种可能的解决方案是采用自动化技术。例如,你可以使用Dashbird跟踪资源不足和资源过剩的情况,并获得有关它们的通知。使用结构良好的lens仪表板时,可以发现,具有EC2实例类型的ECS集群在过去一小时内的CPU利用率超过90%。然后,可以深入到特定的时间间隔,并进一步检查出现这一使用峰值的原因。同时,另一种容器服务可能会被超额配置,可能会浪费成本。有了这些信息,你可以根据实际使用模式优化资源配置。结论以上研究了调整云计算资源大小时的常见问题,并讨论了如何避免这些问题,并真正从云计算的弹性中受益。通过使用容器编排平台、无服务器和完全托管的解决方案,以及随着时间的推移持续监视使用模式,可以优化云计算架构的性能和成本。(来源:企业网D1Net)
  • [技术干货] HTML 拖拉功能的实现代码(下)
    12345678910111213141516171819202122232425262728293031323334353637383940<!-- 父组件代码片段 vue 文件版 --> <template>  <div    ref="father"    style"width: 100%, height: 100%"  >    <ChildComponents      v-for="(item, index) in playList"      :key="index"      :ref="index"      :visible="true"      :z-index="index"      :back-value="backValue"      :info="item"      :close="close"      :width="600"      :height="400"    />  </div></template><script>export default {  components: {    VideoPlayerModal  },  props: {    playList: {      type: Array,      required: true    }  },  methods: {    backValue (left, top, zIndex) {      this.$refs[zIndex][0].$el.style.top = `${top}px`      this.$refs[zIndex][0].$el.style.left = `${left}px`    }  }}</script>设置子组件的围栏范围这个功能只需要在 onmousemove 事件中进行判断 子容器的 top 和 left 是否超出浏览器的可视范围12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061/** 1. this.width 数据为父组件传递进来的 width 值,或者子组件本身设置的默认值* 2. this.height 数据为父组件传递进来的 height 值,或者子组件本身设置的默认值*/ move (e) {  // 判断 flag 是否允许移动  if (!this.moveFlag) return   // 判断是否超出左边视图      if (this.$refs.fatherBox.offsetLeft < this.width / 2) {        // 禁止弹框移动        this.moveFlag = false        // 设置弹框左边位置        this.left = this.width / 2 + 10        // 调用回调函数把偏移量暴露给父组件        this.backValue(this.left, this.top, this.zIndex)        return      }       // 判断是否超出右边视图      if (this.$refs.fatherBox.offsetLeft > document.body.clientWidth - this.width / 2) {        // 禁止弹框移动        this.moveFlag = false        // 设置弹框右边位置        this.left = document.body.clientWidth - this.width / 2 - 10        // 调用回调函数把偏移量暴露给父组件        this.backValue(this.left, this.top, this.zIndex)        return      }       // 判断是否超出顶部视图      if (this.$refs.fatherBox.offsetTop < this.height / 2 + 70) {        // 禁止弹框移动        this.moveFlag = false        // 设置弹框顶部位置        this.top = this.height / 2 + 70 + 10        // 调用回调函数把偏移量暴露给父组件        this.backValue(this.left, this.top, this.zIndex)        return      }       // 判断是否超出底部视图      if (this.$refs.fatherBox.offsetTop > document.body.clientHeight - this.height / 2 - 50) {        // 禁止弹框移动        this.moveFlag = false        // 设置弹框底部位置        this.top = document.body.clientHeight - this.height / 2 - 50 - 10        // 调用回调函数把偏移量暴露给父组件        this.backValue(this.left, this.top, this.zIndex)        return      }       // 设置弹框左边位置      this.left = e.clientX - this.startLeft      // 设置弹框右边位置      this.top = e.clientY - this.startTop       // 调用回调函数把偏移量暴露给父组件      this.backValue(this.left, this.top, this.zIndex)}子组件还要设置一个当鼠标超出子容器时的 onmouseout 事件,用来防止不可预期的 bug 问题123mouseOut (e) {  this.moveFlag = false}
总条数:888 到第
上滑加载中