精华内容
下载资源
问答
  • Nocalhost Nocalhost是云原生开发环境。 检查https://nocalhost.dev以获取更多详细信息。 术语“ Nocalhost”源自No loc Nocalhost Nocalhost是云本机开发环境。 检查https://nocalhost.dev以获取更多详细信息。 ...
  • 便利 方便的Docker镜像,用于在云原生环境下进行调试和检查
  • 一张图理解Flutter中Dart与原生环境通信 Flutter中提供了Dart与原生环境通信的机制Platform Channels。通过该机制可以扩展Flutter,实现调用原生系统Api的能力。官方介绍图如下: [外链图片转存失败(img-oseSHSo7-...

    一张图理解Flutter中Dart与原生环境通信

    Flutter中提供了Dart与原生环境通信的机制Platform Channels。通过该机制可以扩展Flutter,实现调用原生系统Api的能力。官方介绍图如下:

    那么Flutter是怎么实现这套机制的?在设计这套机制时有哪些值得关注的重点?
    这里以Android为例,以一张图解释整个通信流程。
    废话不多说,先上图:

    其中Java与Dart两个语言环境通过C++层做消息中转。Java与C++通信的技术叫做JNI,Dart与C++的通信与JNI类似,可以叫做NativeBinding。

    在设计整个机制时,需要注意一下几点。

    编码与解码

    由于不同语言中的数据类型是不同的,所以在数据传递过程中,需要将其转换成大家都能理解的数据类型。Flutter中支持的数据类型对应关系如下:

    DartAndroidiOS
    nullnullnil (NSNull when nested)
    booljava.lang.BooleanNSNumber numberWithBool:
    intjava.lang.IntegerNSNumber numberWithInt:
    int, if 32 bits not enoughjava.lang.LongNSNumber numberWithLong:
    doublejava.lang.DoubleNSNumber numberWithDouble:
    Stringjava.lang.StringNSString
    Uint8Listbyte[]FlutterStandardTypedData typedDataWithBytes:
    Int32Listint[]FlutterStandardTypedData typedDataWithInt32:
    Int64Listlong[]FlutterStandardTypedData typedDataWithInt64:
    Float64Listdouble[]FlutterStandardTypedData typedDataWithFloat64:
    Listjava.util.ArrayListNSArray
    Mapjava.util.HashMapNSDictionary

    Android环境的编解码是由MessageCodec接口定义的:

    package io.flutter.plugin.common;
    
    public interface MessageCodec<T> {
        @Nullable
        ByteBuffer encodeMessage(@Nullable T var1);
    
        @Nullable
        T decodeMessage(@Nullable ByteBuffer var1);
    }
    

    为了实现不同语言的数据类型对应与转换,需要寻找一种大家都认识的数据类型,也就是计算机世界的最基本的数据类型—byte字节。
    所以Flutter中的标准编解码器,将不同的数据类型高效的编码成字节序列。下面以编解码一个int类型为例做说明:

    int编码

    //字节数组输出流
    ByteArrayOutputStream stream;
    //Int类型标识
    private static final byte INT = 3;
    
    //先写入int类型标识,表明接下来的四个字节要组成一个int整型。
    stream.write(3);
    
    protected static final void writeInt(ByteArrayOutputStream stream, int value) {
    //依次写入int低8位
    //这次要区分系统平台的字节序,分为大端序和小端序
       if (LITTLE_ENDIAN) {
           stream.write(value);
           stream.write(value >>> 8);
           stream.write(value >>> 16);
           stream.write(value >>> 24);
       } else {
           stream.write(value >>> 24);
           stream.write(value >>> 16);
           stream.write(value >>> 8);
           stream.write(value);
       }
    }
    

    int解码

    protected final Object readValue(ByteBuffer buffer) {
       if (!buffer.hasRemaining()) {
           throw new IllegalArgumentException("Message corrupted");
       } else {
           //先读取一个字节,判断是什么类型的数据
           byte type = buffer.get();
           return this.readValueOfType(type, buffer);
       }
    }
    
    protected Object readValueOfType(byte type, ByteBuffer buffer) {
        //如果是int整型数据,则一次性读取四个字节,然后返回一个int整型
        case 3:
           result = buffer.getInt();
           break;
    }
    

    通过上面的编码,就可以将Java层中的数据传递给C++层,C++层转发给Dart后,Dart层在按照相同的规则解码成Dart语言中对应的数据类型。

    除了标准的编解码方式StandardMethodCodec,Flutter还提供了其他三种方式:

    • BinaryCodec
    • StringCodec
    • JSONMessageCodec

    BinaryCodec 用于直接传输字节数组,没有做任何操作

    StandardMethodCodec 用于PlatformViewsChannel

    StringCodec用于字符串和字节数组的转换,例如Flutter中生命周期渠道LifecycleChannel、

    JSONMessageCodec用于大部分场景,如键盘事件KeyEventChannel、页面导航事件NavigationChannel、平台事件PlatformChannel、文本编辑事件TextInputChannel等

    返回值回调

    从发送端到目的端的一次通信过程很简单,但是如果发送端需要获得目的端的响应结果,类似于一个有返回值的方法调用,那么这个返回值如何正确的响应给发送端?
    下面看一下Flutter中的做法:

    package io.flutter.embedding.engine.dart;
    
    class DartMessenger implements BinaryMessenger, PlatformMessageHandler {
        private final Map<Integer, BinaryReply> pendingReplies;
        private int nextReplyId = 1;
        
        // 当发送消息时,可以指定BinaryReply类型的回调
       public void send(@NonNull String channel, @Nullable ByteBuffer message, @Nullable BinaryReply callback) {
           Log.v("DartMessenger", "Sending message with callback over channel '" + channel + "'");
           // 为callback生成唯一标识,存储到Map容器pendingReplies中
           int replyId = 0;
           if (callback != null) {
               replyId = this.nextReplyId++;
               this.pendingReplies.put(replyId, callback);
           }
        
           if (message == null) {
               this.flutterJNI.dispatchEmptyPlatformMessage(channel, replyId);
           } else {
               this.flutterJNI.dispatchPlatformMessage(channel, message, message.position(), replyId);
           }
        
        }
        
        //消息处理完成后,根据回调标识replyId从Map容器pendingReplies中取出对应回调BinaryReply实例并执行
       public void handlePlatformMessageResponse(int replyId, @Nullable byte[] reply) {
           Log.v("DartMessenger", "Received message reply from Dart.");
           BinaryReply callback = (BinaryReply)this.pendingReplies.remove(replyId);
           if (callback != null) {
               try {
                   Log.v("DartMessenger", "Invoking registered callback for reply from Dart.");
                   callback.reply(reply == null ? null : ByteBuffer.wrap(reply));
               } catch (Exception var5) {
                   Log.e("DartMessenger", "Uncaught exception in binary message reply handler", var5);
               }
           }
        
        }
    }
    

    通过上面源码分析可以知道,当需要返回值时需要传出一个回调callback实例,但是这个callback实例不会随着消息传递给Dart层,而是生成一个整型标识与之对应。通过传递这个整型标识来决定由哪个回调来处理返回值。

    区分不同的应用场景

    通过前面的编解码部分,我们了解了Flutter中提供了四种编解码方式,这四种编解码方式提供了对不同数据类型处理的能力,包含基础数据类型、String、JSON、字节数组,他们应用在了不同的通信渠道场景中。
    那么所有的通信渠道场景都是基于三种基础通信渠道衍生出来的。

    • BasicMessageChannel
    • EventChannel
    • MethodChannel

    这三种通信模式不关心具体编解码方式,而是依据特定的使用场景添加了额外的操作功能。

    BasicMessageChannel

    用于使用基本的异步消息传递与Flutter应用程序通信的命名通道。

    @UiThread
    public void send(@Nullable T message, @Nullable BasicMessageChannel.Reply<T> callback) {
       this.messenger.send(this.name, this.codec.encodeMessage(message), callback == null ? null : new BasicMessageChannel.IncomingReplyHandler(callback));
    }
    

    这种通信方式实现了最基本的信息发送和接收,只是添加了一步编解码操作。

    EventChannel

    用于和平台插件以事件流方式通信的命名通道。例如监听手机电量、GPS位置等,需要原生系统不停的向Flutter应用发送变化后的数据。

    既然是事件流,就必须提供连个操作接口:
    添加监听
    取消监听

    如下代码所示:

    public interface StreamHandler {
       void onListen(Object var1, EventChannel.EventSink var2);
    
       void onCancel(Object var1);
    }
    

    当Dart层需要对某个EventChannel的事件流发起监听时,需要调用listen方法,对应到StreamHandler的onListen。当有新的事件发生时,通过EventSink将消息封装好后,传递给Dart层的事件接口函数_onEvent,该函数名是固定的。

    当Dart层不再需要接受新的事件时,需要调用cancel方法,对应StreamHandler的onCancel。之后原生平台就不会发送新事件,并且释放本地的资源。

    MethodChannel

    用于和平台插件进行异步方法调用通信的命名管道。

    @UiThread
    public void invokeMethod(String method, @Nullable Object arguments, MethodChannel.Result callback) {
       this.messenger.send(this.name,
        this.codec.encodeMethodCall(new MethodCall(method, arguments)), 
       callback == null ? null : new MethodChannel.IncomingResultHandler(callback));
    }
    

    MethodChannel对外提供了invokeMethod方法,可以指定方法名称、参数、返回值回调,整个数据流转流程和我们在一开始给出的图中是一样的。
    其内部实现就是把所有东西封装成一个消息。

    总结

    通过对Flutter中PlatformChannel源码的梳理可以知道,Flutter中跨语言通信的原理就是将需要传递的内容编码成字节数组通过C++层传递到Dart层。各个层对应的数据类型分别是ByteBuffer(Java) -> uint8_t*(C++) -> ByteData(Dart)。
    同时,为了方便开发者使用,还针对不同的使用场景做了封装,如方法调用MethodChannel、事件流EventChannel。

    展开全文
  • 被H5逐渐侵蚀的app原生环境

    千次阅读 2016-03-18 15:39:23
    在这个市场大环境下,浪里淘沙的不单单是商业模式、产品定义,技术格局也在以飓风的速度在迭代更新,本来已经日新月异的技术,配合着各式各样产品的出现有着更加惊人的变化。而app和H5的大战,也早在几年前就已经...

     

           在这个app横飞的年代,对于整个产品研发团队来讲,高速的迭代,爆炸式的功能追加已经成为了互联网行业的时代标签,以小时甚至分钟为单位的进度度量成为了常态。在这个市场大环境下,浪里淘沙的不单单是商业模式、产品定义,技术格局也在以飓风的速度在迭代更新,本来已经日新月异的技术,配合着各式各样产品的出现发生了更加惊人的变化。而appH5的大战,也早在几年前就已经悄悄拉开帷幕。

    竞争现状
    说起app和H5的现状,要从2个方面进行阐述:
    1、app应用与H5应用之争
           app应用也就是我们常说的ios、android两大体系(其他系统占比太少不做考虑),这类应用都比较重功能全面交互流畅
           H5应用的主要体现在我们的社交类工具中,只需要有一个简单的浏览器引擎就可以运行,这类应用都非常轻量级功能单一,通过微信等平台传播很快
    2、app应用内部的原生与H5占比之争
           现在的大部分app应用中,已经充斥着占比很高的H5页面或者元素,致使app只是作为一个功能展示框架。从目前主流非工具类、非大型游戏的app应用来看,使用硬件机能部分、常年不变且使用率很高的部分会使用原生app,其他功能几乎都是清一色H5实现,而这种变化对于普通用户来说基本是无感知的

    原生app劣势:
    1、ios迭代周期严重受限
           挡在ios原生app面前最最重要的一个壁垒,就是苹果公司的审核,平均每个版本审核1周,每年只有寥寥数次的快速审核,即便是快速审核也需要3-4天左右的时间才能够发布。加之In House版的推广限制,app store已经成为了团队谈之色变的怪物。让我们这种上午需求下午上线的团队几乎没有办法进行推进。
           每一个原生app改动都要提前若干天进行部署,还需要考虑之后若干个月可能的变更,不单单是成本激增风险更大,更重要的是:互联网时代的产品比拼如果技术成为了瓶颈,那这个产品必将寸步难行
    2、android兼容性差
           android虽然没有像ios那样的审核周期,但所换来的却是千差万别的兼容性问题,每一个android开发和qa手上没有5个以上的真机,都不好意思说自己接触过android。每一个android开发的内心深处,多多少少都对某些老爷机有说不出的怨念,经常会想,我为什么不去搞ios!
    3、用户使用成本高,导致拉新困难
           这一条是针对app应用的劣势,想让一个用户下载并使用一个app,要远比让他从微信中授权使用一个网页应用难的多,导致了各种地推活动的奖品越来越好效果越来越差事实。
    4、开发成本高
           首先你要有一批ios开发,再加一批android开发,然后分别配置一批qa,即便单人的薪资已经有所回落,但app团队的成本永远是整个团队里最高的之一。单单是兼容老版就要花去不少人工成本。

    H5优势:
    1、迭代速度快
           相比ios的迭代速度,H5简直就是即时响应,随时变更随时上线。用户可以在毫无感知的情况下获取到最新的变化。照片红包上线与下线只是瞬息之间,我甚至没有来得及ps我的玉照就已经被下线了。
    2、兼容性强
           H5的兼容性只体现在屏幕的大小部分极特殊机型上,即便出现兼容性问题也仅仅是展示上的略微差异。相比android的夸张测试范围,H5可以说并不存在兼容性的问题。
    3、传播途径广、用户使用成本低
           H5在营销运行方面的优势太多,以至于我只能把他们归结为这一条。通过各种社交产品的病毒式扩散,用户只需简单的打开链接即可达到我们的宣传推广目的。
    4、开发成本低
           H5团队可以直接从pc前端团队演变过来,甚至后端开发兼职H5的例子并不是没有。总结起来就是:学得快用人少测试乐的呱呱叫

    app相比H5的优势:
    相比app的劣势,app的优势显得十分单薄
    1、交互效果好,响应速度快
           页游客户端游戏的区别。目前对于追求产品极致体验但苦于H5无法满足的情况,原生app也是一种退路。
    2、机能操作必不可少
           对于硬件机能的操作,app有其不可替代性,比如相机和touch等功能。
    3、用户黏度高
           对于app应用来说,一旦拉新成功,只要产品对他有价值,一般不会轻易弃用。但H5,链接一关,刚才干什么就已经忘记了。

    未来:
    说完了app和H5的对比后,让我们来预测一下未来的事,还是从那两个方面进行讨论。
    1、app应用与H5应用
           工具类、大型游戏类app,这类app有H5无法达到的技术屏障,还是会继续存在下去。而对于其他的应用,app的价值已经没有或者很少。不说未来,即便是当下,很多没有多少资金的创业团队都是以微信搭载H5的方式进行产品运营,连作为壳子的app都省去了。
    2、app应用内部的原生与H5占比
           当H5(或者未来某种更牛逼的前端移动技术)的发展能够达到媲美app原生的交互流畅度展示效果时,现存的app内部也将发生重大变化,app的作用只是为了保证应用的名称不同logo各异,内部实现将完全由H5取代,app只是提供操作底层硬件机能与展示的空壳
      

     

          也许这些并不在未来,而在明天

     

    点击进入ooppookid的博客

     

    展开全文
  • 原生开发环境初探

    千次阅读 2019-12-12 19:38:33
    在上一篇“云原生的不同解释及正确含义”里,我们讲到了云原生的引申含义,就是开发环境也是云环境,这样就能保证开发环境和生产环境的一致性,使最终的部署顺利进行。本文就通过具体的例子来探讨云原生的开发环境。...

    在上一篇“云原生的不同解释及正确含义”里,我们讲到了云原生的引申含义,就是开发环境也是云环境,这样就能保证开发环境和生产环境的一致性,使最终的部署顺利进行。本文就通过具体的例子来探讨云原生的开发环境。开发流程主要包括编写代码,程序部署和调试几个环节。每一个环节都需要相应的工具来帮助你提高效率。下面我们就来看一下如何搭建开发的云环境以及那些工具能帮你在云环境里提高开发效率。

    开发IDE

    以前的IDE只支持应用程序的开发,但云原生需要同时进行开发环境(容器)的开发,理想的情况是一个IDE能同时支持两者。我用的是Go语言,选择的IDE是Goland(也就是IDEA IntelliJ),它本身是支持k8s的,你只要下载一个插件就行。它支持k8s的自动完成(Auto-complete)等功能。如下图所示,这样你就拥有了同时支持应用程序和k8s的IDE。

    file

    但我不得不说它对k8s的支持很初级,它不能理解k8s对象之间的内在联系。另外,k8s配置文件对格式要求很严,如果空格不对,或格式没有对齐,在部署时会报错。Goland有检查格式的功能,出了问题会报错,但并不是每个错误它都能发现。也就是说当它没有报错时也不能肯定格式就是对的。这已经发生好几次了,IDE没有报错,但部署时有问题。

    关于IntelliJ对k8s的支持功能,请参见IntelliJ IDEA 2018.1: Kubernetes support

    环境搭建

    调式k8s是在Minikube上进行的,而Minikube是安装在Linux虚机上的。这就需要开发环境的宿主机和虚机之间能够共享文件,这样才能方便调试。我的开发环境是Windows,然后在Windows上装了VirtualBox虚拟机,另外还安装了Vagrant(它是管理虚拟机的一个软件)作为界面来管理VirtualBox。

    程序共享

    我的Go应用程序是在Windows上的“C:codesrcgithub.comjfeng45k8sdemo”目录下,通过Vagrant可以把宿主机的目录挂载到虚机上,这样每次在IDE上修改了k8s的配置文件,在虚机上可以直接取到,不需要另外同步。

    在Vagrant中的配置是这样的:

    config.vm.synced_folder "C:/code/src/github.com/jfeng45", "/home/vagrant/jfeng45", id: "jfeng45"

    网络共享

    就是实现宿主机(笔记本)和虚机之间的互相访问,主要是从宿主机访问虚机。我用的是Vagrant, 因此要在Vagran的配置文件(Vagrantfile)里进行配置。网络的配置有不同方式,我配置的是私有网络,这是一种很灵活的方式。它的配置方法是给宿主机和虚机各自设定一个固定的IP地址,这样可以双向互访。

    Vagrant的配置命令:

    “config.vm.network “private_network”, ip: "192.168.50.4”

    数据库共享

    在配置k8s时,一般会把数据库设置成一个服务。如果能在宿主机上访问k8s数据库,就能提前测试数据库,尽早发现数据库的问题。一旦把虚机和宿主机之间的网络联通了,是可以从宿主机直接访问数据库。

    有关环境配置的详情,详情请参阅“通过搭建MySQL掌握k8s(Kubernetes)重要概念(上):网络与持久卷”.

    开发流程

    开发流程通常是这样的。你先在本地的IDE上编写代码(包括应用程序和k8s代码),代码是存储在本地硬盘上的。完成之后,你进入虚机环境,部署k8s集群和应用程序代码,再在k8s集群上运行代码,测试结果。如此反复循环。

    流程示例

    我们通过一个例子来讲解流程。在本地编写完代码之后,就要调试k8s程序。先用Vagrant启动虚机,然后启动Minikube:

    sudo minikube start

    程序结构

    file

    上面是程序的目录结构。“cmd”目录里是主程序,“config”目录是负责程序配置的,“dataservice”是数据访问层,“model”是域模型层,“logs”目录是存储日志的。“script”包含了所有与程序部署相关的文件。其中“database”里面是数据库脚本,“kubernetes”是k8s的所有配置文件,一回儿还会详细讲解。

    file

    上面就是k8s的配置文件目录结构,最外面有两个文件“k8sdemo-config.yaml”和"k8sdemo-secret.yaml"是共享文件,因此放在最外层。里面主要有两个子目录“backend”和“database”分别存后端程序和数据库的配置文件。内部的结构是类似的,都有三个“yaml”文件,“backend-deployment.yaml”是部署配置文件, "backend-service.yaml"是服务配置文件, "backend-volume.yaml"是持久卷配置文件. ".sh"是k8s命令,用来创建k8s对象。“backend”目录还多了一个“docker”子目录用来存储backend应用的Docker镜像,database的镜像文件是直接从Docker的库中取得,因此不需要另外生成镜像文件。

    关于k8s的核心概念,请参阅“通过实例快速掌握k8s(Kubernetes)核心概念”.

    部署和调试应用程序及k8s

    我们的程序有两个服务“k8sdemo-database-service”和“k8sdemo-backend-service”,先要部署“k8sdemo-database-service”,因为它不依赖于其它服务。不过还有些对象是共享的需要先进行调试。有一点需要注意的是由于k8s对象之间是有依赖关系的,在你创建时是需要按照顺序来创建。顺序的部署次序是这样的Secret->ConfigMap->Volume->Deployment->Service。

    部署共享对象:

    cd /home/vagrant/jfeng45/k8sdemo/script/kubernetes
    kubectl apply -f k8sdemo-config.yaml
    kubectl apply -f k8sdemo-secret.yaml

    检查创建情况:

    kubectl describe configMap
    kubectl describe secret

    部署数据库服务:

    cd /home/vagrant/jfeng45/k8sdemo/script/kubernetes/database
    kubectl apply -f database-volume.yaml
    kubectl apply -f database-deployment.yaml
    kubectl apply -f database-service.yaml
    

    数据库创建好了之后,可以在IDE中用程序直接访问虚拟机上的库,这样比较方便。但你需要设置环境变量。在k8s中是由configMap设置的,在Windows里需要单独设置,命令在“windowsEnv.bat”里面。内容如下:

    setx MYSQL_ROOT_PASSWORD root
    setx MYSQL_USER_NAME dbuser
    setx MYSQL_USER_PASSWORD dbuser
    setx MYSQL_DATABASE service_config
    setx MYSQL_HOST 192.168.50.4
    setx MYSQL_PORT 30306

    创建应用程序镜像:

    cd /home/vagrant/jfeng45/k8sdemo/
    docker build -f ./script/kubernetes/backend/docker/Dockerfile-k8sdemo-backend -t k8sdemo-backend .

    部署后端服务

    cd /home/vagrant/jfeng45/k8sdemo/script/kubernetes/backend
    kubectl apply -f backend-volume.yaml
    kubectl apply -f backend-deployment.yaml
    kubectl apply -f backend-service.yaml

    登录容器,并运行程序,查看结果:

    vagrant@ubuntu-xenial:~/jfeng45/k8sdemo/script/kubernetes/backend$ kubectl exec -ti k8sdemo-backend-deployment-57bcd56f7d-26p5k -- /bin/sh
    ~ # ./main.exe
    time="2019-12-10T06:23:45Z" level=debug msg="connect to database "
    time="2019-12-10T06:23:45Z" level=debug msg="dataSourceName:dbuser:dbuser@tcp(k8sdemo-database-service:3306)/service_config?charset=utf8"
    time="2019-12-10T06:23:45Z" level=debug msg="FindAll()"
    time="2019-12-10T06:23:45Z" level=debug msg="created=2019-10-21"
    time="2019-12-10T06:23:45Z" level=debug msg="find user:{1 Tony IT 2019-10-21}"
    time="2019-12-10T06:23:45Z" level=debug msg="find user list:[{1 Tony IT 2019-10-21}]"
    time="2019-12-10T06:23:45Z" level=debug msg="user lst:[{1 Tony IT 2019-10-21}]"

    上面步骤中的k8s部分并不是每次修改应用程序之后都要运行,通常只需要运行有改动的部分。一般来讲只是部署(Deployment)会有改动,因为程序的Docker镜像变了。即使这样要完成一次调试也有不少步骤。

    有关k8s的核心概念,详情请参阅“通过实例快速掌握k8s(Kubernetes)核心概念”.

    综述:

    从上面的流程可以看出,在本地云环境上进行开发和调试还是比较繁琐的,你需要在宿主机和虚拟机之间进行切换,还要同时对应用程序和k8s进行调试,中间有很多手工操作,要敲入很多命令,怎样才能简化它呢?

    Helm

    k8s的一个痛点就是它有很多组成部分(部署,服务,存储卷等),每个部分都要分别敲入命令进行调试,特别是当出现问题时,你需要反复删除原来的并创建新的。Helm解决了它的这个痛点。Helm是最流行的k8s包管理工具,就像Java中的Maven和Go里面的“Go Module”。它的一个核心概念是“Chart”。有了它之后,你可以把k8s的各个部分作为一个整体来管理,这样就大大减少了工作量。在调试初期,你还是可以对各部分进行单独调试,这样减少复杂度。但一旦成功之后,你就可以把它当成一个整体来操作,这样大大简化了操作。Helm的另一个作用就是对K8s配置的版本进行管理。

    Helm文件结构

    chart里一个很重要的概念就是模板(template),也就是Go语言模板。模板就是里面加入了编程逻辑的k8s文件。这些模板文件在使用时都要先进行模板解析,把其中的程序逻辑转化成对应的编码,最终生成k8s配置文件。

    file

    以上就是Helm自动生成的chart目录结构,在Helm里每个项目叫一个chart,它由下面几个组成部分:

    • "Chart.yaml":存有这个chart的基本信息,
    • "values.yaml":定义模板中要用到的常量。
    • “template”目录:里面存有全部的模板文件,其中最重要的是“deployment.yaml”和“service.yaml”,分别是部署和服务文件. "helpers.tpl"用来定义变量,"ingress.yaml"和"serviceaccount.yaml"分别是对外接口和服务账户,这里暂时没用, “NOTES.txt”是注释文件。
    • “charts”目录: 存有这个chart依赖的所有子chart。

    Chart设计

    现在我们就用一个例子来展示Helm的chart设计。这个例子是一个微服务应用程序,它共有三层: 前端,后端和数据库。

    在k8s中,每一层就是一个单独的服务,它里面有各种配置文件。Helm的优势是把这些不同的服务组成一个Chart来共同管理和调式,方便了许多。键入如下命令创建chart,其中“k8sdemo”是chart的名字,这个名字很重要,服务的名字和label都是由它产生的。

    helm create k8sdemo

    这之后,系统会自动创建前面讲到的chart目录结构。然后就是对已经生成的文件进行修改。

    file

    上面就是最终的chart目录结构图。“chart”是总目录,里面有三个子目录“k8sdemo”,“k8sdemo-backend”,“k8sdemo-database”, 每一个对应一个服务,每个服务都是一个独立的chart,能单独调式部署,chart之间也可以有依赖关系。其中“k8sdemo”是父chart,同时也是前端服务,它的“charts”目录里有它依赖的另外两个服务。“k8sdemo-backend”是后端服务,“k8sdemo-database”是数据库服务。

    安装k8sdemo:

    vagrant@ubuntu-xenial:~/jfeng45/k8sdemo/script/kubernetes/chart$ helm upgrade k8sdemo ./k8sdemo
    Release "k8sdemo" has been upgraded. Happy Helming!
    NAME: k8sdemo
    LAST DEPLOYED: Fri Nov 29 01:28:55 2019
    NAMESPACE: default
    STATUS: deployed
    REVISION: 2
    NOTES:
    1. Get the application URL by running these commands:
      export NODE_PORT=$(kubectl get --namespace default -o jsonpath="{.spec.ports[0].nodePort}" services k8sdemo)
      export NODE_IP=$(kubectl get nodes --namespace default -o jsonpath="{.items[0].status.addresses[0].address}")
      echo http://$NODE_IP:$NODE_PORT

    获取Pod名称:

    vagrant@ubuntu-xenial:~/jfeng45/k8sdemo/script/kubernetes/chart$ kubectl get pod
    NAME                                          READY   STATUS    RESTARTS   AGE
    k8sdemo-74cb7b997c-pgcj4                      1/1     Running   0          33s
    k8sdemo-backend-5cd9d79856-dqlmz              1/1     Running   0          33s
    k8sdemo-database-85855485c6-jtksb             1/1     Running   0          33s
    k8sdemo-jenkins-deployment-675dd574cb-r57sb   1/1     Running   3          23d

    运行程序进行测试:

    vagrant@ubuntu-xenial:~/jfeng45/k8sdemo/script/kubernetes/chart$ kubectl exec -ti k8sdemo-backend-5cd9d79856-dqlmz -- /bin/sh
    ~ # ./main.exe
    time="2019-11-27T07:03:03Z" level=debug msg="connect to database "
    time="2019-11-27T07:03:03Z" level=debug msg="dataSourceName:dbuser:dbuser@tcp(k8sdemo-database-service:3306)/service_config?charset=utf8"
    time="2019-11-27T07:03:03Z" level=debug msg="FindAll()"
    time="2019-11-27T07:03:03Z" level=debug msg="created=2019-10-21"
    time="2019-11-27T07:03:03Z" level=debug msg="find user:{1 Tony IT 2019-10-21}"
    time="2019-11-27T07:03:03Z" level=debug msg="find user list:[{1 Tony IT 2019-10-21}]"
    time="2019-11-27T07:03:03Z" level=debug msg="user lst:[{1 Tony IT 2019-10-21}]"
    ~ #

    由上面可以看出,使用了Helm之后,大大简化了k8s的部署和调试过程。只需一步就能完成所有k8s对象的部署。

    详情请参见用Helm3构建多层微服务

    自动调试工具

    Helm解决了k8s的部署问题,但你修改程序之后,还是要更新Docker镜像,才能部署,部署之后还要测试,比对结果,这里面还是有很多手工操作,有没有工具能自动完成这些工作?确实有这样的工具,而且还有不少,它们的功能也不尽相同。这里面有一类工具是相对来说比较有用的,那就是自动化整个部署、调试流程的。它们的功能和流程一般是这样的。

    它会自动检测程序修改,一旦发现就自动生成Docker镜像,然后调用k8s部署文件把新的镜像文件部署到k8s集群上,再调用测试程序进行测试,并在控制台显示结果。整个过程不需要你敲入一行命令,全部自动执行。这样完全消除了手工操作,使整个流程自动执行。你可能会说你并不想每修改一行程序就进行一下测试,而是当你需要的时候再去测试。这个功能在某些工具里也是可以配置的,你可以配置一个触发器,只有当它触发之后才自动完成上述操作。

    Skaffold配置文件:

    我们现在就用一个例子来具体说明,使用的工具是Skaffold。Skaffold的主要部分是一个配置文件,叫“skaffold.yaml”, 存放在项目的根目录。里面有Skaffold需要的信息,如Docker镜像的文件名,k8s的部署文件等。

    apiVersion: skaffold/v1
    kind: Config
    metadata:
      name: k-sdemo
    build:
      artifacts:
      - image: k8sdemo-backend
        context: .
        docker:
          dockerfile: script/kubernetes/backend/docker/Dockerfile-k8sdemo-backend
    deploy:
      kubectl:
        manifests:
        - script/kubernetes/backend/backend-deployment.yaml
        - script/kubernetes/backend/backend-service.yaml
    

    上面就是这个文件,它看起来很像k8s的配置文件,它的类型是“Config”。里面有两个主要部分,一个是:“build”,负责生成项目的Docker镜像的,另一个是“deploy”,负责把生成的镜像部署到k8s上。

    Skaffold可以帮你自动生成基础配置文件。你可以敲入“skaffold init”,它会问你一些问题,并根据你的回答,自动生成“skaffold.yaml”文件。生成之后,你可以根据需要进行修改。这里面比较重要的就是引用了镜像文件和k8s部署文件。如果你以前已经创建了这些文件,那么你可以复用它们。

    运行Skaffold:

    生成“skaffold.yaml”文件之后,键入如下命令“skaffold dev”,系统会运行“skaffold.yaml”,部署k8s,并开始监控程序的修改。输出如下:

    vagrant@ubuntu-xenial:~/jfeng45/k8sdemo$ skaffold dev
    WARN[0000] Could not get minikube docker env, falling back to local docker daemon: getting minikube env: Running [minikube docker-env --shell none]: stdout , stderr: *
    Listing files to watch...
    - k8sdemo-backend
    Generating tags...
    - k8sdemo-backend -> k8sdemo-backend:05894ca-dirty
    Checking cache...
    - k8sdemo-backend: Not found. Building
    Found [minikube] context, using local docker daemon.
    Building [k8sdemo-backend]...
    Sending build context to Docker daemon  534.5kB
    Step 1/13 : FROM golang:latest as builder
    ---> dc7582e06f8e
    Step 2/13 : WORKDIR /app
    ---> Using cache
    ---> d5d126eaa528
    Step 3/13 : COPY go.mod go.sum ./
    ---> Using cache
    ---> 6ed430911953
    Step 4/13 : RUN go mod download
    ---> Using cache
    ---> bfb89c8b352b
    Step 5/13 : COPY . .
    ---> 6c1f89974762
    Step 6/13 : WORKDIR /app/cmd
    ---> Running in d36e8a412aae
    ---> 9f7f92349811
    Step 7/13 : RUN go build -o main.exe
    ---> Running in 31ff6408dfda
    ---> 31d84d0c860a
    Step 8/13 : FROM alpine:latest
    ---> 965ea09ff2eb
    Step 9/13 : RUN apk --no-cache add ca-certificates
    ---> Using cache
    ---> a27265887a1e
    Step 10/13 : WORKDIR /root/
    ---> Using cache
    ---> b9c048c97f07
    Step 11/13 : RUN mkdir /lib64 && ln -s /lib/libc.musl-x86_64.so.1 /lib64/ld-linux-x86-64.so.2
    ---> Using cache
    ---> 95a2b77e3e0a
    Step 12/13 : COPY --from=builder /app/cmd/main.exe .
    ---> Using cache
    ---> 5ef8db6e073a
    Step 13/13 : CMD exec /bin/sh -c "trap : TERM INT; (while true; do sleep 1000; done) & wait"
    ---> Using cache
    ---> 6f3e1f751ac6
    Successfully built 6f3e1f751ac6
    Successfully tagged k8sdemo-backend:05894ca-dirty
    Tags used in deployment:
    - k8sdemo-backend -> k8sdemo-backend:6f3e1f751ac6ad3c39092a9308f9a6e1d5e087da275349aa3719344785b26f1a
       local images can't be referenced by digest. They are tagged and referenced by a unique ID instead
    Starting deploy...
    - deployment.apps/k8sdemo-backend-deployment created
    - service/k8sdemo-backend-service created
    Watching for changes...

    你如果有测试程序,就可以在控制台输出结果。我没有测试程序,就要登录到Pod上运行程序,查看结果。

    获得Pod名

    vagrant@ubuntu-xenial:~/jfeng45/k8sdemo/script/kubernetes/backend$ kubectl get pod
    NAME                                          READY   STATUS    RESTARTS   AGE
    k8sdemo-74cb7b997c-8hpdq                      1/1     Running   1          11d
    k8sdemo-backend-5cd9d79856-nwlcl              1/1     Running   1          11d
    k8sdemo-backend-deployment-57bcd56f7d-26p5k   1/1     Running   0          14s
    k8sdemo-database-85855485c6-vnsp4             1/1     Running   1          11d
    k8sdemo-jenkins-deployment-675dd574cb-r57sb   1/1     Running   5          36d

    登录Pod,并运行程序

    vagrant@ubuntu-xenial:~/jfeng45/k8sdemo/script/kubernetes/backend$ kubectl exec -ti k8sdemo-backend-deployment-57bcd56f7d-26p5k -- /bin/sh
    ~ # ./main.exe
    time="2019-12-10T06:23:45Z" level=debug msg="connect to database "
    time="2019-12-10T06:23:45Z" level=debug msg="dataSourceName:dbuser:dbuser@tcp(k8sdemo-database-service:3306)/service_config?charset=utf8"
    time="2019-12-10T06:23:45Z" level=debug msg="FindAll()"
    time="2019-12-10T06:23:45Z" level=debug msg="created=2019-10-21"
    time="2019-12-10T06:23:45Z" level=debug msg="find user:{1 Tony IT 2019-10-21}"
    time="2019-12-10T06:23:45Z" level=debug msg="find user list:[{1 Tony IT 2019-10-21}]"
    time="2019-12-10T06:23:45Z" level=debug msg="user lst skaffold:[{1 Tony IT 2019-10-21}]"

    有关Skaffold的详情,请参见Working With Skaffold

    自动调试工具比较:

    有四个比较流行的 自动调试工具,它们是“Draft”,“Skaffold”,“Garden”,“Tilt”。

    Garden:我最先测试的是“Garden”,因为它功能强大。但测试之后发现它很不灵活,对项目的目录结构有特殊要求。例如,你的项目有三个微服务,那么它会建一个总项目,三个微服务每个是一个子项目,每个子项目里需要一个“Garden”的微服务配置文件,总项目也要一个配置文件,而且文件的名字和位置是固定的。这导致它配置起来很繁琐,而且与一般的程序结构有冲突。“Garden”的设计思想是好的,它想使用一个工具来统一开发和部署。但由于开发和部署差别还是很大的,统一的结果就是不伦不类。它给出的例子也都是很简单的实例,我觉得一旦应用到比较复杂的项目就会很不方便。

    Garden的详情,请参见Introduction

    Tilt:“Tilt”是我第二个测试的,它看起来非常灵活,功能也很强大。但运行之后,它在连接Minikube时出了问题,连接不上。官方安装文档给出的默认的k8s集群是Microk8s。它的文档里也说了支持Minikube,但并没有解释需要做哪些设置,看起来像是不需要设置就可以直接连通,不知道为什么我的Minikube会有问题。当然,也有可能是因为我启动时用的是“minikube start --vm-driver=none”,导致了连接的问题。我想如果花些时间仔细研究,问题应该可以解决,但连接Minikube是整个过程的第一步,一上来就出问题实在让我有些信心不足,就决定先放一放。

    Tilt的详情,请参见Tutorial: The First 15 Minutes

    Skaffold:这是我测试的第三个工具。它功能很强大,也很灵活,虽然也碰到一些问题,但很快就解决了。因此我对Skaffold是很满意的。Skaffold给出的官方安装文档的下载地址是“https://storage.googleapis.com/skaffold/releases/latest/skaffold-linux-amd64”。 这个没法访问。你可以在GitHub的release里面下载可执行文件,然后拷贝到“/usr/local/bin/skaffold”目录就可以了。

    Draft:我没有测试Draft。Draft现在已经不再维护了,它的开发者有别的任务,停止了继续开发。Draft应该比较容易使用,但功能不够强大。

    总体评论:总的来说我对Skaffold很满意,它确实大大简化了调试流程。但我觉得这类工具并不像我想像的那么完美。因为每次修改程序之后都要重新生成镜像,这个过程很慢。当然你可以有很多手段来优化他,例如建一个本地镜像库。另外这类工具本身也有优化措施,例如对下载库的优化。但总的来说跟本地环境还是没法比。

    关于这些工具的比较详情,请参见The ultimate guide for local development on Kubernetes: Draft vs Skaffold vs Garden.ioLocal Kubernetes development with Tilt.dev

    开发模式:

    在云原生开发模式下,你可以把项目的运行环境分成两部分。一部分是项目需要调用的服务和资源,这些都是部署在云环境上的(也就是k8s集群)。你可以用Helm创建一个chart,里面包含所有本项目需要调用的k8s服务(包括数据库服务),然后把这个chart部署到k8s集群上,这部分的程序变化频率较低。一旦这些服务中的某些代码变了,你只要重新部署chart就行了。另一部分是项目本身的代码和运行环境,这部分程序变化频率较高。这一部分既可以在k8s上运行,也可以在本地环境运行。它的不同决定了开发模式的不同。

    纯云原生开发模式:

    在这种模式下,除了IDE和代码是在本地,其他的所有东西都是在云环境。当项目代码修改之后,需要创建新的Docker镜像文件,然后把镜像部署到k8s集群上,在k8s集群上进行调试。你可以用前面讲到的自动调试工具来完成这一任务。它的好处是开发环境和生产环境完全兼容,这样保证了在生产环境部署时没有意外。缺点是调试效率稍低。你如果想把IDE和代码都放在云上,也是可以的,本地只要有一个客户端来访问它们就行了。 这时就是纯正的云开发环境,但它的象征意义更大,对实际工作没有太大影响。

    混合开发模式:

    在这种模式下,项目是在本地调试的,而它依赖的其它微服务是部署在云环境上(虚拟机上的k8s上)的。由于本地环境和虚机的网络是联通的,本地环境上运行的代码可以访问虚机上的微服务。数据库也是一样,也是部署在k8s集群上,你可以把它看成一个服务,并通过本地客户端访问数据库上的数据,这时数据库的物理位置对你是透明的,不管是在云上还是在本地都没有区别。当项目的代码修改之后,你在本地运行项目并调试。如果你需要web服务器,对有些语言不成问题,例如Go,它的web服务器就是用本地代码生成的,是程序的一部分。如果你用的是Java,需要单独的服务器,那么你还需要一个本地服务器来部署修改之后的代码。

    这种方式的最大好处就是调试效率很高。因为本项目的代码修改频率是最高的,用这种方式能最大限度地提高它的调试速度。虽然牺牲了一点开发环境和生产环境的兼容性,但这也是可以弥补的。例如,你可以每隔一段时间把本地项目部署到k8s集群上(使用上面提到的调试工具)和其他依赖的服务一起进行整个联调,这时的运行环境就和生产环境一致了。具体的部署频率根据个人和项目来定,可以是每天,也可以是3天或更多。这样既能保证平时调试的速度和效率,又能保证本地开发环境和生产环境的一致性。这种模式在我看来更有优势。

    工具总结:

    本文详细讲解了云原生开发环境以及需要的工具,它包括下面四类:

    • IDE:必不可少,需支持k8s.
    • k8s:是云原生的基石,没有它就没有云原生.
    • Helm:不论什么开发模式,它都是一个不可或缺的工具.
    • 自动调试工具:在纯云原生开发模式下是必不可少的,在混合开发模式下也是需要的,但没有纯云原生开发模式下那么重要。

    源码库

    完整源码的github链接:k8sdemo

    索引

    1. 云原生的不同解释及正确含义
    2. IntelliJ IDEA 2018.1: Kubernetes support
    3. 通过搭建MySQL掌握k8s(Kubernetes)重要概念(上):网络与持久卷
    4. 通过实例快速掌握k8s(Kubernetes)核心概念
    5. 用Helm3构建多层微服务
    6. Working With Skaffold
    7. Introduction
    8. Tutorial: The First 15 Minutes
    9. The ultimate guide for local development on Kubernetes: Draft vs Skaffold vs Garden.io
    10. Local Kubernetes development with Tilt.dev

    不堆砌术语,不罗列架构,不迷信权威,不盲从流行,坚持独立思考

    展开全文
  • Cocos Creator2.1安装配置原生开发环境

    千次阅读 2019-08-02 14:48:55
    在使用 Cocos Creator 打包发布到原生平台之前,我们需要先配置好 cocos2d-x 相关的开发环境。 Android 平台相关依赖 要发布到 Android 平台,需要安装以下全部开发环境依赖。 如果您没有发布到 Android 平台的...

    除了内置的 Web 版游戏发布功能外,Cocos Creator 使用基于 cocos2d-x 引擎的 JSB 技术实现跨平台发布原生应用。在使用 Cocos Creator 打包发布到原生平台之前,我们需要先配置好 cocos2d-x 相关的开发环境。

    Android 平台相关依赖

    要发布到 Android 平台,需要安装以下全部开发环境依赖。

    如果您没有发布到 Android 平台的计划,或您的操作系统上已经有完整的 Android 开发环境,可以跳过这个部分。

    下载 Java SDK (JDK)

    编译 Android 工程需要本地电脑上有完整的 Java SDK 工具,请到以下地址下载:

    Java SE Development Kit 8 Downloads

    下载时注意选择和本机匹配的操作系统和架构,下载完成后运行安装程序即可。

    安装后请检查 JAVA 环境,在 Mac 终端或者 Windows 命令行工具中输入下面代码来查看:

    java -version
    

    显示为 JAVA SE 则没有问题,如果系统中使用的是 JRE,则需要安装 JAVA SE 运行环境

    如果是 Windows 系统,请确认你的环境变量中包含 JAVA_HOME。可以通过右键点击我的电脑,选择属性,打开高级选项卡中来查看和修改环境变量。修改完成后 Windows 平台可能需要重启电脑才会生效。参考 如何设置或更改 JAVA 系统环境变量

    下载安装 Android Studio

    从 v1.10 开始,我们不再支持 Eclipse 的 ANT 构建,需要使用 Android Studio 作为安卓平台的构建工具,并在 Android Studio 里下载所需的 SDK 和 NDK 包。首先请 安装 Android Studio

    下载发布 Android 平台所需的 SDK 和 NDK

    安装 Android Studio 完成后,参考官方文档,打开 SDK Manager(AS的菜单Tools---->Android---->SDK Manager):

    SDK Manager 使用说明(需要使用 VPN)

    1. 在 SDK Platforms 分页栏,勾选你希望安装的 API Level,也就是支持安卓系统的版本,推荐选择最低兼容的 API Level 16(4.1) 和所需的主流 API Level 23(6.0)、API Level 26(8.0)和 API Level 28(9.0)。
    2. 在 SDK Tools 分页栏,首先勾选右下角的 Show Package Details,显示分版本的工具选择。
    3. 在 Android SDK Build-Tools 里,选择最新的 build tools 版本。
    4. 勾选 Android SDK Platform-ToolsAndroid SDK Tools 和 Android Support Library
    5. 勾选 NDK,确保版本在 r16 及以上。
    6. 记住窗口上方所示的 Android SDK Location 指示的目录,稍后我们需要在 Cocos Creator 里填写这个 SDK 所在位置。
    7. 点击 OK,根据提示完成安装。

    sdk manager

    安装 C++ 编译环境

    Cocos2d-x 自带的编译工具 Cocos Console 需要以下运行环境:

    • Python 2.7.5+,下载页,注意不要下载 Python 3.x 版本。
    • Windows 下需要安装 Visual Studio 2015 或 2017 社区版,下载页
    • Mac 下需要安装 Xcode 和命令行工具,下载页

    配置原生发布环境路径

    下载安装好开发环境依赖后,让我们回到 Cocos Creator 中配置构建发布原生平台的环境路径。在主菜单中选择 CocosCreator -> 设置,打开设置窗口:

    preference

    我们在这里需要配置以下两个路径:

    • NDK 路径,选择 Android SDK Location 路径下的 ndk-bundle 文件夹(NDK 是其根目录),不需要编译 Android 平台的话这里可以跳过。
    • Android SDK 路径,选择刚才在 SDK Manager 中记下的 Android SDK Location 路径(Android SDK 的目录下应该包含 build-tools、platforms 等文件夹),不需要编译 Android 平台的话这里可以跳过。

    配置完成后点击 保存 按钮,保存并关闭窗口。

    注意:这里的配置会在编译 原生工程 的时候生效。如果没有生效(一些 Mac 机器有可能出现这个情况),可能需要您尝试到 系统环境变量 设置这些值:COCOS_CONSOLE_ROOT, NDK_ROOT, ANDROID_SDK_ROOT。

    注意事项

    由于在公测版中收到了很多原生打包的问题反馈,这里补充一些可能的问题原因。

    1. 检查 Xcode 和 Visual Studio

      打包 Mac 版本和 iOS 版本需要 Xcode 支持,打包 Windows 版本需要安装 Visual Studio。在安装 Visual Studio 时,请勾选 使用 C++ 的桌面开发 和 使用 C++ 的游戏开发 两个模块。

      注意:在 使用 C++ 的游戏开发 模块中有一个 Cocos 选项,请勿勾选安装。

    2. 包名问题

      检查构建发布面板中的包名,包含空格,- 等都是非法的包名。

    3. Android 6.0 SDK 的支持问题

      Android 6.0 SDK 去除了 Cocos2d-x 依赖的 HttpClient 库,所以会导致 Cocos Creator v1.5 以前的版本编译失败。旧版本用户的解决方案是:

      • 找到 Android SDK 目录下的 HttpClient 库:platforms/android-23/optional/org.apache.http.legacy.jar
      • 如果使用源码引擎模版,需要拷贝到原生编译目录下的 jsb/frameworks/cocos2d-x/cocos/platform/android/java/libs/ 目录下。如果使用预编译库引擎模版,需要拷贝到原生编译目录下的 jsb/frameworks/runtime-src/proj.android/jars/ 目录下。
      • 重新编译。
    4. Android 编译成功,但运行时提示 dlopen failed: cannot locate symbol "xxxx" referenced by "libcocos2djs.so"...

      请检查 NDK 和 Android SDK 的架构和版本是否和测试用的 Android 系统相对应,另外可以尝试使用本文所用的 NDK 和 Android SDK 版本来测试。

    展开全文
  • 基于腾讯云cvm的云原生环境搭建

    千次阅读 2021-11-21 15:43:57
    主要简述了使用腾讯云云原生操作系统tlinux3进行开发时常用组件的如docker、vim的配置使用方式。持续更新,后续会追加k8s等组件的安装配置方式。
  • 什么是云原生

    2021-10-24 22:30:13
    原生(CloudNative)的概念是伴随云计算的滚滚浪潮应运而生,云原生这几年很火,简直火得一塌糊涂,不过云原生(CloudNative)没有确切的定义,云原生...Native表示应用程序从设计之初即考虑到云的环境原生为云而设
  • 云计算的发展,经历了虚拟化、商业IaaS、商业PaaS,到开源IaaS...今天,在5G、AI&大数据应用日渐普及的背景下,为适应多云混合云、智能计算、边缘计算、异构计算等计算环境,云原生正在迎来新的进化。在华为开发者大会2020(C
  • PHP原生环境配置 来 让你熟悉为什么

    千次阅读 2017-01-17 13:37:41
    入门环境配置 储备知识 1.PHP是一种典型的脚本语言、开发阶段必要环境配置 2.经典的Apache服务器加MySql数据库就能实现PHP程序运行 3.PHP: 在Web端之所以流行,是因为其兼容性,安全性,及运行效率迅速 ...
  • kubernetes与云原生

    千次阅读 2019-07-15 23:50:26
    在开发部署应用的过程中总会出现测试环境明明好好的,部署得到正式环境就会出现各种各样的莫名其妙的问题,尤其是一些部署复杂的应用。有时会遇到需要部署多个相同的应用,又不得不投入大量人力、时间等资源消耗在...
  • cocos-creator的安装配置原生开发环境

    万次阅读 2016-10-03 12:54:04
    安装配置原生开发环境 (摘自:http://www.cocos.com/docs/creator/publish/setup-native-development.html) 除了内置的 Web 版游戏发布功能外,Cocos Creator 使用基于 cocos2d-x 引擎的 JSB 技术实现跨平台...
  • “云原生”是云计算中很重要的一个概念,不过对“云原生”的认识和解读各有侧重。我们觉得云原生围绕的是“云原生应用”这个核心,微服务、容器、DevOps等是实现云原生的工具和方法论,它们并不等价。澄清概念、厘清...
  • 什么是原生开发?什么是混合开发?两者有什么区别?2020-11-27 17:54:09 991人读过一. APP何为原生开发?何为混合开发?1.原生开发(NativeApp开发):像盖房子一样,先打地基然后浇地梁、房屋结构、一砖一瓦、钢筋水泥...
  • 云安全概述 安全问题成为影响云原生落地的重要因素 ...云原生环境的可观察性 微隔离实现零信任的云原生网络 云原生异常检测 云原生应用安全 服务网格安全防护 serverless安全防护 面向新基建的云原生安全
  • 原生白皮书发布.pdf

    2021-01-08 14:03:47
    原生从字面意思上来看可以分成云和原生两个部分。...原生就是土生土长的意思,我们在开始设计应用的时候就考虑到应用将来是运行云环境里面的,要充分利用云资源的优点,比如️云服务的弹性和分布式优势。
  • 原生下,如何实现高可用的MySQL?

    千次阅读 2020-09-01 15:44:17
    简介:MySQL 作为当前比较受欢迎的关系型数据库(RDS),在云原生浪潮中仍然面临诸多挑战。如何用 Cloud Native 的设计原则,通过沙箱隔离、计算和数据的完全分离,实现低成本、可扩展、高可用的 Cloud RDS 方案?...
  • 前言 本文内容整理自 5月25日 在 Kubernetes &...结合蚂蚁金服的上云实践,阐述在云原生背景下 Service Mesh 的核心价值,以及对云原生落地的关键作用。 内容主要有三个部分: Service Mesh 产品动态:介绍最近半...
  • 原生特有的技术架构和应用模式出发,全面剖析云原生系统面临的 安全威胁,针对性提出云原生安全边界、原则和防护模型,系统阐述 涵盖基础设施安全、云原生计算环境安全、云原生应用安全、云原生 研发运营安全、云...
  • 下面小编就为大家带来一篇老生常谈原生JS执行环境与作用域。小编觉得挺不错的,希望对大家有所帮助。一起跟随小编过来看看吧,祝大家游戏愉快哦
  • 关注「开源Linux」,选择“设为星标” 回复「学习」,有我为您特别筛选的学习资料~ 1带你了解云原生技术图谱如果你研究过云原生应用程序和相关技术,大概率你遇到过 CNCF 的云原生全景...
  • 原生2.0白皮书.pdf

    2021-11-26 21:58:05
    根据云原生计算基金会CNCF的定义,云原生技术使组织能够在现代动态环境(例如公共云、私有云和混合云)中构建和运行可扩展的容器、微服务、DevOps等技术使松散耦合的系统具有弹性、可管理性和可观察性,同时,与强大...
  • 原生沙箱环境技术概述.pptx
  • 原生沙箱环境技术概述.pdf
  • 原生技术作为企业数字业务应用创新的原动力, 不仅被引入到云原生应用全生命周期管理中,而且被推到了生产环境。云原生技术为企业带来快速交付与迭代数字业务应用的优势之外, 同时也带来了新的安全要求与挑战。
  • cocos creator获取安卓原生平台上的信息(ts)说明代码获取当前手机系统版本(安卓版本)获取手机型号获取手机厂商获取手机语言获取手机AndroidID获取项目包名获取手机ip地址 说明 首先在cocos上构建项目,原生平台...
  • (译)云原生安全白皮书

    千次阅读 2020-11-27 08:10:00
    执行摘要目的云原生的开发和部署模式已经成为业界趋势,技术、产品、标准和解决方案的生态系统也在同步的扩张之中,决策者面临着跟进复杂设计的挑战。CISO 要在这个动荡的战场中实践业务价值,这...
  • 原生是什么?细数云原生的5大特征00 云原生是什么?01 轻、快、不变的基础设施02 弹性服务编排03 开发运营一体化04 微服务架构05 无服务模型 来源:大数据DT 导读:随着公有云和私有云的广泛部署,云计算基础...
  • 原生存储和云存储有什么区别?

    千次阅读 2019-11-06 16:14:37
    导读:新的企业负载/智能工作负载容器化、迁云、存储方面遇到的性能、弹性、高可用、加密、隔离、可观测性以及生命周期等方面的问题,不但需要存储产品层次的改进,更需要在云原生的控制/数据平面的改进,推进云...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 213,013
精华内容 85,205
关键字:

原生环境