众所周知,Akka系统是基于Actor模式的分布式运算系统,非常适合构建大数据平台。所以,无可避免地会出现独立系统之间、与异类系统、与移动系统集成的需求。由于涉及到异类和移动系统,系统对接的方式必须在一套公开的标准之上进行,包括数据格式及数据传输标准。实际上针对标准的传输连接及标准数据编码、传输、解码全过程的软件编程是非常复杂及困难的。Akka-http正是这么一套能高效解决以上问题的编程工具。Akka-http是一套支持Tcp传输标准及Http标准数据的编程工具。

Http模式的交流方式是固定单向的:一方永远为对话启动方,另一方永远是回应方。具体运作方式是:发起方构建一个Http消息结构即Request,通过Tcp把它传给接收方;接收方对消息进行解译并按照发起方编写在消息里的要求进行一些运算及构建一个回复消息即Response并把它传回给发送方。在实际应用中这两方形成了一种服务方server与客户方client的关系:客户方向服务方发送服务请求Request;服务方根据Request提供相应运算并用Response回应结果。

Http消息的构成有两部分:一部分是对消息本身的描述,包括Http协议版本、字符集、加密方式、压缩方式、数据类型、安全机制等,另一部分就是消息的内容,即数据本身了,消息描述部分也有一些描述是针对数据的。

从实际应用角度来看:在Tcp上通过Http消息交换实现了一种服务及服务使用计算模式。服务提供方server处于被动调用状态,客户方client通过Request向服务方提出服务要求,服务方按照要求在服务端进行相关运算后将结果用Response返回客户方。可以看出:服务端客户端双方都涉及到了Http消息的构建、解析、传输,而服务提供方则增加了针对Request服务要求分析逻辑及对应的运算服务。

从更高应用层次来分析:系统集成实质上是两个系统之间通过Http协议实现数据交换。整个集成过程可以概括为:Client方将数据封装成Request;然后通过Tcp上传给Server;Server收到Request后进行解析;将Request里的数据解码成内部结构数据;按Request要求进行Server端运算;将运算结果数据封装成Response;然后将Response返回Client;Client对Response进行解析;将Response里的数据解码形成内部结构数据。

Akka-http分别提供了服务端的Server-Side-Api和客户端的Client-Side-Api来帮助编程人员简化编程。两个Api都包括了对Http消息的构建、解析、传输帮助函数。Server-Side-Api还包括了一套DSL以方便Http-Server功能编程。

对某个人群来说,Http是一个极其繁琐的协议:这里包括了消息格式、数据加码、解码、压缩、通讯协议、传输安全等等,等等。如果单纯按照Http协议编程的话将无法避免一堆新的定义及死板规定,无可避免影响编程效率。Akka-http应该正是为了这个人群而设计的。

Akka-http对Http消息的各组成部分进行了建模:用class来代表数据结构。然后在各类的伴生对象中提供大量的帮助函数(helper)来辅助该类型的构建、匹配等操作。如此可以大大简化Http消息的操作编程。举个例子:Request和Response两种类型的消息定义如下:

/**
* The immutable model HTTP request model.
*/
final class HttpRequest(
val method: HttpMethod,
val uri: Uri,
val headers: immutable.Seq[HttpHeader],
val entity: RequestEntity,
val protocol: HttpProtocol)
...
/**
* The immutable HTTP response model.
*/
final class HttpResponse(
val status: StatusCode,
val headers: immutable.Seq[HttpHeader],
val entity: ResponseEntity,
val protocol: HttpProtocol) object HttpRequest {
...
/* Manual Case Class things, to ease bin-compat */ def apply(
method: HttpMethod = HttpMethods.GET,
uri: Uri = Uri./,
headers: immutable.Seq[HttpHeader] = Nil,
entity: RequestEntity = HttpEntity.Empty,
protocol: HttpProtocol = HttpProtocols.`HTTP/1.1`) = new HttpRequest(method, uri, headers, entity, protocol) def unapply(any: HttpRequest) = new OptHttpRequest(any)
...
} object HttpResponse {
/* Manual Case Class things, to easen bin-compat */ def apply(
status: StatusCode = StatusCodes.OK,
headers: immutable.Seq[HttpHeader] = Nil,
entity: ResponseEntity = HttpEntity.Empty,
protocol: HttpProtocol = HttpProtocols.`HTTP/1.1`) = new HttpResponse(status, headers, entity, protocol) def unapply(any: HttpResponse): OptHttpResponse = new OptHttpResponse(any)
}

这使得我们可以很容易的构建Request和Response:

import HttpMethods._

// construct a simple GET request to `homeUri`
val homeUri = Uri("/abc")
HttpRequest(GET, uri = homeUri) // construct simple GET request to "/index" (implicit string to Uri conversion)
HttpRequest(GET, uri = "/index") // construct simple POST request containing entity
val data = ByteString("abc")
HttpRequest(POST, uri = "/receive", entity = data) import StatusCodes._ // simple OK response without data created using the integer status code
HttpResponse(200) // 404 response created using the named StatusCode constant
HttpResponse(NotFound) // 404 response with a body explaining the error
HttpResponse(404, entity = "Unfortunately, the resource couldn't be found.") // A redirecting response containing an extra header
val locationHeader = headers.Location("http://example.com/other")
HttpResponse(Found, headers = List(locationHeader))

Http消息中的Entity,Header也都用HttpEntity,HttpHeader类型进行了对应。

Uri的操作也是比较麻烦的,所以Akka-http也提供了Uri类型:

/**
* An immutable model of an internet URI as defined by http://tools.ietf.org/html/rfc3986.
* All members of this class represent the *decoded* URI elements (i.e. without percent-encoding).
*/
sealed abstract case class Uri(scheme: String, authority: Authority, path: Path, rawQueryString: Option[String],
fragment: Option[String]) {...}

这样可以方便简化Uri的构建、解析:

Uri("ftp://ftp.is.co.za/rfc/rfc1808.txt") shouldEqual
Uri.from(scheme = "ftp", host = "ftp.is.co.za", path = "/rfc/rfc1808.txt") Uri("http://www.ietf.org/rfc/rfc2396.txt") shouldEqual
Uri.from(scheme = "http", host = "www.ietf.org", path = "/rfc/rfc2396.txt") Uri("ldap://[2001:db8::7]/c=GB?objectClass?one") shouldEqual
Uri.from(scheme = "ldap", host = "[2001:db8::7]", path = "/c=GB", queryString = Some("objectClass?one")) Uri("mailto:John.Doe@example.com") shouldEqual
Uri.from(scheme = "mailto", path = "John.Doe@example.com") Uri("news:comp.infosystems.www.servers.unix") shouldEqual
Uri.from(scheme = "news", path = "comp.infosystems.www.servers.unix") Uri("tel:+1-816-555-1212") shouldEqual
Uri.from(scheme = "tel", path = "+1-816-555-1212") Uri("telnet://192.0.2.16:80/") shouldEqual
Uri.from(scheme = "telnet", host = "192.0.2.16", port = , path = "/") Uri("urn:oasis:names:specification:docbook:dtd:xml:4.1.2") shouldEqual
Uri.from(scheme = "urn", path = "oasis:names:specification:docbook:dtd:xml:4.1.2")

Http Server部分也是系统集成的主要部分,因为在绝大多数的情况下Http-Server就处于数据平台上,负责汇集系统数据及与其它系统共享平台数据。这种集成功能一般是通过用Http-Server在平台上构建Rest数据服务来实现的。由于Akka-http是基于Akka-stream功能之上的,它支持Http数据的流操作,也就是说它可以把一个Stream-Source放在Http消息的数据里,然后Akka-http的Client-Side-Api可以运算这些Source。如此可以大大方便数据库之间的数据交换,提高数据集成效率。不过Streaming功能只能在Akka-http-Api内实现。但用Akka-http-Server-Side-Api也可以很方便的实现标准Rest服务使其它异类系统可以顺利调用。下面我们就用Akka-http做个Hello World Rest服务示范:

import akka.actor._
import akka.stream._
import akka.stream.scaladsl._
import akka.http.scaladsl.model._
import akka.http.scaladsl.Http
import akka.http.scaladsl.server.Directives._
import scala.concurrent._ object HelloHttp extends App {
implicit val httpSys = ActorSystem("httpSys")
implicit val httpMat = ActorMaterializer()
implicit val httpEc = httpSys.dispatcher val (host,port) = ("localhost",) val services: Flow[HttpRequest, HttpResponse, Any] = path("hello") {
get {
complete(HttpEntity(ContentTypes.`text/html(UTF-)`,"<h> Hello World! </h>"))
}
} val futBinding: Future[Http.ServerBinding] = Http().bindAndHandle(services,host,port) println(s"Server running at $host $port. Press any key to exit ...") scala.io.StdIn.readLine() futBinding.flatMap(_.unbind())
.onComplete(_ => httpSys.terminate())
}

可以看到,用Akka-http可以很容易的实现一个Rest服务架构。

Akka(28): Http:About Akka-Http的更多相关文章

  1. [易学易懂系列|rustlang语言|零基础|快速入门|(28)|实战5:实现BTC价格转换工具]

    [易学易懂系列|rustlang语言|零基础|快速入门|(28)|实战5:实现BTC价格转换工具] 项目实战 实战5:实现BTC价格转换工具 今天我们来开发一个简单的BTC实时价格转换工具. 我们首先 ...

  2. 连载:面向对象葵花宝典:思想、技巧与实践(28) - 设计原则:内聚&amp;耦合

    前面通过实例解说了一个一环扣一环的面向对象的开发流程:用例模型 -> 领域模型 -> 设计模型(类模型 + 动态模型),解答了面向对象怎样做的问题.接下来我们就要讲"怎样做好面向 ...

  3. Windows Phone开发(28):隔离存储B

    原文:Windows Phone开发(28):隔离存储B 上一节我们聊了目录的操作,这一节我们继续来看看如何读写文件. 首先说一下题外话,许多朋友都在摇摆不定,三心二意,其实这样的学习态度是很不好的, ...

  4. Akka(8): 分布式运算:Remoting-远程查找式

    Akka是一种消息驱动运算模式,它实现跨JVM程序运算的方式是通过能跨JVM的消息系统来调动分布在不同JVM上ActorSystem中的Actor进行运算,前题是Akka的地址系统可以支持跨JVM定位 ...

  5. Akka(17): Stream:数据流基础组件-Source,Flow,Sink简介

    在大数据程序流行的今天,许多程序都面临着共同的难题:程序输入数据趋于无限大,抵达时间又不确定.一般的解决方法是采用回调函数(callback-function)来实现的,但这样的解决方案很容易造成“回 ...

  6. Qt 学习之路 2(28):坐标系统

    Qt 学习之路 2(28):坐标系统 豆子 2012年11月25日 Qt 学习之路 2 59条评论 在经历过实际操作,以及前面一节中我们见到的那个translate()函数之后,我们可以详细了解下 Q ...

  7. Android Animation学习(二) ApiDemos解析:基本Animatiors使用

    Animator类提供了创建动画的基本结构,但是一般使用的是它的子类: ValueAnimator.ObjectAnimator.AnimatorSet ApiDemos中Animation部分是单独 ...

  8. 深度学习(TensorFlow)环境搭建:(三)Ubuntu16.04+CUDA8.0+cuDNN7+Anaconda4.4+Python3.6+TensorFlow1.3

    紧接着上一篇的文章<深度学习(TensorFlow)环境搭建:(二)Ubuntu16.04+1080Ti显卡驱动>,这篇文章,主要讲解如何安装CUDA+CUDNN,不过前提是我们是已经把N ...

  9. java中文乱码解决之道(三)-----编码详情:伟大的创想---Unicode编码

    随着计算机的发展.普及,世界各国为了适应本国的语言和字符都会自己设计一套自己的编码风格,正是由于这种乱,导致存在很多种编码方式,以至于同一个二进制数字可能会被解释成不同的符号.为了解决这种不兼容的问题 ...

随机推荐

  1. 201521123017 《Java程序设计》第6周学习总结

    1. 本周学习总结 <> 2. 书面作业 Q1.clone方法 1.1 Object对象中的clone方法是被protected修饰,在自定义的类中覆盖clone方法时需要注意什么? 1. ...

  2. 201521123095 《Java程序设计》第5周学习总结

    1. 本周学习总结 1.1 尝试使用思维导图总结有关多态与接口的知识点. 2. 书面作业 1.1 com.parent包中Child.java文件能否编译通过?哪句会出现错误?试改正该错误.并分析输出 ...

  3. 201521123005 《Java程序设计》 第十一周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多线程相关内容. 2. 书面作业 本次PTA作业题集多线程 Q1.互斥访问与同步访问 完成题集4-4(互斥访问)与4-5(同步访问) ...

  4. 201521123086 《Java程序设计》第9周学习总结

    本章学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常相关内容. (1)使用try...catch语句捕获异常(try块后可跟一个或多个catch块,注意子类异常要放在父类异常前面,否则子 ...

  5. mybatis教程:入门>>精通>>实战

    以前曾经用过ibatis,这是mybatis的前身,当时在做项目时,感觉很不错,比hibernate灵活.性能也比hibernate好.而且也比较轻量级,因为当时在项目中,没来的及做很很多笔记.后来项 ...

  6. 练习使用markdown

    我的随笔 写随笔的原因 1 完全是为了练习使用markdown编辑器 2 我是个爱学习的宝宝 3 学习能力问题? 随笔内容 弄懂markdown语法 随便谢谢心情 个人心情 冷漠 不想说话 神经 个人 ...

  7. Maven常见错误以及解决方案【转载】

    常见的Maven错误 当遇到401错误的时候,看看自己当前使用的Maven是集成的还是自己下载的,然后去配置setting.xml文件

  8. Linux环境下启动MySQL数据库出现找不到mysqld.sock的解决办法!

    问题: 在普通用户权限下运行:mysql -u root -p,回车之后如果会出现如下错误:ERROR 2002 (HY000): Can't connect to local MySQL serve ...

  9. JVM菜鸟进阶高手之路十一(eden survivor分配问题)

    转载请注明原创出处,谢谢! 问题 这个Xmn设置为1G,,我用jmap -heap 看,这个Eden From To怎么不是一个整8:1:1的关系呢? 我看内存分配还是没变,我Xmn1g,感觉From ...

  10. CentOS7安装后配置MariaDB

    安装后,优先推荐先对安全设置进行配置,键入命令 sudo mysql_secure_installation 键入当前密码,当前没有,直接回车,之后跟随提示会问几个问题:设置 root 密码? / 移 ...