openstack storlet 文档(七):storlet编写和部署向导

来源:互联网 发布:工程设计软件有哪些 编辑:程序博客网 时间:2024/05/21 06:15

Storlet writing and deploying guide

Storlet可以用Java或Python编写。 本指南是一个与语言无关的用于编写和部署storlet起点。 Java和Python的具体指南会补充本指南,并应在此之后阅读。

编写一个storlet涉及实现一个称为invoke的函数(确切的名称因语言而异)。

通常,the invoke操作会获取一个输入流和一个输出流。输入流将包含正在上传的数据(在上传期间调用storlet的case中)或正在下载的数据(在下载过程中进行调用时)。输入流伴随着元数据,它会反映Swift用户定义的元数据。输出流公开了一种方式,不仅可以写回storlet输出数据,还可以写回元数据。输入和输出流以一种所使用语言的native的方式暴露给storlet代码。

一旦storlet被编写和测试,它可以作为对象上传到指定的容器(默认名为“storlet”)。还可以上传Storlet代码外部依赖关系,如Java库或Python模块。然而,它假设storlet dependencies相对较小(大约数MB)。更重要的依赖应该是对Docker image的一部分。部署存储库和依赖关系包括如下。

StorletSamples/java和StorletSamples/python目录中有storlets各种各样的实现。 这些storlets被用于引擎的functional tests。

接下来的两个部分描述了与所使用语言的独立的storlet编写和部署指南。
独立于编写语言来编写storlet,有几个指导要遵循。 其中一些是必须的,一些是建议。

Recommendations

  1. Storlet专为流处理而设计,即它们在读取时处理输入,并在读取时产生输出。 换句话说,*对象的内容的“合并排序”不是一个很好的示例*,因为它需要将所有内容读入内存(随机读取不是一个选项,因为输入是以流的形式提供)。 虽然我们目前不对storlet的CPU使用情况或内存消耗采取任何限制,但是将大型对象读入内存或进行非常密集的计算会对整体系统性能产生影响。
  2. 虽然这可能是显而易见的,确保在部署之前对其进行单元测试。

Musts

  1. storlet代码必须是线程安全的并且是重新进入的(re-enterant)。invoke方法将被多次调用并且可能并行。
  2. 一旦存储器完成写入response,关闭输出流非常重要。否则将导致超时
  3. 一个storlet必须在调用后40秒内开始响应。否则,Swift会超时。此外,storlet必须每40秒输出一次,以免超时。这是一种机制,可以确保这些代码不会卡住。请注意,输出空字符串不会重置40秒超时。
  4. storlet必须将元数据写入输出流,并且必须在开始流出数据之前进行。典型的实现是读取输入元数据并将其用作正在写入的元数据的基础。请注意这里40秒超时的适用性。
  5. 可以设置的元数据的总大小(串行化为字符串时)不得超过4096字节
  6. 虽然Swift使用前缀X-Object-Meta来指定某个头部以反映元数据key,但key本身不应以该前缀开头。更具体地说,由storlet设置的元数据key不应该具有该前缀(除非这真的是key的一部分)

Storlet部署基本上是将该库及其依赖关系上传到您正在使用的帐户中的指定容器中。 虽然storlet和依赖是常规的Swift对象,但它们必须携带一些元数据以供storlet引擎使用。 当一个storlet首次执行时,引擎从Swift中获取必要的对象,并将它们放在Docker容器可访问的目录中 请注意,依赖are meant to be很小。 拥有大量的依赖关系或非常大的依赖关系可能会导致在首次尝试执行storlet时超时。 如果发生这种情况,只需重新发送请求。

我们支持两种dependencies:
1. native的storlet语言的外部库或模块(External libraries or modules that are native to the storlet langauge )
2. 可执行的依赖,即可以执行的storlet代码。( Executables dependency that the storlet code can execute. )

Storlet Object Metadata

上传一个storlet必须是对指定的容器进行上传,这个容器默认为“storlet”。 上传的对象必须携带以下元数据。 有关详细信息,请参阅具体的语言指南。

X-Object-Meta-Storlet-Language - must be 'python' or 'java'X-Object-Meta-Storlet-Interface-Version - currenltly we have a single version '1.0'X-Object-Meta-Storlet-Object-Metadata - Currently, not in use, but must appear. Use the value 'no'X-Object-Meta-Storlet-Main - The name of the class that implements the invoke operation

可选的metadata选项为:

X-Object-Meta-Storlet-Dependency - A comma separated list of dependencies.

如果希望更新storlet,只需再次上传,引擎将识别更新并提供更新的代码。

Dependency Object Metadata

上传一个dependency必须对指定的容器执行上传,默认情况下称为“dependency”。上传的对象必须携带以下元数据

X-Object-Meta-Storlet-Dependency-Version - While the engine currently does not parse this header, it must appear.

可选的元数据项为:

X-Object-Meta-Storlet-Dependency-Permissions - The permissions given to the dependency when it is copied to theDocker container. This is helpful for binary dependencies invoked by the storlet.For a binary dependency once can specify: '0755'

Note: 目前,无法识别dependency更新。

Deploying a Storlet using Swift Client cli

下面我们将展示如何使用Swift客户端cli来部署一个storlet。 该示例使用Java storlet。 部署Python storlet的区别很小,我们会在需要的地方突出显示它们。

当使用Swift client时,需要提供证书以及验证URI。 凭证可以通过环境变量或命令行参数提供。 为了使命令更加可读,我们使用环境变量,如下所示。 实际值与开发环境安装说明一致

export OS_USERNAME=testerexport OS_PASSWORD=testingexport OS_TENANT_NAME=testexport OS_AUTH_URL=http://127.0.0.1:5000/v2.0

以下是Swift客户端命令,用于上传这些存储库。 一些notes如下:
1. 我们使用swift cli的上传选项。
2. 容器名称是upload命令的第一个参数,是’storlet’
3. 要上载的对象的名称和本地文件是’identitystorelt-1.0-jar’。重要提示:当从另一个目录上传文件时,该参数在这种情况下将是“bin/identitystorelt-1.0-jar”的形式出现在storlet容器中,对象的名称为“bin/identitystorelt-1.0-jar”时,这对引擎不起作用。
4. storlet对象上需要附带的元数据是以headers来提供。

eranr@lnx-ccs8:~/workspace/Storlets/StorletSamples/IdentityStorlet/bin$ swift upload storlet identitystorlet-1.0.jar \-H "X-Object-Meta-Storlet-Language:Java" \-H "X-Object-Meta-Storlet-Interface-Version:1.0" \-H "X-Object-Meta-Storlet-Object-Metadata:no" \-H "X-Object-Meta-Storlet-Main:org.openstack.storlet.identity.IdentityStorlet" \-H "X-Object-Meta-Storlet-Dependency:get42"

Note: 当部署一个Python storlet时,该对象的名称(以上的identitystorlet-1.0.jar)具有不同的格式,“X-Object-Meta-Storlet-Language”是“Python”,“X-Object-Meta- Storlet-Main“格式不同。 请参考Python的具体细节。

这是用于上传get42依赖关系的Swift客户端命令。 一些注释:
1. 这里使用的容器名称是upload命令的第一个参数,是’dependency’。
2. 我们使用可选的权限头部,因为这是一个二进制文件。

eranr@lnx-ccs8:~/workspace/Storlets/StorletSamples/IdentityStorlet/bin$ swift upload dependency get42 \-H "X-Object-Meta-Storlet-Dependency-Version:1.0" \-H "X-Object-Meta-Storlet-Dependency-Permissions:0755"

Deploying a Storlet using the Python Swift Client

这是一个代码片段,可以同时上传storlet以及dependencies。 该代码假定用v2进行身份验证,并针对Swift集群进行了测试:
1. Keystone配置了一个“test”帐户,有一个user ‘tester’,其密码为’testing’
2. 在service帐户下,已经有’storlet’和’dependency’容器。
该示例使用Java storlet。 与部署Python storlet的区别很小,与上面使用Swift客户端部分部署中突出显示的差异相同。

from swiftclient import clientdef put_storlet_object(url, token, storlet_name, local_path_to_storlet, main_class_name, dependencies):    # Delete previous storlet    resp = dict()    metadata = {'X-Object-Meta-Storlet-Language':'Java',                'X-Object-Meta-Storlet-Interface-Version':'1.0',                'X-Object-Meta-Storlet-Dependency': dependencies,                'X-Object-Meta-Storlet-Object-Metadata':'no',                'X-Object-Meta-Storlet-Main': main_class_name}    f = open('%s/%s' % (local_path_to_storlet, storlet_name), 'r')    content_length = None    response = dict()    client.put_object(url, token, 'storlet', storlet_name, f,                      content_length, None, None,                      "application/octet-stream",                      metadata,                      None, None, None,                      response)    print response    f.close()def put_storlet_dependency(url, token, dependency_name, local_path_to_dependency):    metadata = {'X-Object-Meta-Storlet-Dependency-Version': '1'}    # for an executable dependency    # metadata['X-Object-Meta-Storlet-Dependency-Permissions'] = '0755'    f = open('%s/%s'% (local_path_to_dependency, dependency_name), 'r')    content_length = None    response = dict()    client.put_object(url, token, 'dependency', dependency_name, f,                      content_length, None, None,                      "application/octet-stream",                      metadata,                      None, None, None,                      response)    print response    f.close()    status = response.get('status')    assert (status == 200 or status == 201)AUTH_IP = '127.0.0.1'AUTH_PORT = '5000'ACCOUNT = 'test'USER_NAME = 'tester'PASSWORD = 'testing'os_options = {'tenant_name': ACCOUNT}url, token = client.get_auth("http://" + AUTH_IP + ":" + AUTH_PORT + "/v2.0", ACCOUNT +":"+USER_NAME,                             PASSWORD,                             os_options = os_options,                             auth_version="2.0")put_storlet_object(url, token,'identitystorlet-1.0.jar','/tmp',                   'org.openstack.storlet.identity.IdentityStorlet',                   'get42')put_storlet_dependency(url, token,'get42','/tmp')