xml地图|网站地图|网站标签 [设为首页] [加入收藏]
澳门新葡亰手机版Alamofire框架的使用二,每天5分
分类:编程

 

Alamofire是在URLSession和URL加载系统的基础上写的。所以,为了更好地学习这个框架,建议先熟悉下列几个底层网络协议栈:

service 的容器副本会 scale up/down,会 failover,会在不同的主机上创建和销毁,这就引出一个问题,如果 service 有要管理的数据,那么这些数据应该如何存放呢?

之前介绍了Docker集群管理工具-Kubernetes部署记录,下面介绍另一个管理工具Swarm的用法,Swarm是Docker原生的集群管理软件,与Kubernetes比起来比较简单。

  • URL Loading System Programming Guide >>
  • URLSession Class Reference >>
  • URLCache Class Reference >>
  • URLAuthenticationChallenge Class Reference >>

选项一:打包在容器里。

Swarm介绍

Session Manager

高级别的方便的方法,例如Alamofire.request,使用的是默认的Alamofire.SessionManager,并且这个SessionManager是用默认URLSessionConfiguration配置的。

例如,下面两个语句是等价的:

Alamofire.request("https://httpbin.org/get")

let sessionManager = Alamofire.SessionManager.default
sessionManager.request("https://httpbin.org/get")

我们可以自己创建后台会话和短暂会话的session manager,还可以自定义默认的会话配置来创建新的session manager,例如修改默认的header httpAdditionalHeaderstimeoutIntervalForRequest

显然不行。除非数据不会发生变化,否则,如何在多个副本直接保持同步呢?

Swarm是Docker公司在2014年12月初发布的一套较为简单的工具,用来管理Docker集群,它将一群Docker宿主机变成一个单一的,虚拟的主机。Swarm使用标准的Docker API接口作为其前端访问入口,换言之,各种形式的Docker Client(docker client in Go, docker_py, docker等)均可以直接与Swarm通信。Swarm几乎全部用Go语言来完成开发,Swarm0.2版本增加了一个新的策略来调度集群中的容器,使得在可用的节点上传播它们,以及支持更多的Docker命令以及集群驱动。Swarm deamon只是一个调度器(Scheduler)加路由器(router),Swarm自己不运行容器,它只是接受docker客户端发送过来的请求,调度适合的节点来运行容器,这意味着,即使Swarm由于某些原因挂掉了,集群中的节点也会照常运行,当Swarm重新恢复运行之后,它会收集重建集群信息。

用默认的会话配置创建一个Session Manager

let configuration = URLSessionConfiguration.default
let sessionManager = Alamofire.SessionManager(configuration: configuration)

选项二:数据放在 Docker 主机的本地目录中,通过 volume 映射到容器里。

Docker的Swarm(集群)模式,集成很多工具和特性,比如:跨主机上快速部署服务,服务的快速扩展,集群的管理整合到docker引擎,这意味着可以不可以不使用第三方管理工具。分散设计,声明式的服务模型,可扩展,状态协调处理,多主机网络,分布式的服务发现,负载均衡,滚动更新,安全(通信的加密)等等,下面就来认识下Swarm(对于Swarm管理的详细操作可以参考:)

用后台会话配置创建一个Session Manager

let configuration = URLSessionConfiguration.background(withIdentifier: "com.example.app.background")
let sessionManager = Alamofire.SessionManager(configuration: configuration)

位于同一个主机的副本倒是能够共享这个 volume,但不同主机中的副本如何同步呢?

Swarm架构

用默短暂会话配置创建一个Session Manager

let configuration = URLSessionConfiguration.ephemeral
let sessionManager = Alamofire.SessionManager(configuration: configuration)

选项三:利用 Docker 的 volume driver,由外部 storage provider 管理和提供 volume,所有 Docker 主机 volume 将挂载到各个副本。

Swarm作为一个管理Docker集群的工具,首先需要将其部署起来,可以单独将Swarm部署于一个节点。另外,自然需要一个Docker集群,集群上每一个节点均安装有Docker。具体的Swarm架构图可以参照下图:

修改会话配置

var defaultHeaders = Alamofire.SessionManager.defaultHTTPHeaders
defaultHeaders["DNT"] = "1 (Do Not Track Enabled)"

let configuration = URLSessionConfiguration.default
configuration.httpAdditionalHeaders = defaultHeaders

let sessionManager = Alamofire.SessionManager(configuration: configuration)

注意:不推荐在Authorization或者Content-Type header使用。而应该使用Alamofire.requestAPI、URLRequestConvertibleParameterEncoding的headers参数。

这是目前最佳的方案。volume 不依赖 Docker 主机和容器,生命周期由 storage provider 管理,volume 的高可用和数据有效性也全权由 provider 负责,Docker 只管使用。

澳门新葡亰手机版 1

会话代理

默认情况下,一个SessionManager实例创建一个SessionDelegate对象来处理底层URLSession生成的不同类型的代理回调。每个代理方法的实现处理常见的情况。然后,高级用户可能由于各种原因需要重写默认功能。

我们将以 Rex-Ray 为例来实践第三种方案。

Swarm架构中最主要的处理部分自然是Swarm节点,Swarm管理的对象自然是Docker Cluster,Docker Cluster由多个Docker Node组成,而负责给Swarm发送请求的是Docker Client。

重写闭包

第一种自定义SessionDelegate的方法是通过重写闭包。我们可以在每个闭包重写SessionDelegate API对应的实现。下面是重写闭包的示例:

/// 重写URLSessionDelegate的`urlSession(_:didReceive:completionHandler:)`方法
open var sessionDidReceiveChallenge: ((URLSession, URLAuthenticationChallenge) -> (URLSession.AuthChallengeDisposition, URLCredential?))?

/// 重写URLSessionDelegate的`urlSessionDidFinishEvents(forBackgroundURLSession:)`方法 
open var sessionDidFinishEventsForBackgroundURLSession: ((URLSession) -> Void)?

/// 重写URLSessionTaskDelegate的`urlSession(_:task:willPerformHTTPRedirection:newRequest:completionHandler:)`方法 
open var taskWillPerformHTTPRedirection: ((URLSession, URLSessionTask, HTTPURLResponse, URLRequest) -> URLRequest?)?

/// 重写URLSessionDataDelegate的`urlSession(_:dataTask:willCacheResponse:completionHandler:)`方法 
open var dataTaskWillCacheResponse: ((URLSession, URLSessionDataTask, CachedURLResponse) -> CachedURLResponse?)?

下面的示例演示了如何使用taskWillPerformHTTPRedirection来避免回调到任何apple.com域名。

let sessionManager = Alamofire.SessionManager(configuration: URLSessionConfiguration.default)
let delegate: Alamofire.SessionDelegate = sessionManager.delegate

delegate.taskWillPerformHTTPRedirection = { session, task, response, request in
    var finalRequest = request

    if
        let originalRequest = task.originalRequest,
        let urlString = originalRequest.url?.urlString,
        urlString.contains("apple.com")
    {
        finalRequest = originalRequest
    }

    return finalRequest
}

Rex-Ray

Rex-Ray 是开源的容器存储管理解决方案。支持主流的容器编排引擎 Docker Swarm、 Kubernetes 和 Mesos,为容器集群提供自动化的存储编排功能。

在《每天5分钟玩转Docker容器技术》的数据管理章节中已经详细讨论了 Rex-Ray 如何跨 Docker 主机管理 data volume,本节内容也是建立在这些基础知识之上。为节省篇幅,建议大家先阅读这些内容,然后回到这里继续实践。

我们将在部署如下的 Rex-Ray 实验环境:

澳门新葡亰手机版 2

  1. swarm 中的所有 node 都安装部署 Rex-Ray。

  2. Rex-Ray 使用 VirtualBox backend。

  3. 具体的安装部署方法请参考前面 Docker 数据管理章节,这里不再赘述。

Swarm关键概念

子类化

另一个重写SessionDelegate的实现的方法是把它子类化。通过子类化,我们可以完全自定义他的行为,或者为这个API创建一个代理并且仍然使用它的默认实现。通过创建代理,我们可以跟踪日志事件、发通知、提供前后实现。下面这个例子演示了如何子类化SessionDelegate,并且有回调的时候打印信息:

class LoggingSessionDelegate: SessionDelegate {
    override func urlSession(
        _ session: URLSession,
        task: URLSessionTask,
        willPerformHTTPRedirection response: HTTPURLResponse,
        newRequest request: URLRequest,
        completionHandler: @escaping (URLRequest?) -> Void)
    {
        print("URLSession will perform HTTP redirection to request: (request)")

        super.urlSession(
            session,
            task: task,
            willPerformHTTPRedirection: response,
            newRequest: request,
            completionHandler: completionHandler
        )
    }
}

总的来说,无论是默认实现还是重写闭包,都应该提供必要的功能。子类化应该作为最后的选择。

实践

接下来,我们将:

  1. 创建 httpd 服务,并使用 Rex-Ray data volume。

  2. 修改 volume 中的数据,并验证更新同步到所有副本。

  3. 验证 failover 发生时,更新的数据不会丢失。

1)Swarm
集群的管理和编排是使用嵌入到docker引擎的SwarmKit,可以在docker初始化时启动swarm模式或者加入已存在的swarm

2)Node
一个节点(node)是已加入到swarm的Docker引擎的实例 当部署应用到集群,你将会提交服务定义到管理节点,接着Manager
管理节点调度任务到worker节点,manager节点还执行维护集群的状态的编排和群集管理功能,worker节点接收并执行来自
manager节点的任务。通常,manager节点也可以是worker节点,worker节点会报告当前状态给manager节点

3)服务(Service)
服务是要在worker节点上要执行任务的定义,它在工作者节点上执行,当你创建服务的时,你需要指定容器镜像

4)任务(Task)
任务是在docekr容器中执行的命令,Manager节点根据指定数量的任务副本分配任务给worker节点

--------------------------------------------------------------------------------------------------------
docker swarm:集群管理,子命令有init, join, leave, update。(docker swarm --help查看帮助)
docker service:服务创建,子命令有create, inspect, update, remove, tasks。(docker service--help查看帮助)
docker node:节点管理,子命令有accept, promote, demote, inspect, update, tasks, ls, rm。(docker node --help查看帮助)

node是加入到swarm集群中的一个docker引擎实体,可以在一台物理机上运行多个node,node分为:
manager nodes,也就是管理节点
worker nodes,也就是工作节点

1)manager node管理节点:执行集群的管理功能,维护集群的状态,选举一个leader节点去执行调度任务。
2)worker node工作节点:接收和执行任务。参与容器集群负载调度,仅用于承载task。
3)service服务:一个服务是工作节点上执行任务的定义。创建一个服务,指定了容器所使用的镜像和容器运行的命令。
   service是运行在worker nodes上的task的描述,service的描述包括使用哪个docker 镜像,以及在使用该镜像的容器中执行什么命令。
4)task任务:一个任务包含了一个容器及其运行的命令。task是service的执行实体,task启动docker容器并在容器中执行任务。

请求

requestdownloaduploadstream方法的结果是DataRequestDownloadRequestUploadRequestStreamRequest,并且所有请求都继承自Request。所有的Request并不是直接创建的,而是由session manager创建的。

每个子类都有特定的方法,例如authenticatevalidateresponseJSONuploadProgress,都返回一个实例,以便方法链接(也就是用点语法连续调用方法)。

请求可以被暂停、恢复和取消:

  • suspend():暂停底层的任务和调度队列
  • resume():恢复底层的任务和调度队列。如果manager的startRequestsImmediately不是true,那么必须调用resume()来开始请求。
  • cancel():取消底层的任务,并产生一个error,error被传入任何已经注册的响应handlers。
创建 service

执行如下命令:

 

docker service create --name my_web 
       --publish 8080:80 
       --mount "type=volume,volume-driver=rexray,source=web_data,target=/usr/local/apache2/htdocs" 
       httpd

 

  1. --mount 指定数据卷的 volume-driver 为 rexray

  2. source 指定数据卷的名字为 web_data,如果不存在,则会新建。

  3. target 指定将数据卷 mount 到每个副本容器的 /usr/local/apache2/htdocs,即存放静态页面的目录。

澳门新葡亰手机版 3

 

访问 service:

澳门新葡亰手机版 4

权限有些问题,需要进容器修改 /usr/local/apache2/htdocs 的权限。

澳门新葡亰手机版 5

service 已经可以访问了:

澳门新葡亰手机版 6

当前 Rex-Ray volume web_data 被挂载到 node swarm-worker1

澳门新葡亰手机版 7

mount 到 /var/lib/libstorage/volumes/web_data/data 目录。

澳门新葡亰手机版 8

通过 docker inspect my_web.1.2j7dgzuyk9hodseej707t97su 可以确认 /var/lib/libstorage/volumes/web_data/data 已经映射到容器目录 /usr/local/apache2/htdocs

澳门新葡亰手机版 9

当前的实验环境如图所示:

澳门新葡亰手机版 10

下一节我们验证在故障情况 Volume 的持久性。

澳门新葡亰手机版 11书籍:

1.《每天5分钟玩转Docker容器技术》

2.《每天5分钟玩转OpenStack》

澳门新葡亰手机版 12

Swarm工作方式

传送请求

随着应用的不多增大,当我们建立网络栈的时候要使用通用的模式。在通用模式的设计中,一个很重要的部分就是如何传送请求。遵循Router设计模式的URLConvertibleURLRequestConvertible协议可以帮助我们。

1)Node

URLConvertible

遵循了URLConvertible协议的类型可以被用来构建URL,然后用来创建URL请求。StringURLURLComponent默认是遵循URLConvertible协议的。它们都可以作为url参数传入requestuploaddownload方法:

let urlString = "https://httpbin.org/post"
Alamofire.request(urlString, method: .post)

let url = URL(string: urlString)!
Alamofire.request(url, method: .post)

let urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: true)!
Alamofire.request(urlComponents, method: .post)

以一种有意义的方式和web应用程序交互的应用,都鼓励使用自定义的遵循URLConvertible协议的类型将特定领域模型映射到服务器资源,因为这样比较方便。

本文由澳门新葡亰手机版发布于编程,转载请注明出处:澳门新葡亰手机版Alamofire框架的使用二,每天5分

上一篇:没有了 下一篇:没有了
猜你喜欢
热门排行
精彩图文