AssetBundle 详解

AssetBundle 详解文章目录AssetBundle的定义和作用什么是AssetBundle用处AssetBundle使用流程图指定资源的AssetBundle属性构建AssetBundle包核心代码详解上传AB包加载AB包和包里面的资源加载本地的AB包加载服务器上的AB包AssetBundle分组策略按照逻辑实体分组按照资源类型分组按照使用分组构建AB后产生的文件AssetBund…

大家好,又见面了,我是你们的朋友全栈君。

AssetBundle 的定义和作用

什么是 AssetBundle

  • 它是一个存在于硬盘上的文件。可以称之为压缩包。这个压缩包可以认为是一个文件夹,里面包含了多个文件。这些文件可以分为两类:serialized file 和 resource files。(序列化文件和源文件)

  • serialized file:资源被打碎放在一个对象中,最后统一被写进一个单独的文件

    • serialized file 只有一个
    • 不能直接看到是什么东西,只有在游戏中加载才能看到的会被打包为序列化文件
    • 例如:prefab,材质
  • resource files:为某些资源(图片和声音)单独存储的二进制数据块,方便快速加载
    mark

  • 它是一个 AssetBundle 对象,我们可以通过代码从一个特定的压缩包加载出来的对象。这个对象包含了所有我们当初添加到这个压缩包里面的内容,我们可以通过这个对象加载出来使用。即:通过对象使用里面的资源

用处

  • AssetBundle 是一个压缩包包含模型、贴图、预制体、声音、甚至整个场景,可以在游戏运行的时候被加载;
  • AssetBundle 自身保存着互相的依赖关系;
    • 例如一个包保存着模型,一个包保存着贴图,而模型又依赖于贴图
  • 压缩包可以使用 LZMA 和 LZ4 压缩算法,可以减少包大小,更快的进行网络传输;
  • 把一些可以下载内容(DLC)放在 AssetBundle 里面,减小初始安装大小,实时更新一些资源;
    • 既然可以把资源放在 AB 里,那么就不会放在 apk 里,玩家下载安装包的时候就会很小,当玩家运行游戏的时候再在服务器上去下载资源包
    • 可以更新一些资源而不用重新安装,例如:在特殊节日的时候更换不同的封面

AssetBundle 使用流程图

mark

指定资源的 AssetBundle 属性

在 Inspector 底部,有 AssetBundle 的面板。

  • AssetBundle 名称“environment/forest”表示,将在 environment 子文件夹下创建名为 forest 的捆绑包
  • 名字不区分大小写,默认小写
  • 指定相同名字的资源会被打到一个包里面
  • 可以自行设置文件的后缀名

构建 AssetBundle 包

mark

在 Assets 文件夹中创建一个名为 Editor 的文件夹,并将包含以下内容的脚本放在该文件夹中:

  • 此脚本将在 Assets 菜单底部创建一个名为“Build AssetBundles”的菜单项,该菜单项将执行与该标签关联的函数中的代码。
  • 单击 Build AssetBundles 会将带有 AssetBundle 名称标签的所有资源,打包放在指定目录下
using System.IO;
using UnityEditor;

public class CreateAssetBundles { 
   
    [MenuItem("Assets/Build AssetBundles")]
    static void BuildAllAssetBundles() { 
   
        string assetBundleDirectory = "Assets/AssetBundles"; // 包的输出路径
        if (!Directory.Exists(assetBundleDirectory)) { 
    // 若路径不存在,则创建
            Directory.CreateDirectory(assetBundleDirectory);
        }
        // BuildPipeline:允许您以编程方式构建可从 Web 加载的播放器或 AssetBundle。
        // BuildAssetBundles():打包,Build 出来的包是有平台限制的
        BuildPipeline.BuildAssetBundles(assetBundleDirectory, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows);
    }
}

核心代码详解

public static AssetBundleManifest BuildAssetBundles(string outputPath, BuildAssetBundleOptions assetBundleOptions, BuildTarget targetPlatform);

  • Build 的路径:随意只要是在硬盘上都可以的
  • BuildAssetBundleOptions
    • None:使用 LZMA 算法压缩,压缩的包更小,但是加载时间更长。
      • 使用之前需要整体解压,一旦被解压,这个包会使用 LZ4 重新压缩。
      • LZ4 使用资源的时候不需要整体解压。
      • 在下载的时候可以使用 LZMA 算法,一旦它被下载了之后,它会使用 LZ4 算法保存到本地上。(Unity 内置的优化策略)
    • UncompressedAssetBundle:不压缩,包大,加载快
    • ChunkBasedCompression:使用 LZ4 压缩,压缩率没有 LZMA 高,但是我们可以加载指定资源而不用解压全部。
      • LZ4 使用基于块的算法,允许按段或“块”加载 AssetBundle。解压缩单个块即可使用包含的资源,即使 AssetBundle 的其他块未解压缩也不影响。
    • 注意使用 LZ4 压缩,可以获得可以跟不压缩想媲美的加载速度,而且比不压缩文件要小。
  • BuildTarget:选择 build 出来的 AB 包要使用的平台

关于构建 AB 后产生的文件

[构建 AB 后产生的文件](#构建 AB 后产生的文件)

上传 AB 包

将资源包上传到自己的服务器,以供游戏运行时的加载。

加载 AB 包和包里面的资源

开发的时候一般会将 AB 包放在本地,因为会进行频繁的操作,发布的时候才会上传到服务器上。

加载本地的 AB 包

using System.IO;
using UnityEngine;

public class LoadFromFileExample : MonoBehaviour { 
   

    private void Start() { 
   
        AssetBundle ab = AssetBundle.LoadFromFile("Assets/AssetBundles/scene/cubewall.u3d");
        if (ab == null) { 
   
            Debug.Log("Failed to load AssetBundle!");
            return;
        }

        // 加载包里的指定物体
        var wallPre = ab.LoadAsset<GameObject>("CubeWall");
        Instantiate(wallPre); // 实例化物体
    }

    // 加载包里的所有物体
    private void LoadAllAssets(AssetBundle ab) { 
   
        Object[] objects = ab.LoadAllAssets();
        foreach (var o in objects) { 
   
            Instantiate(o);
        }
    }
}

加载服务器上的 AB 包

IEnumerator InstantiateObject()
    { 
   
        string uri = "file:///" + Application.dataPath + "/AssetBundles/" + assetBundleName;
        // GetAssetBundle(string, int):获取 AssetBundle 的位置以及要下载的捆绑包的版本。
        UnityEngine.Networking.UnityWebRequest request = UnityEngine.Networking.UnityWebRequest.GetAssetBundle(uri, 0);
        yield return request.Send();
        AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(request);
        GameObject cube = bundle.LoadAsset<GameObject>("Cube");
        GameObject sprite = bundle.LoadAsset<GameObject>("Sprite");
        Instantiate(cube);
        Instantiate(sprite);
    }

其他详细使用可见:

[AssetBundles 的具体使用](#AssetBundles 的具体使用 )

AssetBundle 分组策略

应根据实际项目的需求来进行设置,这里只是给一个简单的参考。

这里的分组策略不是指如何划分文件夹,而是,将哪些资源打包在一个 AssetBundle 里,一个 AssetBundle 就是一组。

按照逻辑实体分组

逻辑实体分组非常适合于可下载内容 (DLC),因为通过这种方式将所有内容隔离后,可以对单个实体进行更改,而无需下载其他未更改的资源。

  • 一个 UI 界面或者所有 UI 界面一个包(这个界面里面的贴图和布局信息一个包)
  • 一个角色或者所有角色一个包(这个角色里面的模型和动画一个包)
  • 所有的场景所共享的部分一个包(包括贴图和模型)

按照资源类型分组

要构建供多个平台使用的 AssetBundle,类型分组是最佳策略之一。

例如,如果音频压缩在 Windows 和 Mac 平台上完全相同,则可以将所有音频数据打包到 AssetBundle 并重复使用这些捆绑包;而着色器往往使用更多特定于平台的选项进行编译,因此为 Mac 构建的着色器捆绑包可能无法在 Windows 上重复使用。此外,这种方法非常适合让 AssetBundle 与更多 Unity 播放器版本兼容,因为纹理压缩格式和设置的更改频率低于代码脚本或预制件。

  • 所有声音资源打成一个包,所有 shader 打成一个包,所有模型打成一个包,所有材质打成一个包

按照使用分组

  • 将需要同时加载和使用的资源捆绑在一起
    • 可以按照关卡分,一个关卡所需要的所有资源包括角色、贴图、声音等打成一个包。
    • 也可以按照场景分,一个场景所需要的资源一个包

总结

  • 把经常更新的资源放在一个单独的包里面,同不经常更新的包分离
  • 把需要同时加载的资源放在一个包里面
    • 如果一个 AssetBundle 中只有不到 50% 的资源经常同时加载,请考虑拆分该捆绑包
    • 如果不可能同时加载两组对象(例如标清资源和高清资源),请确保它们位于各自的 AssetBundle 中。
  • 可以把其他包共享的资源放在一个单独的包里面
    • 防止资源的重复打包
  • 把一些需要同时加载的小资源打包成一个包
  • 如果对于一个同一个资源有两个版本,可以考虑通过后缀来区分版本,xx.v1 xx.v2 xx.v3

构建 AB 后产生的文件

AssetBundle 文件

文件使用自定义后缀,包含在运行时为了加载资源而需要加载的内容。

此包的结构根据它是 AssetBundle 还是场景 AssetBundle 可能会略有不同。

  • 普通 AssetBundle 的结构:
    mark

  • 场景 AssetBundle 与普通 AssetBundle 的不同之处在于,它针对场景及其内容的串流加载进行了优化。

Manifest 清单文件

对于生成的每个 AB 包,都会生成关联的清单文件。清单文件包含诸如 循环冗余校验 (CRC) 数据 和 包的依赖性数据 等信息。

对于普通 AssetBundle,它们的清单文件将如下所示:

AssetBundles.manifest – AB 包的清单文件

ManifestFileVersion: 0
CRC: 4225903359
AssetBundleManifest:
  AssetBundleInfos:
    Info_0:
      Name: share.u3d
      Dependencies: {}
    Info_1:
      Name: cubewall.u3d
      Dependencies:
        Dependency_0: share.u3d
    Info_2:
      Name: spherewall.u3d
      Dependencies:
        Dependency_0: share.u3d

share.u3d.manifest – 包含贴图资源

ManifestFileVersion: 0
CRC: 4044919538
Hashes:
  AssetFileHash:
    serializedVersion: 2
    Hash: db0f6906b386d5d4413b2ddd1d9a6c61
  TypeTreeHash:
    serializedVersion: 2
    Hash: 6f165f44e4778b6c9d85e7a145a54cb1
HashAppended: 0
ClassTypes:
- Class: 21
  Script: {instanceID: 0}
- Class: 28
  Script: {instanceID: 0}
- Class: 48
  Script: {instanceID: 0}
Assets:
- Assets/Materials/Stone_floor_09.png
- Assets/Materials/Stone_floor_09.mat
Dependencies: []

cubewall.u3d.manifest – 依赖于 share

ManifestFileVersion: 0
CRC: 2862441256
Hashes:
  AssetFileHash:
    serializedVersion: 2
    Hash: 6e48f6b8e6cedd4070323880d839a3ee
  TypeTreeHash:
    serializedVersion: 2
    Hash: f49f05f36a566d50434f7d9f3fb347da
HashAppended: 0
ClassTypes:
- Class: 1
  Script: {instanceID: 0}
- Class: 4
  Script: {instanceID: 0}
- Class: 21
  Script: {instanceID: 0}
- Class: 23
  Script: {instanceID: 0}
- Class: 33
  Script: {instanceID: 0}
- Class: 43
  Script: {instanceID: 0}
- Class: 65
  Script: {instanceID: 0}
Assets:
- Assets/Prefabs/CubeWall.prefab
Dependencies:
- G:/UnityDocuments/AssetBundle/Assets/AssetBundles/share.u3d

AB 依赖

依赖打包

把共享资源放在一个包里,以节约空间。

mark

加载依赖

如果 AssetBundle 中包含依赖项,则在加载尝试实例化的对象之前,务必加载包含这些依赖项的AB包。Unity 不会自动加载依赖项。

参考以下示例,a 中的材质引用了 b 中的纹理,加载 a 和 b 的顺序无关紧要,重要的是在使用 a 中的材质前应加载 b。

在此示例中,在从 a 加载材质之前,需要将 b 加载到内存中。加载 a 和 b 的顺序无关紧要,重要的是在使用 a 中的材质前应加载 b。

mark

 private void Start() { 
   
     AssetBundle.LoadFromFile("Assets/AssetBundles/share.u3d"); // 加载依赖包
     AssetBundle ab = AssetBundle.LoadFromFile("Assets/AssetBundles/cubewall.u3d");

     var wallPre = ab.LoadAsset<GameObject>("CubeWall");
	 Instantiate(wallPre); // 实例化物体
 }

[当 AB 包存在依赖关系时,如何知道在加载原始包的资源前,需要加载哪些依赖包?](#加载 AssetBundle 清单)

AssetBundles 的具体使用

加载 AB

根据 AssetBundle 是以什么样的形式提供的,而选择具体的加载方式。

  • AssetBundle.LoadFromMemoryAsync
    • 字节数组
    • 从内存里加载
  • AssetBundle.LoadFromFile
    • 从本地加载
  • WWW.LoadFromCacheOrDownload (弃用)
  • UnityWebRequest
    • 从远程服务器加载

AssetBundle.LoadFromMemoryAsync

此函数采用包含 AssetBundle 数据的字节数组。也可以根据需要传递 CRC 值。如果捆绑包采用的是 LZMA 压缩方式,将在加载时解压缩 AssetBundle。LZ4 压缩包则会以压缩状态加载。

using System.Collections;
using System.IO;
using UnityEngine;

public class LoadFromFileExample : MonoBehaviour { 
   

    private void Start() { 
   
        StartCoroutine(LoadFromMemoryAsync("Assets/AssetBundles/cubewall.u3d"));
    }

    IEnumerator LoadFromMemoryAsync(string path) { 
   
        // 加载 AB
        AssetBundleCreateRequest createRequest = AssetBundle.LoadFromMemoryAsync(File.ReadAllBytes(path)); // 字节数组
        yield return createRequest;
        AssetBundle bundle = createRequest.assetBundle;
        // 使用里面的资源
        var prefab = bundle.LoadAsset<GameObject>("CubeWall");
        Instantiate(prefab);
    }
}

AssetBundle.LoadFromFile

  • 如果AB未压缩或采用了数据块 (LZ4) 压缩方式,LoadFromFile 将直接从磁盘加载AB包。
  • 加载完全压缩的 (LZMA) AB包将首先解压缩捆绑包,然后再将其加载到内存中。
using System.Collections;
using System.IO;
using UnityEngine;

public class LoadFromFileExample : MonoBehaviour { 
   

    private void Start() { 
   
        StartCoroutine(LoadFromFile("Assets/AssetBundles/cubewall.u3d"));
    }

    IEnumerator LoadFromFile(string path) { 
   
        // 加载 AB
        AssetBundleCreateRequest createRequest = AssetBundle.LoadFromFileAsync("Assets/AssetBundles/cubewall.u3d");
        yield return createRequest; // 等待加载完成
        AssetBundle ab = createRequest.assetBundle;
        // 使用里面的资源
        var prefab = ab.LoadAsset<GameObject>("CubeWall");
        Instantiate(prefab);
    }
}

UnityWebRequest

从远程服务器加载 AssetBundle

using System.Collections;
using System.IO;
using UnityEngine;
using UnityEngine.Networking;

public class LoadFromFileExample : MonoBehaviour { 
   

    private void Start() { 
   
        StartCoroutine(InstantiateObject());
    }

    IEnumerator InstantiateObject() { 
   
        // 加载 AB
        //string uri = @"http://127.0.0.1/AssetBundles/cubewall.u3d";
        string uri = "file:///G:/UnityDocuments/AssetBundle/Assets/AssetBundles/cubewall.u3d";
        UnityWebRequest request = UnityWebRequest.GetAssetBundle(uri, 0);
        yield return request.SendWebRequest();
        AssetBundle ab = DownloadHandlerAssetBundle.GetContent(request);
        // 使用里面的资源
        var prefab = ab.LoadAsset<GameObject>("CubeWall");
        Instantiate(prefab);
    }
}

从 AB 加载资源

通用代码片段:

// T 是尝试加载的资源类型
T objectFromBundle = bundleObject.LoadAsset<T>(assetName);

同步加载方式:

// 加载单个游戏对象
GameObject gameObject = loadedAssetBundle.LoadAsset<GameObject>(assetName);

// 加载所有资源
Unity.Object[] objectArray = loadedAssetBundle.LoadAllAssets();

异步加载方式:

// 加载单个游戏对象
AssetBundleRequest request = loadedAssetBundleObject.LoadAssetAsync<GameObject>(assetName);
yield return request;
var loadedAsset = request.asset;

// 加载所有资源
AssetBundleRequest request = loadedAssetBundle.LoadAllAssetsAsync();
yield return request;
var loadedAssets = request.allAssets;

加载 AssetBundle 清单

当 AB 包存在依赖关系时,如何知道在加载原始包的资源前,需要加载哪些依赖包?

可以通过 Manifest 文件得到某个包的依赖,清单对象可以动态地查找加载依赖项。

using System.Collections;
using System.IO;
using UnityEngine;
using UnityEngine.Networking;

public class LoadFromFileExample : MonoBehaviour { 
   
    private void Start() { 
   
        // 加载 ab 包
        AssetBundle manifestAB = AssetBundle.LoadFromFile("Assets/AssetBundles/AssetBundles");
        // 加载清单文件
        AssetBundleManifest manifest = manifestAB.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
        // 加载 ab 的所有依赖项
        string[] dependencies = manifest.GetAllDependencies("wall.u3d");
        foreach (string dependency in dependencies) { 
   
            print(dependency);
            AssetBundle.LoadFromFile("Assets/AssetBundles/" + dependency);
        }
        // 加载资源
        AssetBundle ab = AssetBundle.LoadFromFile("Assets/AssetBundles/wall.u3d");
        var wallPre = ab.LoadAsset<GameObject>("CubeWall");
        // 实例化物体
        Instantiate(wallPre); 
    }
}

AssetBundle 的卸载

了解何时加载和卸载 AssetBundle 非常重要。不正确地卸载 AssetBundle 会导致在内存中复制对象或其他不良情况,例如缺少纹理。

// 卸载 AssetBundle
AssetBundle.Unload(bool); 

AssetBundle.Unload(true)

  • 卸载所有资源,即使有资源被使用着
  • 卸载从 AssetBundle 加载的所有游戏对象(及其依赖项)。这不包括复制的游戏对象(例如实例化的游戏对象),因为它们不再属于 AssetBundle。
  • 采用此种方式卸载,从该 AssetBundle 加载的纹理(并且仍然属于它)会从场景中的游戏对象消失,因此 Unity 将它们视为缺少纹理。

AssetBundle.Unload(false)

  • 卸载所有没用被使用的资源
  • 此种方式可能会在内存中产生大量复制对象

如何选择用哪种方式

假设材质 M 是从 AssetBundle AB 加载的,如下所示。

  • 如果调用 AB.Unload(true),活动场景中的任何 M 实例也将被卸载并销毁。
  • 如果改作调用 AB.Unload(false),那么将会中断 M 和 AB 当前实例的链接关系。

mark

通常,使用 AssetBundle.Unload(false) 不会带来理想情况。大多数项目应该使用 AssetBundle.Unload(true) 来防止在内存中复制对象。

大多数项目应该使用 AssetBundle.Unload(true) 并采用一种方法来确保对象不会重复。两种常用方法是:

  • 在应用程序生命周期中具有明确定义的卸载瞬态 AssetBundle 的时间点,例如在关卡之间或在加载屏幕期间。
  • 维护单个对象的引用计数,仅当未使用所有组成对象时才卸载 AssetBundle。这允许应用程序卸载和重新加载单个对象,而无需复制内存。

如果应用程序必须使用 AssetBundle.Unload(false),则只能以两种方式卸载单个对象:

  • 在场景和代码中消除对不需要的对象的所有引用。
  • 以非附加方式加载场景。

修补 AssetBundle

修补 AssetBundle 很简单,只需要下载新的 AssetBundle 并替换现有的 AssetBundle。

如果使用 UnityWebRequest 来管理应用程序的缓存 AssetBundle,则将不同的版本参数传递给所选 API 将触发新 AssetBundle 的下载。

在修补系统中要解决的更难的问题是检测要替换的 AssetBundle。修补系统需要两个信息列表:

  • 当前已下载的 AssetBundle 及其版本控制信息的列表
  • 服务器上的 AssetBundle 及其版本控制信息的列表

修补程序应下载服务器端 AssetBundle 列表并比较这些 AssetBundle 列表。应重新下载缺少的 AssetBundle 或已更改版本控制信息的 AssetBundle。

也可以编写一个自定义系统来检测 AssetBundle 的更改。自己编写系统的大多数开发人员会选择对 AssetBundle 文件列表使用行业标准数据格式(例如 JSON)和并使用标准 c sharp 类(例如 MD5)来计算校验和。

常见问题

依赖包重复问题

  • 把需要共享的资源打包到一起
  • 分割包,这些包不是在同一时间使用的
  • 把共享部分打包成一个单独的包

图集重复问题

若不指定 Sprite 的 Packing Tag ,这些 Sprite 将会被自动打包在一个图集里面。

假如 a 包使用了这个图集里的一张图片,那么这个图集就会被打包在 a 包里面,如果 b 包也使用了图集里的一张图片,那么这个图集也会被打包在 b 包里面,这样一来就产生了图集的重复问题。

为了确保精灵图集不重复,请确保将相同精灵图集的所有精灵分配到同一个 AssetBundle。

Android 贴图问题

由于 Android 生态系统中存在严重的设备碎片,因此通常需要将纹理压缩为多种不同的格式。虽然所有 Android 设备都支持 ETC1,但 ETC1 不支持具有 Alpha 通道的纹理。如果应用程序不需要 OpenGL ES 2 支持,解决该问题的最简单方法是使用所有 Android OpenGL ES 3 设备都支持的 ETC2。

解决这个问题的一种方法是使用 Unity 5 的 AssetBundle 变体。(有关其他方案的详细信息,请参阅 Unity 的 Android 优化指南。)

Unity Asset Bundle Browser 工具

下载后,直接将 Editor 文件夹放在自己的项目目录下,此工具使用户能够查看和编辑 Unity 项目的资源包的配置。此工具将在 Window 菜单下创建 AssetBundle Browser 菜单项。

此窗口提供了一个类似资源管理器的界面,用于管理和修改项目中的资源包。

mark

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/148014.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 在安装twincat plc时,出现 there are some files marked for deletion on next reboot.please reboot first then

    在安装twincat plc时,出现 there are some files marked for deletion on next reboot.please reboot first then

    2022年2月1日
    46
  • 《王道》数据结构笔记整理2022级_数据结构笔记整理

    《王道》数据结构笔记整理2022级_数据结构笔记整理数据结构第一章绪论1.1数据结构的基本概念1.2数据结构的三要素1.3算法的基本概念1.4算法的时间复杂度1.5算法的空间复杂度第一章绪论1.1数据结构的基本概念1.数据:数据是信息的载体,是描述客观事物属性的数、字符以及所有能输入到计算机中并被程序识别和处理的符号的集合。2.数据元素:数据元素是数据的基本单位,通常作为一个整体进行考虑和处理。一个数据元素可由若干数据项组成,数据项是构成数据元素的不可分割的最小单位。例如,学生记录就是一个数据元素,它由学号、姓名、性别等数据项组成。3.数据对象:数

    2022年8月23日
    17
  • Redis Sentinel实现的机制与原理详解

    Redis Sentinel实现的机制与原理详解

    2022年3月2日
    39
  • touchstart和click 自动区分

    touchstart和click 自动区分varclickEvent=(function(){if(‘ontouchstart’indocument.documentElement===true)return’touchstart’;elsereturn’click’;})();转载于:https://www.cnblogs.com/gaidalou/p/9927885.html

    2022年6月19日
    29
  • 云服务器和虚拟主机的区别

    云服务器和虚拟主机的区别云服务器和虚拟主机的区别:1、技术原理:云服务器是基于庞大的服务器资源池,是在一组集群主机上虚拟出多个类似独立主机的部分,集群中每个主机上都有云服务器的一个镜像;虚拟主机是服务器划分出的一部分,因此也叫做虚拟空间,在服务器当中划分出一定的磁盘空间放置web程序组件,提供数据的存放和传输功能。2、可用资源:云服务器是独享资源,具有独立的CPU、内存、硬盘和ip等;虚拟主机则是众多网站空间共享一台物理服务器的资源。3、主机费用:由于虚拟主机是多个空间分享一台服务器的带宽、IP等资源,费用低廉,价格比云服

    2022年6月25日
    33
  • 通过逆向分析防御挖矿病毒「建议收藏」

    通过逆向分析防御挖矿病毒「建议收藏」转载于:https://www.freebuf.com/articles/network/163233.html前言:因为这次是从应急响应引出的,所以我将侧重点放在分析病毒本身的存储方式和传播途径,靠逆向分析出防护策略用于帮助后续的应急响应/系统加固/运维。情况概述:最近接到用户的应急响应请求,用户的描述是服务器从前2天开始不定时重启。抵达现场初看没发现什么端倪,杀毒软件没有报毒,…

    2022年6月6日
    32

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号