├── .gitignore ├── .project ├── 2.3.6 └── scala │ ├── README.md │ ├── SUMMARY.md │ ├── book │ ├── GLOSSARY.html │ ├── chapter1 │ │ ├── 01_what_is_akka.html │ │ ├── 02_why_akka.html │ │ ├── 03_getting_started.html │ │ ├── 04_the_obligatory_hello_world.html │ │ ├── 05_usecase_and_deployment_scenarios.html │ │ ├── 06_examples_of_usecases_for_akka.html │ │ └── introduction.html │ ├── chapter10 │ │ ├── 01_migration_guides.html │ │ ├── 02_issue_tracking.html │ │ ├── 03_licenses.html │ │ ├── 04_sponsors.html │ │ ├── 05_project.html │ │ └── project_information.html │ ├── chapter11 │ │ ├── 01_faq.html │ │ ├── 02_books.html │ │ ├── 03_other_language_bindings.html │ │ ├── 04_akka_in_osgi.html │ │ ├── 05_incomplete_list_of_http_frameworks.html │ │ └── additional_information.html │ ├── chapter2 │ │ ├── 01_terminology_concepts.html │ │ ├── 02_actor_systems.html │ │ ├── 03_what_is_an_actor.html │ │ ├── 04_supervision_and_monitoring.html │ │ ├── 05_actor_references_paths_and_addresses.html │ │ ├── 06_location_transparency.html │ │ ├── 07_akka_and_the_java_memory_model.html │ │ ├── 08_message_delivery_reliability.html │ │ ├── 09_configuration.html │ │ ├── ActorPath.png │ │ ├── RemoteDeployment.png │ │ ├── general.html │ │ └── guardians.png │ ├── chapter3 │ │ ├── 01_actors.html │ │ ├── 02_typed_actors.html │ │ ├── 03-1_fault_tolerance_sample.html │ │ ├── 03_fault_tolerance.html │ │ ├── 04_dispatchers.html │ │ ├── 05_mailboxes.html │ │ ├── 06_routing.html │ │ ├── 07_fsm.html │ │ ├── 08_persistence.html │ │ ├── 09_1_testkit-example.html │ │ ├── 09_1_testkit-example.md │ │ ├── 09_testing_actor_systems.html │ │ ├── 10_actor_dsl.html │ │ └── actors.html │ ├── chapter4 │ │ ├── 01_futures.html │ │ ├── 02_agents.html │ │ └── futures_and_agents.html │ ├── chapter5 │ │ ├── 01_cluster_cpecification.html │ │ ├── 02_cluster_usage.html │ │ ├── 03_remoting.html │ │ ├── 04_serialization.html │ │ ├── 05_io.html │ │ ├── 06_using_tcp.html │ │ ├── 07_using_udp.html │ │ ├── 08_zeromq.html │ │ ├── 09_camel.html │ │ └── networking.html │ ├── chapter6 │ │ ├── 01_event_bus.html │ │ ├── 02_logging.html │ │ ├── 03_scheduler.html │ │ ├── 04_duration.html │ │ ├── 05_circuit_breaker.html │ │ ├── 06_akka_extensions.html │ │ ├── 07_microkernel.html │ │ └── utilities.html │ ├── chapter7 │ │ └── howto_common_patterns.html │ ├── chapter8 │ │ ├── 02_multi_node_testing.html │ │ ├── 03_actors.html │ │ ├── 04_fsm.html │ │ ├── 05_external_contributions.html │ │ └── experimental_modules.html │ ├── chapter9 │ │ ├── 01_building_akka.html │ │ ├── 02_multi_jvm_testing.html │ │ ├── 03_io_layer_design.html │ │ ├── 04_developer_guidelines.html │ │ ├── 05_documentation_guidelines.html │ │ ├── 06_team.html │ │ └── information_for_akka_developers.html │ ├── gitbook │ │ ├── app.js │ │ ├── fonts │ │ │ ├── fontawesome │ │ │ │ ├── FontAwesome.otf │ │ │ │ ├── fontawesome-webfont.eot │ │ │ │ ├── fontawesome-webfont.svg │ │ │ │ ├── fontawesome-webfont.ttf │ │ │ │ └── fontawesome-webfont.woff │ │ │ ├── merriweather │ │ │ │ ├── 250.woff │ │ │ │ ├── 250i.woff │ │ │ │ ├── 400.woff │ │ │ │ ├── 400i.woff │ │ │ │ ├── 700.woff │ │ │ │ ├── 700i.woff │ │ │ │ ├── 900.woff │ │ │ │ └── 900i.woff │ │ │ └── opensans │ │ │ │ ├── 300.woff │ │ │ │ ├── 300i.woff │ │ │ │ ├── 400.woff │ │ │ │ ├── 400i.woff │ │ │ │ ├── 600.woff │ │ │ │ ├── 600i.woff │ │ │ │ ├── 700.woff │ │ │ │ └── 700i.woff │ │ ├── images │ │ │ ├── apple-touch-icon-precomposed-152.png │ │ │ └── favicon.ico │ │ ├── plugins │ │ │ └── gitbook-plugin-mathjax │ │ │ │ └── plugin.js │ │ ├── print.css │ │ └── style.css │ ├── glossary_index.json │ ├── images │ │ ├── actor_lifecycle.png │ │ ├── actor_lifecycle.svg │ │ ├── akka-remote-testconductor.png │ │ ├── association_lifecycle.png │ │ ├── association_lifecycle.svg │ │ ├── benchmark-akka-sample-trading-throughput.png │ │ ├── build-path.png │ │ ├── camel-pubsub.png │ │ ├── camel-pubsub2.png │ │ ├── circuit-breaker-states.dot │ │ ├── circuit-breaker-states.png │ │ ├── clojure-trees.png │ │ ├── diagnostics-window.png │ │ ├── example-code.png │ │ ├── faulttolerancesample-failure-flow.png │ │ ├── faulttolerancesample-normal-flow.png │ │ ├── faulttolerancesample.graffle │ │ ├── import-project.png │ │ ├── install-beta2-updatesite.png │ │ ├── member-states.drawing │ │ ├── member-states.png │ │ ├── member-states.svg │ │ ├── more.png │ │ ├── phi1.png │ │ ├── phi2.png │ │ ├── phi3.png │ │ ├── pi-formula.png │ │ ├── quickfix.png │ │ ├── run-config.png │ │ ├── tcp-message-protocol.graffle │ │ ├── tcp-message-protocol_bind-connect-maxed-out.svg │ │ ├── tcp-message-protocol_binding.svg │ │ ├── tcp-message-protocol_closing.svg │ │ ├── tcp-message-protocol_establishing-incoming.svg │ │ ├── tcp-message-protocol_establishing-outgoing.svg │ │ ├── tcp-message-protocol_noticing-close.svg │ │ ├── tcp-message-protocol_receiving.svg │ │ ├── tcp-message-protocol_unbinding.svg │ │ └── tcp-message-protocol_writing.svg │ ├── index.html │ └── search_index.json │ ├── chapter1 │ ├── 01_what_is_akka.md │ ├── 02_why_akka.md │ ├── 03_getting_started.md │ ├── 04_the_obligatory_hello_world.md │ ├── 05_usecase_and_deployment_scenarios.md │ ├── 06_examples_of_usecases_for_akka.md │ └── introduction.md │ ├── chapter10 │ ├── 01_migration_guides.md │ ├── 02_issue_tracking.md │ ├── 03_licenses.md │ ├── 04_sponsors.md │ ├── 05_project.md │ └── project_information.md │ ├── chapter11 │ ├── 01_faq.md │ ├── 02_books.md │ ├── 03_other_language_bindings.md │ ├── 04_akka_in_osgi.md │ ├── 05_incomplete_list_of_http_frameworks.md │ └── additional_information.md │ ├── chapter2 │ ├── 01_terminology_concepts.md │ ├── 02_actor_systems.md │ ├── 03_what_is_an_actor.md │ ├── 04_supervision_and_monitoring.md │ ├── 05_actor_references_paths_and_addresses.md │ ├── 06_location_transparency.md │ ├── 07_akka_and_the_java_memory_model.md │ ├── 08_message_delivery_reliability.md │ ├── 09_configuration.md │ ├── ActorPath.png │ ├── RemoteDeployment.png │ ├── general.md │ └── guardians.png │ ├── chapter3 │ ├── 01_actors.md │ ├── 02_typed_actors.md │ ├── 03-1_fault_tolerance_sample.md │ ├── 03_fault_tolerance.md │ ├── 04_dispatchers.md │ ├── 05_mailboxes.md │ ├── 06_routing.md │ ├── 07_fsm.md │ ├── 08_persistence.md │ ├── 09_1_testkit-example.md │ ├── 09_testing_actor_systems.md │ ├── 10_actor_dsl.md │ └── actors.md │ ├── chapter4 │ ├── 01_futures.md │ ├── 02_agents.md │ └── futures_and_agents.md │ ├── chapter5 │ ├── 01_cluster_cpecification.md │ ├── 02_cluster_usage.md │ ├── 03_remoting.md │ ├── 04_serialization.md │ ├── 05_io.md │ ├── 06_using_tcp.md │ ├── 07_using_udp.md │ ├── 08_zeromq.md │ ├── 09_camel.md │ └── networking.md │ ├── chapter6 │ ├── 01_event_bus.md │ ├── 02_logging.md │ ├── 03_scheduler.md │ ├── 04_duration.md │ ├── 05_circuit_breaker.md │ ├── 06_akka_extensions.md │ ├── 07_microkernel.md │ └── utilities.md │ ├── chapter7 │ └── howto_common_patterns.md │ ├── chapter8 │ ├── 02_multi_node_testing.md │ ├── 03_actors.md │ ├── 04_fsm.md │ ├── 05_external_contributions.md │ └── experimental_modules.md │ ├── chapter9 │ ├── 01_building_akka.md │ ├── 02_multi_jvm_testing.md │ ├── 03_io_layer_design.md │ ├── 04_developer_guidelines.md │ ├── 05_documentation_guidelines.md │ ├── 06_team.md │ └── information_for_akka_developers.md │ └── images │ ├── actor_lifecycle.png │ ├── actor_lifecycle.svg │ ├── akka-remote-testconductor.png │ ├── association_lifecycle.png │ ├── association_lifecycle.svg │ ├── benchmark-akka-sample-trading-throughput.png │ ├── build-path.png │ ├── camel-pubsub.png │ ├── camel-pubsub2.png │ ├── circuit-breaker-states.dot │ ├── circuit-breaker-states.png │ ├── clojure-trees.png │ ├── diagnostics-window.png │ ├── example-code.png │ ├── faulttolerancesample-failure-flow.png │ ├── faulttolerancesample-normal-flow.png │ ├── faulttolerancesample.graffle │ ├── import-project.png │ ├── install-beta2-updatesite.png │ ├── member-states.drawing │ ├── member-states.png │ ├── member-states.svg │ ├── more.png │ ├── phi1.png │ ├── phi2.png │ ├── phi3.png │ ├── pi-formula.png │ ├── quickfix.png │ ├── run-config.png │ ├── tcp-message-protocol.graffle │ ├── tcp-message-protocol_bind-connect-maxed-out.svg │ ├── tcp-message-protocol_binding.svg │ ├── tcp-message-protocol_closing.svg │ ├── tcp-message-protocol_establishing-incoming.svg │ ├── tcp-message-protocol_establishing-outgoing.svg │ ├── tcp-message-protocol_noticing-close.svg │ ├── tcp-message-protocol_receiving.svg │ ├── tcp-message-protocol_unbinding.svg │ └── tcp-message-protocol_writing.svg ├── LICENSE ├── README.md └── index.html /.gitignore: -------------------------------------------------------------------------------- 1 | _book 2 | .idea 3 | *iml -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | akka-doc-cn 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /2.3.6/scala/README.md: -------------------------------------------------------------------------------- 1 | > 无水scala群:`231809997` 2 | > 有各路scala高手帮你释疑,语言风格像scala一样简洁,精确 3 | 4 | 5 | 6 | # AKKA 2.3.6 Scala 文档 7 | 8 | 该文档是Akka 2.3.6 Scala 文档的中文翻译([github](https://github.com/jasonqu/akka-doc-cn))。 9 | 10 | 本文大量参考了[上海广谈信息技术有限公司](http://www.gtan.com/)的[《Akka 2.0文档》](http://www.gtan.com/welfare04.html),[广谈公益](http://www.gtan.com/welfare.html)还有很多优秀的资源,感兴趣的请移步参考。 11 | -------------------------------------------------------------------------------- /2.3.6/scala/SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | * [Introduction](README.md) 4 | * [引言](chapter1/introduction.md) 5 | * [Akka是什么?](chapter1/01_what_is_akka.md) 6 | * [为什么使用Akka?](chapter1/02_why_akka.md) 7 | * [入门](chapter1/03_getting_started.md) 8 | * [必修的“Hello World”](chapter1/04_the_obligatory_hello_world.md) 9 | * [用例和部署场景](chapter1/05_usecase_and_deployment_scenarios.md) 10 | * [Akka使用实例](chapter1/06_examples_of_usecases_for_akka.md) 11 | * [概述](chapter2/general.md) 12 | * [术语,概念](chapter2/01_terminology_concepts.md) 13 | * [Actor系统](chapter2/02_actor_systems.md) 14 | * [什么是Actor?](chapter2/03_what_is_an_actor.md) 15 | * [监管与监控](chapter2/04_supervision_and_monitoring.md) 16 | * [Actor引用, 路径与地址](chapter2/05_actor_references_paths_and_addresses.md) 17 | * [位置透明性](chapter2/06_location_transparency.md) 18 | * [Akka与Java内存模型](chapter2/07_akka_and_the_java_memory_model.md) 19 | * [消息发送语义](chapter2/08_message_delivery_reliability.md) 20 | * [配置](chapter2/09_configuration.md) 21 | * [Actors](chapter3/actors.md) 22 | * [Actors](chapter3/01_actors.md) 23 | * [有类型Actor](chapter3/02_typed_actors.md) 24 | * [容错](chapter3/03_fault_tolerance.md) 25 | * [容错示例](chapter3/03-1_fault_tolerance_sample.md) 26 | * [调度器](chapter3/04_dispatchers.md) 27 | * [邮箱](chapter3/05_mailboxes.md) 28 | * [路由](chapter3/06_routing.md) 29 | * [有限状态机(FSM)](chapter3/07_fsm.md) 30 | * [持久化](chapter3/08_persistence.md) 31 | * [测试Actor系统](chapter3/09_testing_actor_systems.md) 32 | * [TestKit实例](chapter3/09_1_testkit-example.md) 33 | * [Actor DSL](chapter3/10_actor_dsl.md) 34 | * [Futures与Agents](chapter4/futures_and_agents.md) 35 | * [Futures](chapter4/01_futures.md) 36 | * [Agents](chapter4/02_agents.md) 37 | * [网络](chapter5/networking.md) 38 | * [集群规格](chapter5/01_cluster_cpecification.md) 39 | * [集群用法](chapter5/02_cluster_usage.md) 40 | * [远程](chapter5/03_remoting.md) 41 | * [序列化](chapter5/04_serialization.md) 42 | * [I/O](chapter5/05_io.md) 43 | * [使用TCP](chapter5/06_using_tcp.md) 44 | * [使用UDP](chapter5/07_using_udp.md) 45 | * [ZeroMQ](chapter5/08_zeromq.md) 46 | * [Camel](chapter5/09_camel.md) 47 | * [实用工具](chapter6/utilities.md) 48 | * [事件总线](chapter6/01_event_bus.md) 49 | * [日志](chapter6/02_logging.md) 50 | * [调度器](chapter6/03_scheduler.md) 51 | * [Duration](chapter6/04_duration.md) 52 | * [线路断路器](chapter6/05_circuit_breaker.md) 53 | * [Akka扩展](chapter6/06_akka_extensions.md) 54 | * [微内核](chapter6/07_microkernel.md) 55 | * [如何使用:常用模式](chapter7/howto_common_patterns.md) 56 | * [实验模块](chapter8/experimental_modules.md) 57 | * [持久化](chapter3/08_persistence.md) 58 | * [多节点测试](chapter8/02_multi_node_testing.md) 59 | * [Actors(使用Java的Lambda支持)](chapter8/03_actors.md) 60 | * [FSM(使用Java的Lambda支持)](chapter8/04_fsm.md) 61 | * [外部贡献](chapter8/05_external_contributions.md) 62 | * [Akka开发者信息](chapter9/information_for_akka_developers.md) 63 | * [构建Akka](chapter9/01_building_akka.md) 64 | * [多JVM测试](chapter9/02_multi_jvm_testing.md) 65 | * [I/O层设计](chapter9/03_io_layer_design.md) 66 | * [开发指南](chapter9/04_developer_guidelines.md) 67 | * [文档指南](chapter9/05_documentation_guidelines.md) 68 | * [团队](chapter9/06_team.md) 69 | * [工程信息](chapter10/project_information.md) 70 | * [迁移指南](chapter10/01_migration_guides.md) 71 | * [问题追踪](chapter10/02_issue_tracking.md) 72 | * [许可证](chapter10/03_licenses.md) 73 | * [赞助商](chapter10/04_sponsors.md) 74 | * [项目](chapter10/05_project.md) 75 | * [附加信息](chapter11/additional_information.md) 76 | * [常见问题](chapter11/01_faq.md) 77 | * [图书](chapter11/02_books.md) 78 | * [其他语言绑定](chapter11/03_other_language_bindings.md) 79 | * [Akka与OSGi](chapter11/04_akka_in_osgi.md) 80 | * [部分HTTP框架名单](chapter11/05_incomplete_list_of_http_frameworks.md) 81 | 82 | -------------------------------------------------------------------------------- /2.3.6/scala/book/chapter2/ActorPath.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/chapter2/ActorPath.png -------------------------------------------------------------------------------- /2.3.6/scala/book/chapter2/RemoteDeployment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/chapter2/RemoteDeployment.png -------------------------------------------------------------------------------- /2.3.6/scala/book/chapter2/guardians.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/chapter2/guardians.png -------------------------------------------------------------------------------- /2.3.6/scala/book/chapter3/09_1_testkit-example.md: -------------------------------------------------------------------------------- 1 | # TestKit实例(Scala) 2 | 3 | 这是Ray Roestenburg 在 [他的博客](http://roestenburg.agilesquad.com/2011/02/unit-testing-akka-actors-with-testkit_12.html) 中的示例代码,作了改动以兼容 Akka 2.x。 4 | 5 | ```scala 6 | import scala.util.Random 7 | 8 | import org.scalatest.BeforeAndAfterAll 9 | import org.scalatest.WordSpecLike 10 | import org.scalatest.Matchers 11 | 12 | import com.typesafe.config.ConfigFactory 13 | 14 | import akka.actor.Actor 15 | import akka.actor.ActorRef 16 | import akka.actor.ActorSystem 17 | import akka.actor.Props 18 | import akka.testkit.{ TestActors, DefaultTimeout, ImplicitSender, TestKit } 19 | import scala.concurrent.duration._ 20 | import scala.collection.immutable 21 | 22 | /** 23 | * a Test to show some TestKit examples 24 | */ 25 | class TestKitUsageSpec 26 | extends TestKit(ActorSystem("TestKitUsageSpec", 27 | ConfigFactory.parseString(TestKitUsageSpec.config))) 28 | with DefaultTimeout with ImplicitSender 29 | with WordSpecLike with Matchers with BeforeAndAfterAll { 30 | import TestKitUsageSpec._ 31 | 32 | val echoRef = system.actorOf(TestActors.echoActorProps) 33 | val forwardRef = system.actorOf(Props(classOf[ForwardingActor], testActor)) 34 | val filterRef = system.actorOf(Props(classOf[FilteringActor], testActor)) 35 | val randomHead = Random.nextInt(6) 36 | val randomTail = Random.nextInt(10) 37 | val headList = immutable.Seq().padTo(randomHead, "0") 38 | val tailList = immutable.Seq().padTo(randomTail, "1") 39 | val seqRef = 40 | system.actorOf(Props(classOf[SequencingActor], testActor, headList, tailList)) 41 | 42 | override def afterAll { 43 | shutdown() 44 | } 45 | 46 | "An EchoActor" should { 47 | "Respond with the same message it receives" in { 48 | within(500 millis) { 49 | echoRef ! "test" 50 | expectMsg("test") 51 | } 52 | } 53 | } 54 | "A ForwardingActor" should { 55 | "Forward a message it receives" in { 56 | within(500 millis) { 57 | forwardRef ! "test" 58 | expectMsg("test") 59 | } 60 | } 61 | } 62 | "A FilteringActor" should { 63 | "Filter all messages, except expected messagetypes it receives" in { 64 | var messages = Seq[String]() 65 | within(500 millis) { 66 | filterRef ! "test" 67 | expectMsg("test") 68 | filterRef ! 1 69 | expectNoMsg 70 | filterRef ! "some" 71 | filterRef ! "more" 72 | filterRef ! 1 73 | filterRef ! "text" 74 | filterRef ! 1 75 | 76 | receiveWhile(500 millis) { 77 | case msg: String => messages = msg +: messages 78 | } 79 | } 80 | messages.length should be(3) 81 | messages.reverse should be(Seq("some", "more", "text")) 82 | } 83 | } 84 | "A SequencingActor" should { 85 | "receive an interesting message at some point " in { 86 | within(500 millis) { 87 | ignoreMsg { 88 | case msg: String => msg != "something" 89 | } 90 | seqRef ! "something" 91 | expectMsg("something") 92 | ignoreMsg { 93 | case msg: String => msg == "1" 94 | } 95 | expectNoMsg 96 | ignoreNoMsg 97 | } 98 | } 99 | } 100 | } 101 | 102 | object TestKitUsageSpec { 103 | // Define your test specific configuration here 104 | val config = """ 105 | akka { 106 | loglevel = "WARNING" 107 | } 108 | """ 109 | 110 | /** 111 | * An Actor that forwards every message to a next Actor 112 | */ 113 | class ForwardingActor(next: ActorRef) extends Actor { 114 | def receive = { 115 | case msg => next ! msg 116 | } 117 | } 118 | 119 | /** 120 | * An Actor that only forwards certain messages to a next Actor 121 | */ 122 | class FilteringActor(next: ActorRef) extends Actor { 123 | def receive = { 124 | case msg: String => next ! msg 125 | case _ => None 126 | } 127 | } 128 | 129 | /** 130 | * An actor that sends a sequence of messages with a random head list, an 131 | * interesting value and a random tail list. The idea is that you would 132 | * like to test that the interesting value is received and that you cant 133 | * be bothered with the rest 134 | */ 135 | class SequencingActor(next: ActorRef, head: immutable.Seq[String], 136 | tail: immutable.Seq[String]) extends Actor { 137 | def receive = { 138 | case msg => { 139 | head foreach { next ! _ } 140 | next ! msg 141 | tail foreach { next ! _ } 142 | } 143 | } 144 | } 145 | } 146 | ``` -------------------------------------------------------------------------------- /2.3.6/scala/book/gitbook/fonts/fontawesome/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/gitbook/fonts/fontawesome/FontAwesome.otf -------------------------------------------------------------------------------- /2.3.6/scala/book/gitbook/fonts/fontawesome/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/gitbook/fonts/fontawesome/fontawesome-webfont.eot -------------------------------------------------------------------------------- /2.3.6/scala/book/gitbook/fonts/fontawesome/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/gitbook/fonts/fontawesome/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /2.3.6/scala/book/gitbook/fonts/fontawesome/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/gitbook/fonts/fontawesome/fontawesome-webfont.woff -------------------------------------------------------------------------------- /2.3.6/scala/book/gitbook/fonts/merriweather/250.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/gitbook/fonts/merriweather/250.woff -------------------------------------------------------------------------------- /2.3.6/scala/book/gitbook/fonts/merriweather/250i.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/gitbook/fonts/merriweather/250i.woff -------------------------------------------------------------------------------- /2.3.6/scala/book/gitbook/fonts/merriweather/400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/gitbook/fonts/merriweather/400.woff -------------------------------------------------------------------------------- /2.3.6/scala/book/gitbook/fonts/merriweather/400i.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/gitbook/fonts/merriweather/400i.woff -------------------------------------------------------------------------------- /2.3.6/scala/book/gitbook/fonts/merriweather/700.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/gitbook/fonts/merriweather/700.woff -------------------------------------------------------------------------------- /2.3.6/scala/book/gitbook/fonts/merriweather/700i.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/gitbook/fonts/merriweather/700i.woff -------------------------------------------------------------------------------- /2.3.6/scala/book/gitbook/fonts/merriweather/900.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/gitbook/fonts/merriweather/900.woff -------------------------------------------------------------------------------- /2.3.6/scala/book/gitbook/fonts/merriweather/900i.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/gitbook/fonts/merriweather/900i.woff -------------------------------------------------------------------------------- /2.3.6/scala/book/gitbook/fonts/opensans/300.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/gitbook/fonts/opensans/300.woff -------------------------------------------------------------------------------- /2.3.6/scala/book/gitbook/fonts/opensans/300i.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/gitbook/fonts/opensans/300i.woff -------------------------------------------------------------------------------- /2.3.6/scala/book/gitbook/fonts/opensans/400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/gitbook/fonts/opensans/400.woff -------------------------------------------------------------------------------- /2.3.6/scala/book/gitbook/fonts/opensans/400i.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/gitbook/fonts/opensans/400i.woff -------------------------------------------------------------------------------- /2.3.6/scala/book/gitbook/fonts/opensans/600.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/gitbook/fonts/opensans/600.woff -------------------------------------------------------------------------------- /2.3.6/scala/book/gitbook/fonts/opensans/600i.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/gitbook/fonts/opensans/600i.woff -------------------------------------------------------------------------------- /2.3.6/scala/book/gitbook/fonts/opensans/700.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/gitbook/fonts/opensans/700.woff -------------------------------------------------------------------------------- /2.3.6/scala/book/gitbook/fonts/opensans/700i.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/gitbook/fonts/opensans/700i.woff -------------------------------------------------------------------------------- /2.3.6/scala/book/gitbook/images/apple-touch-icon-precomposed-152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/gitbook/images/apple-touch-icon-precomposed-152.png -------------------------------------------------------------------------------- /2.3.6/scala/book/gitbook/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/gitbook/images/favicon.ico -------------------------------------------------------------------------------- /2.3.6/scala/book/gitbook/plugins/gitbook-plugin-mathjax/plugin.js: -------------------------------------------------------------------------------- 1 | require(["gitbook"], function(gitbook) { 2 | MathJax.Hub.Config({ 3 | tex2jax: { 4 | processEscapes: true 5 | } 6 | }); 7 | 8 | 9 | gitbook.events.bind("page.change", function() { 10 | MathJax.Hub.Typeset() 11 | }); 12 | }); 13 | 14 | -------------------------------------------------------------------------------- /2.3.6/scala/book/gitbook/print.css: -------------------------------------------------------------------------------- 1 | .link-inherit{color:inherit}.link-inherit:hover,.link-inherit:focus{color:inherit}.hidden{display:none}.hljs-comment,.hljs-title{color:#8e908c}.hljs-variable,.hljs-attribute,.hljs-tag,.hljs-regexp,.ruby .hljs-constant,.xml .hljs-tag .hljs-title,.xml .hljs-pi,.xml .hljs-doctype,.html .hljs-doctype,.css .hljs-id,.css .hljs-class,.css .hljs-pseudo{color:#c82829}.hljs-number,.hljs-preprocessor,.hljs-pragma,.hljs-built_in,.hljs-literal,.hljs-params,.hljs-constant{color:#f5871f}.ruby .hljs-class .hljs-title,.css .hljs-rules .hljs-attribute{color:#eab700}.hljs-string,.hljs-value,.hljs-inheritance,.hljs-header,.ruby .hljs-symbol,.xml .hljs-cdata{color:#718c00}.css .hljs-hexcolor{color:#3e999f}.hljs-function,.python .hljs-decorator,.python .hljs-title,.ruby .hljs-function .hljs-title,.ruby .hljs-title .hljs-keyword,.perl .hljs-sub,.javascript .hljs-title,.coffeescript .hljs-title{color:#4271ae}.hljs-keyword,.javascript .hljs-function{color:#8959a8}.hljs{display:block;background:white;color:#4d4d4c;padding:.5em}.coffeescript .javascript,.javascript .xml,.tex .hljs-formula,.xml .javascript,.xml .vbscript,.xml .css,.xml .hljs-cdata{opacity:.5}.book-chapter{display:none}.exercise,.quiz{margin:1cm 0;padding:.4cm;page-break-inside:avoid;border:3px solid #ddd}.exercise .exercise-header,.quiz .exercise-header{margin-bottom:.4cm;padding-bottom:.2cm;border-bottom:1px solid #ddd}.exercise .question,.quiz .question{margin-top:.4cm}body{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;line-height:1.4;color:#333;overflow:hidden;line-height:1.6;word-wrap:break-word;display:block}body>*:first-child{margin-top:0!important}body>*:last-child{margin-bottom:0!important}body a{background:transparent}body a:active,body a:hover{outline:0}body strong{font-weight:bold}body h1{font-size:2em;margin:.67em 0}body img{border:0}body hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}body pre{overflow:auto}body code,body pre{font-family:monospace,monospace;font-size:1em}body table{border-collapse:collapse;border-spacing:0}body td,body th{padding:0}body *{-moz-box-sizing:border-box;box-sizing:border-box}body a{color:#4183c4;text-decoration:none}body a:hover,body a:focus,body a:active{text-decoration:underline}body hr{height:0;margin:15px 0;overflow:hidden;background:transparent;border:0;border-bottom:1px solid #ddd}body hr:before,body hr:after{display:table;content:" "}body hr:after{clear:both}body h1,body h2,body h3,body h4,body h5,body h6{margin-top:15px;margin-bottom:15px;line-height:1.1}body h1{font-size:30px}body h2{font-size:21px}body h3{font-size:16px}body h4{font-size:14px}body h5{font-size:12px}body h6{font-size:11px}body blockquote{margin:0}body ul,body ol{padding:0;margin-top:0;margin-bottom:0}body ol ol{list-style-type:lower-roman}body dd{margin-left:0}body code,body pre{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:12px}body pre{margin-top:0;margin-bottom:0}body .markdown-body>*:first-child{margin-top:0!important}body .markdown-body>*:last-child{margin-bottom:0!important}body .anchor{position:absolute;top:0;bottom:0;left:0;display:block;padding-right:6px;padding-left:30px;margin-left:-30px}body .anchor:focus{outline:0}body h1,body h2,body h3,body h4,body h5,body h6{position:relative;margin-top:1em;margin-bottom:16px;font-weight:bold;line-height:1.4}body h1{padding-bottom:.3em;font-size:2.25em;line-height:1.2;border-bottom:1px solid #eee}body h2{padding-bottom:.3em;font-size:1.75em;line-height:1.225;border-bottom:1px solid #eee}body h3{font-size:1.5em;line-height:1.43}body h4{font-size:1.25em}body h5{font-size:1em}body h6{font-size:1em;color:#777}body p,body blockquote,body ul,body ol,body dl,body table,body pre{margin-top:0;margin-bottom:16px}body hr{height:4px;padding:0;margin:16px 0;background-color:#e7e7e7;border:0 none}body ul,body ol{padding-left:2em}body ol ol,body ol ul{margin-top:0;margin-bottom:0}body dl{padding:0}body dl dt{padding:0;margin-top:16px;font-size:1em;font-style:italic;font-weight:bold}body dl dd{padding:0 16px;margin-bottom:16px}body blockquote{padding:0 15px;color:#777;border-left:4px solid #ddd}body blockquote>:first-child{margin-top:0}body blockquote>:last-child{margin-bottom:0}body table{display:block;width:100%;overflow:auto}body table th{font-weight:bold}body table th,body table td{padding:6px 13px;border:1px solid #ddd}body table tr{background-color:#fff;border-top:1px solid #ccc}body table tr:nth-child(2n){background-color:#f8f8f8}body img{max-width:100%;-moz-box-sizing:border-box;box-sizing:border-box;page-break-inside:avoid}body code{padding:0;padding-top:.2em;padding-bottom:.2em;margin:0;font-size:85%;background-color:#f7f7f7;border-radius:3px}body code:before,body code:after{letter-spacing:-0.2em;content:"\00a0"}body pre>code{padding:0;margin:0;font-size:100%;white-space:pre;background:transparent;border:0}body .highlight pre,body pre{padding:16px;overflow:auto;font-size:85%;line-height:1.45;background-color:#f7f7f7;border:0;border-radius:3px}body pre{word-wrap:normal}body pre code{display:inline;max-width:initial;padding:0;margin:0;overflow:initial;line-height:inherit;word-wrap:normal;background-color:transparent;border:0}body pre code:before,body pre code:after{content:normal}body .highlight{background:#fff} -------------------------------------------------------------------------------- /2.3.6/scala/book/glossary_index.json: -------------------------------------------------------------------------------- 1 | [] -------------------------------------------------------------------------------- /2.3.6/scala/book/images/actor_lifecycle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/images/actor_lifecycle.png -------------------------------------------------------------------------------- /2.3.6/scala/book/images/akka-remote-testconductor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/images/akka-remote-testconductor.png -------------------------------------------------------------------------------- /2.3.6/scala/book/images/association_lifecycle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/images/association_lifecycle.png -------------------------------------------------------------------------------- /2.3.6/scala/book/images/benchmark-akka-sample-trading-throughput.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/images/benchmark-akka-sample-trading-throughput.png -------------------------------------------------------------------------------- /2.3.6/scala/book/images/build-path.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/images/build-path.png -------------------------------------------------------------------------------- /2.3.6/scala/book/images/camel-pubsub.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/images/camel-pubsub.png -------------------------------------------------------------------------------- /2.3.6/scala/book/images/camel-pubsub2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/images/camel-pubsub2.png -------------------------------------------------------------------------------- /2.3.6/scala/book/images/circuit-breaker-states.dot: -------------------------------------------------------------------------------- 1 | digraph circuit_breaker { 2 | rankdir = "LR"; 3 | size = "6,5"; 4 | graph [ bgcolor = "transparent" ] 5 | node [ fontname = "Helvetica", 6 | fontsize = 14, 7 | shape = circle, 8 | color = white, 9 | style = filled ]; 10 | edge [ fontname = "Helvetica", fontsize = 12 ] 11 | Closed [ fillcolor = green2 ]; 12 | "Half-Open" [fillcolor = yellow2 ]; 13 | Open [ fillcolor = red2 ]; 14 | Closed -> Closed [ label = "Success" ]; 15 | "Half-Open" -> Open [ label = "Trip Breaker" ]; 16 | "Half-Open" -> Closed [ label = "Reset Breaker" ]; 17 | Closed -> Open [ label = "Trip Breaker" ]; 18 | Open -> Open [ label = "Calls failing fast" ]; 19 | Open -> "Half-Open" [ label = "Attempt Reset" ]; -------------------------------------------------------------------------------- /2.3.6/scala/book/images/circuit-breaker-states.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/images/circuit-breaker-states.png -------------------------------------------------------------------------------- /2.3.6/scala/book/images/clojure-trees.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/images/clojure-trees.png -------------------------------------------------------------------------------- /2.3.6/scala/book/images/diagnostics-window.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/images/diagnostics-window.png -------------------------------------------------------------------------------- /2.3.6/scala/book/images/example-code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/images/example-code.png -------------------------------------------------------------------------------- /2.3.6/scala/book/images/faulttolerancesample-failure-flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/images/faulttolerancesample-failure-flow.png -------------------------------------------------------------------------------- /2.3.6/scala/book/images/faulttolerancesample-normal-flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/images/faulttolerancesample-normal-flow.png -------------------------------------------------------------------------------- /2.3.6/scala/book/images/import-project.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/images/import-project.png -------------------------------------------------------------------------------- /2.3.6/scala/book/images/install-beta2-updatesite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/images/install-beta2-updatesite.png -------------------------------------------------------------------------------- /2.3.6/scala/book/images/member-states.drawing: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/images/member-states.drawing -------------------------------------------------------------------------------- /2.3.6/scala/book/images/member-states.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/images/member-states.png -------------------------------------------------------------------------------- /2.3.6/scala/book/images/more.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/images/more.png -------------------------------------------------------------------------------- /2.3.6/scala/book/images/phi1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/images/phi1.png -------------------------------------------------------------------------------- /2.3.6/scala/book/images/phi2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/images/phi2.png -------------------------------------------------------------------------------- /2.3.6/scala/book/images/phi3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/images/phi3.png -------------------------------------------------------------------------------- /2.3.6/scala/book/images/pi-formula.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/images/pi-formula.png -------------------------------------------------------------------------------- /2.3.6/scala/book/images/quickfix.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/images/quickfix.png -------------------------------------------------------------------------------- /2.3.6/scala/book/images/run-config.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/book/images/run-config.png -------------------------------------------------------------------------------- /2.3.6/scala/book/images/tcp-message-protocol_bind-connect-maxed-out.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 2013-01-23 14:28ZCanvas 1Layer 1TcpManagerTcpSelectorUser ActorBind(…) / Connect(…)Maximum number of channels registered with TcpSelectorsCommandFailed(command)**Maximum number of channels registered with TcpSelectorsBind/Connect when max Capacity is reached(via Router)Retry(command, retriesLeft)*(via Router)* if retriesLeft > 0** if retriesLeft == 0 4 | -------------------------------------------------------------------------------- /2.3.6/scala/book/images/tcp-message-protocol_closing.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 2013-01-23 14:28ZCanvas 1Layer 1Connection EstablishedUser ActorTcpConnectionClosed / ConfirmedClosed / AbortedNo Connection EstablishedClose / ConfirmedClose / AbortClosing a Connection 4 | -------------------------------------------------------------------------------- /2.3.6/scala/book/images/tcp-message-protocol_noticing-close.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 2013-01-23 14:28ZCanvas 1Layer 1Connection EstablishedHandlerTcpConnectionClosed / ConfirmedClosed / Aborted / PeerClosed / ErrorClosed(cause)No Connection EstablishedNoticing that a Connection was closed 4 | -------------------------------------------------------------------------------- /2.3.6/scala/book/images/tcp-message-protocol_receiving.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 2013-01-23 14:28ZCanvas 1Layer 1Connection EstablishedTcpSelectorHandlerTcpConnectionChannelReadableReadInterestReceived(data)Connection EstablishedReceiving Data from a Connection 4 | -------------------------------------------------------------------------------- /2.3.6/scala/book/images/tcp-message-protocol_unbinding.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 2013-01-22 22:05ZCanvas 1Layer 1User ActorUnboundUnbindServer BoundTcpListenerServer UnboundUnbinding a Server 4 | -------------------------------------------------------------------------------- /2.3.6/scala/book/images/tcp-message-protocol_writing.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 2013-01-23 14:28ZCanvas 1Layer 1Connection EstablishedTcpSelectorUser ActorTcpConnectionChannelWriteable**WriteInterest**ck***Connection EstablishedWrite(data, ack)Writing to a Connection* if a preceding write is still uncompleted** if all preceding writes have been completed*** if the write has been completed successfully and write.ack != Tcp.NoAck CommandFailed(write)* 4 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter1/01_what_is_akka.md: -------------------------------------------------------------------------------- 1 | # Akka是什么? 2 | 3 | ##### 可扩展的实时事务处理 4 | 5 | 我们相信编写出正确的、具有容错性和可扩展性的并发程序太困难了。这多数是因为使用了错误的工具和错误的抽象级别。Akka就是为了改变这种状况而生的。通过使用Actor模型我们提升了抽象级别,为构建可扩展的、有弹性的响应式并发应用提供了一个更好的平台——详见[《响应式宣言》](http://reactivemanifesto.org/) 。在容错性方面我们采用了“let it crash”(让它崩溃)模型,该模型已经在电信行业构建出“自愈合”的应用和永不停机的系统,取得了巨大成功。Actor还为透明的分布式系统以及真正的可扩展高容错应用的基础进行了抽象。 6 | 7 | Akka是开源的,可以通过Apache 2许可获得。 8 | 9 | 可以从 http://akka.io/downloads/ 下载 10 | 11 | 请注意所有的代码示例都是可编译的,所以如果你想直接获得源代码,可以查看github的"Akka Docs"子项目——[java](http://github.com/akka/akka/tree/v2.3.6/akka-docs/rst/java/code/docs)和[scala](http://github.com/akka/akka/tree/v2.3.6/akka-docs/rst/scala/code/docs) 12 | 13 | ### Akka实现了独特的混合模型 14 | 15 | ##### Actors 16 | 17 | Actors为你提供: 18 | 19 | * 对并发/并行程序的简单的、高级别的抽象。 20 | * 异步、非阻塞、高性能的事件驱动编程模型。 21 | * 非常轻量的事件驱动处理(1G内存可容纳数百万个actors)。 22 | 23 | 参阅 [Actors (Scala)](../chapter3/01_actors.md) 和 [Actors (Java)](#TODO) 24 | 25 | 26 | ##### 容错性 27 | 28 | * 使用“let-it-crash”语义的监控层次体系。 29 | * 监控层次体系可以跨越多个JVM,从而提供真正的容错系统。 30 | * 非常适合编写永不停机、自愈合的高容错系统。 31 | 32 | 参阅 [容错性 (Scala)](../chapter3/03_fault_tolerance.md) 和 [容错性 (Java)](#TODO) 33 | 34 | ##### 位置透明性 35 | Akka的所有元素都为分布式环境而设计:所有actor只通过发送消息进行交互,所有操作都是异步的。 36 | 37 | 集群支持概览请参阅[Java](#TODO)和[Scala](../chapter5/02_cluster_usage.md)文档相关章节。 38 | 39 | 40 | ##### 持久性 41 | 42 | actor接收到的消息可以选择性的被持久化,并在actor启动或重启的时候重放。这使得actor能够恢复其状态,即使是在JVM崩溃或正在迁移到另外节点的情况下。 43 | 44 | 详情请参阅[Java](#TODO)和[Scala](../chapter3/08_persistence.md)相关章节. 45 | 46 | ### Scala 和 Java APIs 47 | Akka同时提供 [Scala API](../README.md) 和 [Java API](#TODO)。 48 | 49 | ### Akka的两种使用方式 50 | 51 | 以库的形式:在web应用中使用,放到 WEB-INF/lib 中或者作为一个普通的Jar包放进classpath。 52 | 53 | 以微内核的形式:可以将你的应用放进一个独立的内核。 54 | 55 | 参阅[用例与部署场景](05_usecase_and_deployment_scenarios.md)了解细节。 56 | 57 | ### 商业支持 58 | Typesafe提供Akka的商业许可,提供开发和产品支持,详见[这里](http://www.typesafe.com/how/subscription) 59 | 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter1/02_why_akka.md: -------------------------------------------------------------------------------- 1 | # 为什么使用Akka? 2 | 3 | ### Akka平台提供哪些有竞争力的特性? 4 | 5 | Akka提供可扩展的实时事务处理。 6 | 7 | Akka为以下目标提供了一致的运行时与编程模型: 8 | 9 | * 垂直扩展(并发) 10 | * 水平扩展(远程调用) 11 | * 高容错 12 | 13 | 这个模型是唯一需要学习和掌握的,它具有高内聚和高一致的语义。 14 | 15 | Akka是一种高度可扩展的软件,这不仅仅表现在性能方面,也表现在它所适用的应用的大小。Akka的核心——akka-actor是非常小的,可以方便地加入你的应用中,提供你所需要的异步无锁并行功能,不会有任何困扰。 16 | 17 | 你可以任意选择Akka的某些组件部分集成到你的应用中,也可以使用完整的包——Akka 微内核,它是一个独立的容器,可以直接部署你的Akka应用。随着CPU核数越来越多,即使你只使用一台主机,Akka也可作为一种性能卓越的选择。Akka还同时提供多种并发范型,允许用户选择正确的工具来完成工作。 18 | 19 | 20 | ### 什么场景下特别适合使用Akka? 21 | 22 | 我们看到Akka被成功运用在众多行业的众多企业中: 23 | 24 | * 投资业到商业银行 25 | * 零售业 26 | * 社会媒体 27 | * 仿真 28 | * 游戏和博彩 29 | * 汽车和交通系统 30 | * 卫生保健 31 | * 数据分析 32 | 等等等等。任何需要高吞吐率和低延迟的系统都是使用Akka的候选。 33 | 34 | Actor使你能够进行服务失败管理(监控),负载管理(缓和策略、超时和处理隔离),以及水平和垂直方向上的可扩展性(增加cpu核数和/或增加更多的机器)管理。 35 | 36 | 下面的链接中有一些Akka用户关于他们如何使用Akka的描述: http://stackoverflow.com/questions/4493001/good-use-case-for-akka 37 | 38 | 所有以上这些都在这个使用Apache2许可的开源软件中。 39 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter1/03_getting_started.md: -------------------------------------------------------------------------------- 1 | # 入门 2 | 3 | ### 准备工作 4 | Akka要求你安装了 [Java 1.6](http://www.oracle.com/technetwork/java/javase/downloads/index.html)或更高版本。 5 | 6 | ### 入门指南和模板工程 7 | 最好的学习Akka的方法是下载[“Typesafe Activator”](http://www.typesafe.com/platform/getstarted)并且尝试一下其中的Akka模板工程。 8 | 9 | ### 下载 10 | 下载Akka有几种方法。你可以通过下载Typesafe平台来下载Akka(如前所述)。你可以下载包含微内核的完整发布包(包含所有的模块)。或者也可以使用构建工具如Maven或SBT从Akka Maven仓库下载依赖。 11 | 12 | 13 | ### 模块 14 | Akka的模块化做得非常好,它为不同的功能提供了不同的Jar包。 15 | 16 | * akka-actor – 标准Actor, 类型Actor,IO Actor等。 17 | * akka-agent – Agent,与 Scala STM 集成 18 | * akka-camel – Apache Camel 集成 19 | * akka-cluster – 集群成员管理,弹性路由器。 20 | * akka-kernel – Akka 微内核来运行简单应用服务器 21 | * akka-osgi – 在OSGi容器中使用Akka的基本组件,包含akka-actor类 22 | * akka-osgi-aries – Aries 的actor系统蓝图 23 | * akka-remote.jar – 远程Actor 24 | * akka-slf4j.jar – SLF4J日志(事件总线监听器) 25 | * akka-testkit.jar – Actor系统的测试工具包 26 | * akka-zeromq – ZeroMQ 集成 27 | 28 | 除了这些稳定的模块之外,还有一些虽然趋于稳定但仍然被标记为“实验”的模块。这并不是说他们的功能不符合预期,而主要的意思是他们的API还没有足够稳定到被认为已经固定了。你可以通过在我们的邮件组里进行反馈,来加速试验模块发布的进程。 29 | 30 | * akka-contrib – 一系列的Akka贡献,他们有可能被加入核心模块中,详情见[外部贡献](../chapter8/05_external_contributions.md)。 31 | 32 | 实际的jar包文件名会加上版本号,如akka-actor_2.10-2.3.6.jar(对其他模块也是类似)。 33 | 34 | 查看Akka模块之间的jar依赖的详情在[依赖](../chapter9/01_building_akka.md#dependencies)这一节中。 35 | 36 | 37 | ### 使用发布版 38 | 从http://akka.io/downloads 下载发布包并解压. 39 | 40 | ### 使用快照版 41 | Akka的每日快照发布在 http://repo.akka.io/snapshots/, 版本号中包含 SNAPSHOT 和时间戳. 你可以选择一个快照版,可以决定何时升级到一个新的版本。Akka快照仓库也可以在 http://repo.typesafe.com/typesafe/snapshots/ 找到,此处还包含Akka模块依赖的其它仓库。 42 | 43 | > 警告 44 | 45 | > 不鼓励直接使用Akka快照版(SNAPSHOT)、每日构建版(nightly)和里程碑版(milestone),除非你知道自己在做什么。 46 | 47 | ### 微内核 48 | Akka发布包包含微内核。要运行微内核,将你应用的jar包放到 `deploy` 目录下并运行 `bin` 目录下的脚本即可。 49 | 50 | 关于微内核的更多文档在 [微内核(Scala)](../chapter6/07_microkernel.md) / [微内核(Java)](#TODO)。 51 | 52 | ### 使用构建工具 53 | 54 | Akka可以与支持Maven仓库的构建工具一起使用。 55 | 56 | ### Maven仓库 57 | 58 | 对Akka 2.1-M2 及以后的版本: 59 | 60 | [Maven Central](http://repo1.maven.org/maven2/) 61 | 62 | 对以前的Akka 版本: 63 | 64 | [Akka Repo Typesafe Repo](http://repo.akka.io/releases) 65 | 66 | ### 通过Maven使用Akka 67 | 68 | 通过Maven使用Akka最简单的入门是检出[“Typesafe Activator”](http://www.typesafe.com/platform/getstarted)中的模板工程[“Akka Main in Java”](http://www.typesafe.com/activator/template/akka-sample-main-java)。 69 | 70 | 由于Akka已经发布到Maven中心仓库了(自2.1-M2版本起),所以直接在POM文件中加入Akka依赖即可。例如。这是akka-actor的依赖: 71 | 72 | ```xml 73 | 74 | com.typesafe.akka 75 | akka-actor_2.10 76 | 2.3.6 77 | 78 | ``` 79 | 80 | 注意:对快照版本,SNAPSHOT和时间戳都在版本号中。 81 | 82 | ### 通过SBT使用Akka 83 | 84 | 通过SBT使用Akka最简单的入门是检出[“Akka/SBT”](http://www.typesafe.com/resources/getting-started/typesafe-stack/downloading-installing.html#template-projects-for-scala-akka-and-play)模板工程。 85 | 86 | 通过SBT使用Akka的要点: 87 | 88 | SBT安装指导 https://github.com/harrah/xsbt/wiki/Setup 89 | 90 | `build.sbt` 文件: 91 | 92 | ```sbt 93 | name := "My Project" 94 | 95 | version := "1.0" 96 | 97 | scalaVersion := "2.10.4" 98 | 99 | resolvers += "Typesafe Repository" at "http://repo.typesafe.com/typesafe/releases/" 100 | 101 | libraryDependencies += 102 | "com.typesafe.akka" %% "akka-actor" % "2.3.6" 103 | ``` 104 | 105 | 注意:以上的`libraryDependencies`设置需要SBT 0.12.x或更高的版本。如果你使用更老版本的SBT,`libraryDependencies`需要这样设置: 106 | 107 | ```sbt 108 | libraryDependencies += 109 | "com.typesafe.akka" % "akka-actor_2.10" % "2.3.6" 110 | ``` 111 | 112 | ### Using Akka with Gradle 113 | 114 | 需要 [Gradle](http://gradle.org/) 1.4 及以上的版本来使用 [Scala 插件](http://gradle.org/docs/current/userguide/scala_plugin.html) 115 | 116 | ```gradle 117 | apply plugin: 'scala' 118 | 119 | repositories { 120 | mavenCentral() 121 | } 122 | 123 | dependencies { 124 | compile 'org.scala-lang:scala-library:2.10.4' 125 | } 126 | 127 | tasks.withType(ScalaCompile) { 128 | scalaCompileOptions.useAnt = false 129 | } 130 | 131 | dependencies { 132 | compile group: 'com.typesafe.akka', name: 'akka-actor_2.10', version: '2.3.6' 133 | compile group: 'org.scala-lang', name: 'scala-library', version: '2.10.4' 134 | } 135 | ``` 136 | 137 | ### 通过Eclipse使用Akka 138 | 建好SBT项目并使用 [sbteclipse](https://github.com/typesafehub/sbteclipse) 来创建Eclipse项目。 139 | 140 | ### 通过IntelliJ IDEA使用Akka 141 | 建好SBT项目并使用 [sbt-idea](https://github.com/mpeltonen/sbt-idea) 来创建IntelliJ IDEA 项目。 142 | 143 | ### 通过NetBeans使用Akka 144 | 建好SBT项目并使用 [nbsbt](https://github.com/dcaoyuan/nbsbt) 来创建NetBeans项目。 145 | 146 | 你也应该使用[nbscala](https://github.com/dcaoyuan/nbscala)提供的scala IDE支持 147 | 148 | ### 不要使用scala编译器的-optimize选项 149 | 150 | > 警告 151 | 152 | > Akka并没有在scala编译器的`-optimize`选项下编译和测试过。尝试过这种方式的用户发现了Akka的奇怪行为。 153 | 154 | ### 从源码编译 155 | 156 | Akka使用Git并托管在 [Github](http://github.com/)。 157 | 158 | * Akka: 从 http://github.com/akka/akka 克隆 Akka 的资源库 159 | 160 | 具体请参考 [构建Akka](../chapter9/01_building_akka.md)。 161 | 162 | ### 需要帮助? 163 | 164 | 如果有问题,你可以在 [Akka Mailing List](http://groups.google.com/group/akka-user) 获得帮助。 165 | 166 | 也可以寻求 [商业支持](http://www.typesafe.com)。 167 | 168 | 感谢你成为Akka社区的一部分。 169 | 170 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter1/04_the_obligatory_hello_world.md: -------------------------------------------------------------------------------- 1 | # 必修的“Hello World” 2 | 3 | 将著名的问候语——“Hello World”——打印在控制台中,这个艰巨任务的actor版在[Typesafe Activator](http://www.typesafe.com/platform/getstarted)中一个名为[“Akka Main in Scala”](http://www.typesafe.com/activator/template/akka-sample-main-scala)的教程中有介绍。 4 | 5 | 这个教程展示了一个通用启动类`akka.Main`,它只需要一个命令行参数:应用主actor的类名。这个main方法会创建actor需要的底层运行环境,启动主actor,并且做好在主actor结束的时候关闭整个系统的准备。 6 | 7 | 另外还有一个名为[Hello Akka!](http://www.typesafe.com/activator/template/hello-akka) 的 [Typesafe Activator](http://www.typesafe.com/platform/getstarted)教程也是关于这一问题的,不过它更加深入的描述了Akka的基础。 8 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter1/05_usecase_and_deployment_scenarios.md: -------------------------------------------------------------------------------- 1 | # 用例和部署场景 2 | 3 | ### 我该如何使用和部署 Akka? 4 | 5 | Akka 可以有几种使用方式: 6 | 7 | * 作为一个库: 以普通jar包的形式放在classpath上,或放到web应用中的 `WEB-INF/lib`位置 8 | * 作为一个独立的应用程序,使用[微内核(Scala)](../chapter6/07_microkernel.md) / [微内核(Java)](#TODO) ,自己使用一个main类来初始化Actor系统 9 | 10 | 11 | ##### 将Akka作为一个库 12 | 当编写web应用的时候,你很可能要使用这种方式。通过添加更多的模块,可以有多种使用Akka库模式的方式。 13 | 14 | ##### 将Akka用作单独的微内核 15 | Akka 也可以作为独立微内核使用。参阅 [微内核(Scala)](../chapter6/07_microkernel.md) / [微内核(Java)](#TODO) 获取更多信息. 16 | 17 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter1/06_examples_of_usecases_for_akka.md: -------------------------------------------------------------------------------- 1 | # Akka使用实例 2 | 3 | 我们看到Akka被成功运用在众多行业的众多大企业,从投资业到商业银行、从零售业到社会媒体、仿真、游戏和博彩、汽车和交通系统、医疗保健、数据分析等等等等。对任何需要高吞吐率和低延迟的系统,Akka都是优秀的候选。 4 | 5 | [这里](http://stackoverflow.com/questions/4493001/good-use-case-for-akka/4494512#4494512)是一个由生产用户撰写的关于Akka的使用实例的非常好的讨论 6 | 7 | ### 以下是Akka被部署到生产环境中的领域 8 | 9 | ##### 事务处理 (在线游戏,金融/银行业,贸易,统计,赌博,社会媒体,电信) 10 | 垂直扩展,水平扩展,容错/高可用性 11 | 12 | ##### 服务后端 (任何行业,任何应用) 13 | 提供REST, SOAP, Cometd, WebSockets 等服务;作为消息总线/集成层;垂直扩展,水平扩展,容错/高可用性 14 | 15 | ##### 并发/并行 (任何应用) 16 | 运行正确,方便使用,只需要将jar包添加到现有的JVM项目中(可使用Scala,Java, Groovy或JRuby) 17 | 18 | ##### 仿真 19 | 主/从,计算网格,MapReduce等等 20 | 21 | ##### 批处理 (任何行业) 22 | Camel集成来连接批处理数据源,Actor分治批处理工作负载 23 | 24 | ##### 通信Hub (电信, Web媒体, 手机媒体) 25 | 垂直扩展,水平扩展,容错/高可用性 26 | 27 | ##### 游戏与博彩 (MOM, 在线游戏, 博彩) 28 | 垂直扩展,水平扩展,容错/高可用性 29 | 30 | ##### 商业智能/数据挖掘/通用密集计算 31 | 垂直扩展,水平扩展,容错/高可用性 32 | 33 | ##### 复杂事件流处理 34 | 垂直扩展,水平扩展,容错/高可用性 35 | 36 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter1/introduction.md: -------------------------------------------------------------------------------- 1 | # 引言 2 | 3 | * [Akka是什么](01_what_is_akka.md) 4 | * Akka实现了独特的混合模型 5 | * Scala 和 Java API 6 | * 使用Akka的两种方式 7 | * 商业支持 8 | * [为什么使用Akka?](02_why_akka.md) 9 | * Akka平台提供哪些有竞争力的特性? 10 | * Akka特别适合什么场景? 11 | * [入门](03_getting_started.md) 12 | * 准备工作 13 | * 入门指南和模板工程 14 | * 下载 15 | * 模块 16 | * 使用发布版 17 | * 使用快照版 18 | * 微内核 19 | * 使用build工具 20 | * Maven仓库 21 | * 通过Maven使用Akka 22 | * 通过SBT使用Akka 23 | * 通过Gradle使用Akka 24 | * 通过Eclipse使用Akka 25 | * 通过IntelliJ IDEA使用Akka 26 | * 通过NetBeans使用Akka 27 | * 不要使用scala编译器的-optimize选项 28 | * 从源码编译 29 | * 需要帮助? 30 | * [必修的“Hello World”](04_the_obligatory_hello_world.md) 31 | * [用例和部署场景](05_usecase_and_deployment_scenarios.md) 32 | * 我该如何使用和部署Akka? 33 | * [Akka使用实例](06_examples_of_usecases_for_akka.md) 34 | * 这里是一些将Akka用于生产环境的领域 35 | 36 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter10/01_migration_guides.md: -------------------------------------------------------------------------------- 1 | # 迁移指南 2 | 3 | * [Migration Guide 1.3.x to 2.0.x](http://doc.akka.io/docs/akka/2.3.6/project/migration-guide-1.3.x-2.0.x.html) 4 | * [Migration Guide 2.0.x to 2.1.x](http://doc.akka.io/docs/akka/2.3.6/project/migration-guide-2.0.x-2.1.x.html) 5 | * [Migration Guide 2.1.x to 2.2.x](http://doc.akka.io/docs/akka/2.3.6/project/migration-guide-2.1.x-2.2.x.html) 6 | * [Migration Guide 2.2.x to 2.3.x](http://doc.akka.io/docs/akka/2.3.6/project/migration-guide-2.2.x-2.3.x.html) 7 | * [Migration Guide Akka Persistence (experimental) 2.3.3 to 2.3.4 (and 2.4.x)](http://doc.akka.io/docs/akka/2.3.6/project/migration-guide-persistence-experimental-2.3.x-2.4.x.html) 8 | * [Migration Guide Eventsourced to Akka Persistence 2.3.x](http://doc.akka.io/docs/akka/2.3.6/project/migration-guide-eventsourced-2.3.x.html) -------------------------------------------------------------------------------- /2.3.6/scala/chapter10/02_issue_tracking.md: -------------------------------------------------------------------------------- 1 | # 问题追踪 2 | 3 | Akka使用 GitHub Issues作为其问题跟踪系统。 4 | 5 | ### 浏览 6 | 7 | ##### Tickets 8 | 在提交一张ticket之前,请检查现有的[Akka tickets](https://github.com/akka/akka/issues)是否在早些时候报告了同样的问题。非常欢迎你在现有的ticket中发表评论,尤其是当你有可以分享的重复性测试用例的时候。 9 | 10 | ##### 路线图 11 | 请参看[Akka路线图](https://docs.google.com/document/d/18W9-fKs55wiFNjXL9q50PYOnR7-nnsImzJqHOPPbM4E/pub),以找出即将发行的Akka版本中的总体主题。 12 | 13 | ### 创建ticket 14 | *请包括 Scala 和Akka的版本及相关配置文件。* 15 | 16 | 如果你已经注册了 GitHub 的用户,你可以创建一张[新问题单](https://github.com/akka/akka/issues/new)。 17 | 18 | 非常感谢报告 bug 以及建议功能 ! -------------------------------------------------------------------------------- /2.3.6/scala/chapter10/03_licenses.md: -------------------------------------------------------------------------------- 1 | # 许可证 2 | 3 | Akka License 4 | ------------ 5 | 6 | This software is licensed under the Apache 2 license, quoted below. 7 | 8 | Copyright 2009-2014 Typesafe Inc. 9 | 10 | Licensed under the Apache License, Version 2.0 (the "License"); you may not 11 | use this file except in compliance with the License. You may obtain a copy of 12 | the License at 13 | 14 | http://www.apache.org/licenses/LICENSE-2.0 15 | 16 | Unless required by applicable law or agreed to in writing, software 17 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 18 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 19 | License for the specific language governing permissions and limitations under 20 | the License. 21 | 22 | Akka Committer License Agreement 23 | -------------------------------- 24 | 25 | All committers have signed this [CLA](http://www.typesafe.com/contribute/current-cla). 26 | It can be [signed online](http://www.typesafe.com/contribute/cla). 27 | 28 | Licenses for Dependency Libraries 29 | --------------------------------- 30 | 31 | Each dependency and its license can be seen in the project build file (the comment on the side of each dependency): 32 | [AkkaBuild.scala](http://github.com/akka/akka/tree/v2.3.6/project/AkkaBuild.scala#L1054) 33 | 34 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter10/04_sponsors.md: -------------------------------------------------------------------------------- 1 | # 赞助商 2 | 3 | Typesafe 4 | -------- 5 | 6 | Typesafe is the company behind the Akka Project, Scala Programming Language, 7 | Play Web Framework, Scala IDE, Simple Build Tool and many other open source 8 | projects. It also provides the Typesafe Stack, a full-featured development 9 | stack consisting of Akka, Play and Scala. Learn more at 10 | [typesafe.com](http://www.typesafe.com). 11 | 12 | YourKit 13 | ------- 14 | 15 | YourKit is kindly supporting open source projects with its full-featured Java Profiler. 16 | 17 | YourKit, LLC is the creator of innovative and intelligent tools for profiling Java 18 | and .NET applications. Take a look at YourKit’s leading software products: 19 | [YourKit Java Profiler](http://www.yourkit.com/java/profiler/index.jsp) 20 | and [YourKit .NET Profiler](http://www.yourkit.com/.net/profiler/index.jsp) 21 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter10/05_project.md: -------------------------------------------------------------------------------- 1 | # 项目 2 | 3 | ### Commercial Support 4 | 5 | Commercial support is provided by `Typesafe `_. 6 | Akka is part of the `Typesafe Reactive Platform `_. 7 | 8 | ### Mailing List 9 | 10 | [Akka User Google Group](http://groups.google.com/group/akka-user) 11 | 12 | [Akka Developer Google Group](http://groups.google.com/group/akka-dev) 13 | 14 | 15 | ### Downloads 16 | 17 | [`http://akka.io/downloads`](http://akka.io/downloads) 18 | 19 | 20 | ### Source Code 21 | 22 | Akka uses Git and is hosted at [Github](http://github.com). 23 | 24 | * Akka: clone the Akka repository from [`http://github.com/akka/akka`](http://github.com/akka/akka) 25 | 26 | 27 | ### Releases Repository 28 | 29 | All Akka releases are published via Sonatype to Maven Central, see 30 | [search.maven.org](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.typesafe.akka%22) 31 | 32 | ### Snapshots Repository 33 | 34 | Nightly builds are available in http://repo.akka.io/snapshots/ as both ``SNAPSHOT`` and 35 | timestamped versions. 36 | 37 | For timestamped versions, pick a timestamp from 38 | http://repo.akka.io/snapshots/com/typesafe/akka/akka-actor_@binVersion@/. 39 | All Akka modules that belong to the same build have the same timestamp. 40 | 41 | ##### sbt definition of snapshot repository 42 | 43 | Make sure that you add the repository to the sbt resolvers:: 44 | 45 | resolvers += "Typesafe Snapshots" at "http://repo.akka.io/snapshots/" 46 | 47 | Define the library dependencies with the timestamp as version. For example:: 48 | 49 | libraryDependencies += "com.typesafe.akka" % "akka-remote_@binVersion@" % 50 | "2.1-20121016-001042" 51 | 52 | ##### maven definition of snapshot repository 53 | 54 | Make sure that you add the repository to the maven repositories in pom.xml:: 55 | 56 | 57 | 58 | akka-snapshots 59 | Akka Snapshots 60 | http://repo.akka.io/snapshots/ 61 | default 62 | 63 | 64 | 65 | Define the library dependencies with the timestamp as version. For example:: 66 | 67 | 68 | 69 | com.typesafe.akka 70 | akka-remote_@binVersion@ 71 | 2.1-20121016-001042 72 | 73 | 74 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter10/project_information.md: -------------------------------------------------------------------------------- 1 | # 工程信息 2 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter11/01_faq.md: -------------------------------------------------------------------------------- 1 | # 常见问题 2 | 3 | ### Akka Project 4 | 5 | ##### Where does the name Akka come from? 6 | 7 | It is the name of a beautiful Swedish [mountain](https://lh4.googleusercontent.com/-z28mTALX90E/UCOsd249TdI/AAAAAAAAAB0/zGyNNZla-zY/w442-h331/akka-beautiful-panorama.jpg) 8 | up in the northern part of Sweden called Laponia. The mountain is also sometimes 9 | called 'The Queen of Laponia'. 10 | 11 | Akka is also the name of a goddess in the Sámi (the native Swedish population) 12 | mythology. She is the goddess that stands for all the beauty and good in the 13 | world. The mountain can be seen as the symbol of this goddess. 14 | 15 | Also, the name AKKA is the a palindrome of letters A and K as in Actor Kernel. 16 | 17 | Akka is also: 18 | 19 | * the name of the goose that Nils traveled across Sweden on in [The Wonderful Adventures of Nils](http://en.wikipedia.org/wiki/The_Wonderful_Adventures_of_Nils) by the Swedish writer Selma Lagerlöf. 20 | * the Finnish word for 'nasty elderly woman' and the word for 'elder sister' in the Indian languages Tamil, Telugu, Kannada and Marathi. 21 | * a [font](http://www.dafont.com/akka.font) 22 | * a town in Morocco 23 | * a near-earth asteroid 24 | 25 | ### Actor总体 26 | ##### 当我在Actor中使用Future时,sender()/getSender()消失了,为什么呢? 27 | 当在Actor内部使用Future回调时需要小心,避免闭合包含Actor的引用,即对闭合的Actor不在回调内调用方法或访问其内的可变状态。这将打破Actor封装,因为回调将被调度与闭合的Actor并发执行,所以可能会引入同步 bug 和竞态条件。不幸的是没有编译时的方法发现这些非法访问。 28 | 29 | 更多内容参见[Actor与共享可变状态](../chapter2/07_akka_and_the_java_memory_model.md#jmm-shared-state)的文档。 30 | 31 | ##### 为什么发生OutOfMemoryError? 32 | 产生OutOfMemoryError错误的原因很多。例如,在基于纯推送系统中,消费者的消息处理速度可能低于相应消息生产者,必须添加某种消息流量控制。否则邮件将在消费者的邮箱中排队,从而填满堆内存。 33 | 34 | 一些寻找灵感的文章: 35 | 36 | * [Balancing Workload across Nodes with Akka 2](http://letitcrash.com/post/29044669086/balancing-workload-across-nodes-with-akka-2) 37 | * [Work Pulling Pattern to prevent mailbox overflow, throttle and distribute work](http://www.michaelpollmeier.com/akka-work-pulling-pattern/) 38 | 39 | ### Actors Scala API 40 | 41 | ##### 我怎么会得到`receive`方法丢失消息的编译时错误呢? 42 | 43 | 一种解决方案来帮助你获得警告,因为基于你的actor输入输出消息实现基本特质的定义,编译时将检查的处理消息的全面性,如有遗漏将会告警。 44 | 45 | 这里有一个例子,编译器将发出警告你接收的比配并不是详尽无遗的: 46 | 47 | ```scala 48 | object MyActor { 49 | // these are the messages we accept 50 | sealed abstract trait Message 51 | case class FooMessage(foo: String) extends Message 52 | case class BarMessage(bar: Int) extends Message 53 | 54 | // these are the replies we send 55 | sealed abstract trait Reply 56 | case class BazMessage(baz: String) extends Reply 57 | } 58 | 59 | class MyActor extends Actor { 60 | import MyActor._ 61 | def receive = { 62 | case message: Message => message match { 63 | case BarMessage(bar) => sender ! BazMessage("Got " + bar) 64 | // warning here: 65 | // "match may not be exhaustive. It would fail on the following input: FooMessage(_)" 66 | } 67 | } 68 | } 69 | ``` 70 | 71 | ### Remoting 72 | 73 | ##### 我想发送到远程系统,但它没有做任何事情 74 | 75 | 请确保你有在两端上都启用远程处理:客户端和服务器。两端都需要配置主机名和端口,而且你将需要知道服务器端口;客户端在大多数情况下可以使用一个自动的港口(即配置端口为零)。如果这两个系统在同一网络主机上运行,它们的端口必须是不同的。 76 | 77 | 如果仍然看不到任何东西,看看远程的生命周期事件的日志记录了什么 (通常在 INFO 级别) 或打开[辅助的远程日志记录选项](../chapter6/02_logging.md#logging-remote-java),以查看所有发送和接收消息 (在DEBUG级别)。 78 | 79 | ##### 调试远程处理问题时,应启用哪些选项? 80 | 详见[远程配置](../chapter5/03_remoting.md#remote-configuration-scala),典型的候选人是: 81 | 82 | * `akka.remote.log-sent-messages` 83 | * `akka.remote.log-received-messages` 84 | * `akka.remote.log-remote-lifecycle-events` (this also includes deserialization errors) 85 | 86 | ##### 远程Actor的名字是什么? 87 | 当你想要将消息发送到远程主机上的Actor时,你需要知道它的[完整路径](../chapter2/05_actor_references_paths_and_addresses.md#addressing),格式如下: 88 | 89 | akka.protocol://system@host:1234/user/my/actor/hierarchy/path 90 | 91 | 所需要的部分是: 92 | 93 | * ``protocol``是要用来与远程系统进行通信的协议。大多数情况下是 `tcp`。 94 | 95 | * ``system``是远程系统的名称 (必须完全匹配,区分大小写!) 96 | 97 | * ``host``是远程系统的 IP 地址或 DNS 名称,它必须匹配该系统的配置 (即 `akka.remote.netty.hostname`) 98 | 99 | * ``1234`` 是侦听连接和接收消息的远程系统的端口号 100 | 101 | * ``/user/my/actor/hierarchy/path`` 是远程Actor在远程系统监督层次结构中的绝对路径 ,包括系统的监护者(即 ``/user``还有其他如``/system``承载日志记录器,``/temp`` 保存使用``ask()``创建的临时Actor引用,`/remote`启用远程部署等);这符合该Actor在远程主机上打印它自身的引用的方式,例如在日志输出。 102 | 103 | ##### 为什么没有收到远程Actor的答复? 104 | 最常见的原因是本地系统名称 (即上述答案中的 ``system@host:1234`` 部分) 是从远程系统的网络位置不可以到达的,例如因为``host``被配置为为``0.0.0.0``,``localhost``或 NAT'ed IP 地址。 105 | 106 | ##### 消息如何可靠传递? 107 | 一般的规则是**至多一次交付(at-most-once delivery)**,即没有保证。可以在其上面建立更强的可靠性,Akka提供了工具来这样做。 108 | 109 | 详见[消息传递可靠性](../chapter2/08_message_delivery_reliability.md#message-delivery-reliability)。 110 | 111 | ### 调试 112 | 113 | ##### 如何打开调试日志记录 114 | 若要打开actor系统调试日志记录,添加如下配置: 115 | 116 | akka.loglevel = DEBUG 117 | 118 | 若要打开不同类型的调试日志记录,添加如下配置: 119 | 120 | * ``akka.actor.debug.receive`` 将记录发送到一个actor的所有消息,如果actor `receive`方法是 ``LoggingReceive`` 121 | * ``akka.actor.debug.autoreceive`` 将记录发送给所有actor的所有*特殊*消息如``Kill``, ``PoisonPill``等 122 | * ``akka.actor.debug.lifecycle`` 将记录所有actor的所有actor生命周期事件 123 | 124 | 更多内容参见[日志记录](../chapter6/02_logging.md#logging-scala) 和 [追踪Actor调用](../chapter3/09_testing_actor_systems.md#actor-logging-scala) 。 -------------------------------------------------------------------------------- /2.3.6/scala/chapter11/02_books.md: -------------------------------------------------------------------------------- 1 | # 图书 2 | 3 | * [Akka in Action](http://typesafe.com/resources/e-book/akka-in-action), by Raymond Roestenburg and Rob Bakker, Manning Publications Co., ISBN: 9781617291012, est fall 2013 4 | * [Akka Concurrency](http://www.artima.com/shop/akka_concurrency), by Derek Wyatt, artima developer, ISBN: 0981531660, est April 2013 5 | * [Akka Essentials](http://www.packtpub.com/akka-java-applications-essentials/book), by Munish K. Gupta, PACKT Publishing, ISBN: 1849518289, October 2012 6 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter11/03_other_language_bindings.md: -------------------------------------------------------------------------------- 1 | # 其他语言绑定 2 | 3 | JRuby 4 | ----- 5 | 6 | Read more here: https://github.com/iconara/mikka. 7 | 8 | Groovy/Groovy++ 9 | --------------- 10 | 11 | Read more here: https://gist.github.com/620439. 12 | 13 | Clojure 14 | ------- 15 | 16 | Read more here: http://blog.darevay.com/2011/06/clojure-and-akka-a-match-made-in/. 17 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter11/04_akka_in_osgi.md: -------------------------------------------------------------------------------- 1 | # Akka与OSGi 2 | 3 | 4 | Configuring the OSGi Framework 5 | ------------------------------ 6 | 7 | To use Akka in an OSGi environment, the ``org.osgi.framework.bootdelegation`` 8 | property must be set to always delegate the ``sun.misc`` package to the boot classloader 9 | instead of resolving it through the normal OSGi class space. 10 | 11 | Activator 12 | --------- 13 | 14 | To bootstrap Akka inside an OSGi environment, you can use the ``akka.osgi.ActorSystemActivator`` class 15 | to conveniently set up the ActorSystem. 16 | 17 | ```scala 18 | import akka.actor.{ Props, ActorSystem } 19 | import org.osgi.framework.BundleContext 20 | import akka.osgi.ActorSystemActivator 21 | 22 | class Activator extends ActorSystemActivator { 23 | 24 | def configure(context: BundleContext, system: ActorSystem) { 25 | // optionally register the ActorSystem in the OSGi Service Registry 26 | registerService(context, system) 27 | 28 | val someActor = system.actorOf(Props[SomeActor], name = "someName") 29 | someActor ! SomeMessage 30 | } 31 | 32 | } 33 | ``` 34 | 35 | The ``ActorSystemActivator`` creates the actor system with a class loader that finds resources 36 | (``reference.conf`` files) and classes from the application bundle and all transitive dependencies. 37 | 38 | The ``ActorSystemActivator`` class is included in the ``akka-osgi`` artifact:: 39 | 40 | 41 | com.typesafe.akka 42 | akka-osgi_@binVersion@ 43 | @version@ 44 | 45 | 46 | 47 | Sample 48 | ------ 49 | 50 | A complete sample project is provided in [akka-sample-osgi-dining-hakkers](http://github.com/akka/akka/tree/v2.3.6/akka-samples/akka-sample-osgi-dining-hakkers). 51 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter11/05_incomplete_list_of_http_frameworks.md: -------------------------------------------------------------------------------- 1 | # 部分HTTP框架名单 2 | 3 | Play 4 | ==== 5 | 6 | The [Play framework](http://www.playframework.com) is built using Akka, and is well suited for building both full web applications as well as REST services. 7 | 8 | Spray 9 | ===== 10 | 11 | The [Spray toolkit](http://spray.io) is built using Akka, and is a minimalistic HTTP/REST layer. 12 | 13 | Akka Mist 14 | ========= 15 | 16 | If you are using Akka Mist (Akka's old HTTP/REST module) with Akka 1.x and wish to upgrade to 2.x 17 | there is now a port of Akka Mist to Akka 2.x. You can find it [here](https://github.com/thenewmotion/akka-http). 18 | 19 | Other Alternatives 20 | ================== 21 | 22 | There are a bunch of other alternatives for using Akka with HTTP/REST. You can find some of them 23 | among the [Community Projects](http://akka.io/community). 24 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter11/additional_information.md: -------------------------------------------------------------------------------- 1 | # 附加信息 2 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter2/01_terminology_concepts.md: -------------------------------------------------------------------------------- 1 | # 术语,概念 2 | 3 | 这一章我们将尝试建立通用的术语,对Akka面向的并发、分布式系统等提供一个坚实的讨论基础。请注意,这里的很多术语都没有统一的定义。我们只是希望在Akka文档的范围内给出可用的定义。 4 | 5 | ### 并发 vs. 并行 6 | 7 | 并发和并行是相关的定义,有一些微小的不同。*并发* 指的是两个或多个任务都有进展,即使他们没有被同时执行。例如可以这样实现:划分出时间片,几个任务交叉执行,尽管时间片的执行是线性的。*并行* 则是指可以真正同时执行。 8 | 9 | ### 异步 vs. 同步 10 | 11 | 一个方法调用是 *同步* 的,当调用者不能继续处理,除非方法返回一个值或抛出一个异常。另一方面,一个 *异步* 调用允许调用者在调用方法的有限步后能够继续执行,并且该方法的结束可以被额外的机制通知到(也许是一个注册的回调callback,一个Future或一个消息)。 12 | 13 | 一个同步的API也许会使用阻塞实现同步性,但也不是必须的。一个CPU极为密集的任务也会导致类似阻塞的行为。通常推荐使用非阻塞API,因为它们能确保系统继续处理。Actor本质上是异步的:一个Actor可以在发送消息后继续处理,而不需要等待消息确实被送达。 14 | 15 | ### 非阻塞 vs. 阻塞 16 | 17 | 如果一个线程的延迟会导致其它一些线程无限期的延迟,我们称之为 *阻塞*。一个很好的例子是资源可以被线程通过互斥锁独占。如果这个线程无限期地占有这个资源(例如不小心进入死循环),其他等待这个资源的线程就无法处理了。相反地,*非阻塞* 意味着没有线程可以无限期的阻塞其他线程。 18 | 19 | 相比阻塞操作,我们推荐非阻塞的操作,因为很明显这样系统不会因为阻塞操作而不再继续处理。 20 | 21 | 22 | ### 死锁 vs. 饥饿 vs. 活锁 23 | 24 | 当多个参与者互相等待别人达到某个特殊的状态才能继续处理的时候,*死锁* 出现了。因为如果一些参与者不达到特定状态,所有的参与者都不能执行(就像[《第二十二条军规》](http://en.wikipedia.org/wiki/Catch-22)描述的那样),所有相关子系统都停顿了。死锁和阻塞息息相关,因为阻塞使得一个参与者线程可以无限期地推迟其他线程的处理。 25 | 26 | 在死锁中,没有参与者可以处理,然而相对的 *饥饿* 可能发生,当有些参与者可以不断地处理,而另一些可能不行。一个典型的场景是一个幼稚的调度算法——总是选择高优先级的任务。如果高优先级的任务数量一直足够多,则低优先级的任务永远不会被完成。 27 | 28 | *活锁* 和死锁类似,没有参与者可以处理。区别在于与进程进入等待其他进程处理的“冻结”状态不同,参与者不断地变换他们的状态。一个示例场景是两个参与者和两个特殊的资源。他们分别试图获取资源,并且检查是不是另一个参与者也需要这个资源。如果该资源被另一个参与者请求,则它们试图获取另一个资源。在一个很不幸的情况下,也许两个参与者会不停的在两个资源上“跳跃”,永远在谦让而不使用资源。 29 | 30 | ### 竞态条件 31 | 32 | 当一组事件的顺序假设可能被外部不确定因素影响,我们称之为 *竞态条件*。竞态条件经常在多个线程共享一个可变状态时出现,一个线程对这个状态的操作可能被交织从而导致意外的行为。尽管这是常见的情况,但是共享状态并不一定会导致竞态条件。例如一个客户端向服务器发送无序的包(例如UDP数据包)`P1`,`P2`。由于包可能经过不同的网络路由器传送,所以服务器可能先收到`P2`,后收到`P1`。如果消息中没有包含发送顺序的相关信息的话,服务器是不可能确定包是否是按照发送顺序接收的。根据包的内容这可能会导致竞态条件。 33 | 34 | > 注意 35 | 36 | > 对两个actor之间的消息发送,Akka唯一提供的保证是消息的发送顺序是被保留的。详见 [消息传送可靠性Message Delivery Reliability](08_message_delivery_reliability.md) 37 | 38 | 39 | ### 非阻塞担保(进展条件) 40 | 41 | 就像前几个章节描述的,阻塞是不受欢迎的,因为它有可能导致死锁并降低系统的吞吐量。在下面几节,我们将从不同深度讨论各种无阻塞特性。 42 | 43 | 44 | ##### 无等待(Wait-freedom) 45 | 46 | 如果一个方法的调用可以保证在有限步骤内完成,则称该方法是 *无等待* 的。如果方法是 *有界无等待* 的,则方法的执行步数有一个确定的上界。 47 | 48 | 从这个定义可以得出无等待的方法永远不会阻塞,因此死锁是不可能发生的。此外,因为每个参与者都可以经过有限步后继续执行(当调用完成),所以无等待方法也不会出现饥饿的情况。 49 | 50 | ##### 无锁(Lock-freedom) 51 | 52 | *无锁* 是比 *无等待* 更弱的特性。在无锁调用的情况下,无限地经常有一些方法在有限步骤内完成。这个定义暗示着对无锁调用是不可能出现死锁的。另一方面,*部分方法调用* 在有限步骤内 *结束*,不足以保证*所有调用最终完成*。换句话说,无锁不足以保证不会出现饥饿。 53 | 54 | ##### 无阻碍(Obstruction-freedom) 55 | 56 | *无阻碍* 是这里讨论的最弱的无阻塞保证。对一个方法,当在某一个它独自执行的时间点(其他线程不在执行,例如都挂起了),之后它在有限步后能够结束,我们称之为 *无阻碍*。所有无锁的对象都是无阻碍的,但反之一般不成立。 57 | 58 | *乐观并发模型OCC(Optimistic concurrency control )* 的方法通常是无阻碍的。OCC的做法是,每一位参与者都试图在共享对象上执行操作,但是如果参与者检测到来自其他参与者的冲突,它回滚修改,并根据调度再次尝试。如果在某一个时间点,其中一个参与者,是唯一一个尝试修改的点,则其操作就会成功。 59 | 60 | ### 推荐文献 61 | 62 | * The Art of Multiprocessor Programming, M. Herlihy and N Shavit, 2008. ISBN 978-0123705914 (注:中文译[《多处理器编程的艺术》](http://book.douban.com/subject/3901836/)) 63 | * Java Concurrency in Practice, B. Goetz, T. Peierls, J. Bloch, J. Bowbeer, D. Holmes and D. Lea, 2006. ISBN 978-0321349606(注:中文译[《Java并发编程实战》](http://book.douban.com/subject/10484692/)) 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter2/02_actor_systems.md: -------------------------------------------------------------------------------- 1 | # Actor系统 2 | 3 | Actor是封装状态和行为的对象,他们唯一的通讯方式是交换消息——把消息存放在接收方的邮箱里。从某种意义上来说,actor是面向对象最严格的形式,不过最好把它们比作人:在使用actor来对解决方案建模时,把actor想象成一群人,把子任务分配给他们,将他们的功能整理成一个有组织的结构,考虑如何将失败逐级上传(好在我们并不需要真正跟人打交道,这样我们就不需要关心他们的情绪状态和道德问题)。这个结果就可以作为软件实现的思维框架。 4 | 5 | > 注意 6 | 7 | > 一个Actor系统是一个很重的结构,它会分配一到N个线程,所以对每一个逻辑应用创建一个就够了。 8 | 9 | ### 树形结构 10 | 11 | 象一个经济组织一样,actor自然形成树形结构。程序中负责某一功能的actor,可能需要把它的任务分拆成更小的、更易管理的部分。为此它启动子actor并监督它们。虽然[后面章节](04_supervision_and_monitoring.md)会解释监督机制的细节,我们会集中在这一节里介绍其中的根本思想,唯一需要了解的前提是每个actor有且仅有一个监管者,就是创建它的那个actor。 12 | 13 | Actor系统的精髓在于任务被拆开、委托,直到任务小到可以被完整地处理。这样做不仅清晰地划分出了任务本身的结构,而且最终的actor也能按照它们“应该处理什么类型的消息”,“如何处理正常流程”以及“如何应对失败流程”来进行推理。如果一个actor对某种状况无法进行处理,它会发送相应的失败消息给它的监管者请求帮助。这样的递归结构使得失败能够在正确的层次得到处理。 14 | 15 | 可以将这种思想与分层的设计方法进行比较。分层的设计方法最终很容易形成防护性编程,以防止任何失败被泄露出来;相比之下把问题交由正确的人处理会是比将所有的事情“藏在深处”更好的解决方案。 16 | 17 | 现在,设计这种系统的难度在于如何决定谁应该监管什么。这当然没有唯一的最佳方案,但是有一些指导原则可能会有帮助: 18 | 19 | * 如果一个actor管理另一个actor所做的工作,如分配一个子任务,那么父actor应该监督子actor。因为父actor知道可能会出现哪些失败情况,以及如何处理它们。 20 | * 如果一个actor携带着重要数据(即它的状态要尽可能地不被丢失),这个actor应该将任何可能出现危险的子任务分配给它所监管的子actor,并酌情处理子任务的失败。根据请求的性质,可能的话最好为每一个请求创建一个子actor,这样能简化收集回应的状态管理。这在Erlang中被称为“Error Kernel Pattern”。 21 | * 如果actor A需要依赖actor B才能完成它的任务,A应该观测B的存活状态并对B的终止提醒消息进行响应。这与监管机制不同,因为观测方对监管机制没有影响;需要指出的是,仅仅是功能上的依赖并不足以用来决定是否在树形监管体系中添加子actor. 22 | 23 | 当然以上的规则都会有例外,但无论是遵循这些规则还是打破它们,都需要有足够的理由。 24 | 25 | ### 配置容器 26 | 27 | actor系统是多个协作actor的组,它天生就是管理调度服务、配置、日志等共享设施的单元。使用不同配置的多个actor系统可以在同一个jvm中共存,Akka自身没有全局共享的状态。将这与actor系统之间的透明通讯(在同一节点上或者跨网络连接的多个节点)结合,可以看到actor系统本身可以被作为功能层次中的构建单元。 28 | 29 | ### Actor最佳实践 30 | 31 | * Actor应该被视为友好的同事:高效完成其工作,不会无必要地打扰其它人,也不会争抢资源。对应在编程中,其意思是以事件驱动的方式来处理事件并生成响应(或更多的请求)。Actor不应该因为某一个外部实体而阻塞(即占据一个线程又被动等待),这个外部实体可能是一个锁、一个网络socket等等;除非它是不可避免的,如下一节所述。 32 | * 不要在actor之间传递可变对象。为了保证这一点,选择不可变消息。如果actor将他们的可变状态暴露给外界,打破了封装,你就回到了普通的Java并发领域并遭遇其所有缺点。 33 | * Actor是行为和状态的容器,拥抱这一点意味着不要在消息中传递行为(例如在消息中使用scala闭包)。有一个风险是意外地在actor之间共享了可变状态,这种对actor模型规则的违反将破坏使用actor编程带来的所有良好体验。 34 | * 顶级actor在错误内核最深处,所以尽量少创建它们并且选择真正的树形分层系统。这对故障处理有好处(同时考虑到配置的粒度和性能),同时也减少了对监管actor这个竞争单点的过度使用。 35 | 36 | ### 阻塞需要仔细的管理 37 | 38 | 在某些情况下,阻塞操作是不可避免的,即必须不定期地休眠一个线程,等待外部事件唤醒。例如传统的关系型数据库的驱动程序或消息传递API,而深层的原因通常是出现幕后的(网络)I/O。面对这一点,你可能受到诱惑,只是将阻塞调用包装在 `Future` 中来替之工作,但这个策略太简单了:当应用的负载增加,你很可能会发现性能瓶颈,或者出现内存或线程耗尽的情况。 39 | 40 | 对“阻塞问题”的充分解决方案的清单是不会穷尽的,但肯定会有下面的建议: 41 | 42 | * 在一个actor(或由一个路由器[[Java](#TODO), [Scala](../chapter3/06_routing.md)]管理的一组actor内)内进行阻塞调用,并确保配置一个线程池,它要足够大或者专门用于这一目的。 43 | * 在一个 `Future` 内进行阻塞调用,确保任意时间点内这种调用的数量都在一个上限内(无限制提交这类任务会耗尽你的内存或线程)。 44 | * 在一个 `Future` 内进行阻塞调用,使用一个线程池,该线程池的线程数上限对应用程序运行的硬件是合适的。 45 | * 奉献一个单独的线程来管理一组阻塞资源(如一个NIO选择器驱动多个频道),并在事件发生时把它们作为actor消息发送。 46 | 47 | 第一个建议对本质上是单线程的资源特别适合,如传统数据库句柄一次只能执行一个未完成的查询,并使用内部同步保证这一点。一个常见的模式是对N个actor创建一个router,每个actor包装一个数据库连接,并处理发送给这个router的查询。数目`N`必须被调整为最大吞吐量,这个数字取决于什么数据库管理系统部署在什么硬件上。 48 | 49 | > 注意 50 | 51 | > 配置线程池的任务最好代理给Akka来做,只要在`application.conf`中配置,并由`ActorSystem` [[Java](#TODO), [Scala](../chapter3/04_dispatchers.md#dispatcher-lookup-scala)] 实例化即可。 52 | 53 | 54 | ### 你不应该担心的事 55 | 56 | 一个actor系统管理它所配置使用的资源,运行它所包含的actor。 在一个系统中可能有上百万个actor,不用担心,内存一定是够用的,因为每个actor实例仅占差不多300个字节。自然地,一个大系统中消息处理的具体顺序是不受应用开发者控制的,但这并不是有意为之。放松些,让Akka去做幕后的繁重事务吧。 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter2/03_what_is_an_actor.md: -------------------------------------------------------------------------------- 1 | # 什么是Actor? 2 | 3 | 上一节 [Actor系统](02_actor_systems.md) 解释了actor是应用创建中最小的单元,以及它们如何组成一个树形结构。本节单独来看看一个actor,解释在实现它时你会遇到的概念。更多细节请参阅 [Actors (Scala)](../chapter3/01_actors.md)和 [Actors (Java)](#TODO). 4 | 5 | 一个Actor是一个容器,它包含了[状态](#state),[行为](#behavior),一个[邮箱](#mailbox),[子Actor](#children)和一个[监管策略](#supervisor-strategy)。所有这些封装在一个[Actor引用](#actor-reference)里。最终在Actor终止时,会有[这些](#when-an-actor-terminates)发生。 6 | 7 | ### Actor引用 8 | 9 | 如下所详细描述的,一个actor对象需要与外界隔离开才能从actor模型中获益。因此actor是以actor引用的形式展现给外界的,actor引用作为对象,可以被无限制地自由传递。内部和外部对象的这种划分使得所有想要的操作都能够透明:重启actor而不需要更新别处的引用,将实际actor对象放置到远程主机上,向另外一个应用程序发送消息。但最重要的方面是从外界不可能到actor对象的内部获取其状态,除非这个actor非常不明智地将信息公布出去。 10 | 11 | ### 状态 12 | Actor对象通常包含一些变量来反映其所处的可能状态。这可以是一个明确的状态机(例如使用 [FSM 模块](../chapter3/07_FSM.md)),或是一个计数器,一组监听器,待处理的请求,等等。这些数据使得actor有价值,并且必须将这些数据保护起来不被其它actor所破坏。好消息是在概念上每个Akka actor都有自己的轻量线程,它与系统其它部分是完全隔离的。这意味着你不需要使用锁来进行资源同步,可以直接编写你的actor代码,完全不必担心并发问题。 13 | 14 | 在幕后,Akka会在一组真实线程上运行Actor组,通常是很多actor共享一个线程,对某一个actor的调用可能会在不同的线程上得到处理。Akka保证这个实现细节不影响处理actor状态的单线程性。 15 | 16 | 由于内部状态对于actor的操作是至关重要的,所以状态不一致是致命的。因此当actor失败并被其监管者重新启动时,状态会被重新创建,就象第一次创建这个actor一样。这是为了实现系统的“自愈合”。 17 | 18 | 可选地,通过持久化收到的消息并在重启后重放它们,一个actor的状态可自动恢复到重启前的状态(详见[持久化](../chapter3/08_persistence.md)) 19 | 20 | ### 行为 21 | 每当一个消息被处理,它会与actor的当前行为进行匹配。行为是一个函数,它定义了在某个时间点处理当前消息所要采取的动作,例如如果客户已经授权,那么就对请求进行转发处理,否则拒绝。这个行为可能随着时间而改变,例如由于不同的客户在不同的时间获得授权,或是由于actor进入了“非服务”模式,之后又变回来。这些变化的实现,要么是通过将它们编码入状态变量中并由行为逻辑读取,要么是函数本身在运行时被交换出来,见`become` 和 `unbecome`操作。但是actor对象在创建时所定义的初始行为是特殊的,因为actor重启时会恢复这个初始行为。 22 | 23 | 24 | ### 邮箱 25 | Actor的目的是处理消息,这些消息是从其它actor(或者从actor系统外部)发送过来的。连接发送者与接收者的纽带是actor的邮箱:每个actor有且仅有一个邮箱,所有的发来的消息都在邮箱里排队。排队按照发送操作的时间顺序来进行,这意味着由于actor分布在不同的线程中,所以从不同的actor发来的消息在运行时没有一个固定的顺序。从另一个角度讲,从同一个actor发送到相同目标actor的多个消息,会按发送的顺序排队。 26 | 27 | 可以有不同的邮箱实现供选择,缺省的是FIFO:actor处理消息的顺序与消息入队列的顺序一致。这通常是一个好的选择,但是应用可能需要对某些消息进行优先处理。在这种情况下,可以使用优先邮箱来根据消息优先级将消息放在非队尾的某个指定位置,甚至可能是队列头。如果使用这样的队列,消息的处理顺序是由队列的算法决定的,而不是FIFO。 28 | 29 | Akka与其它actor模型实现的一个重要区别在于:当前的行为总是必须处理下一个从队列中取出的消息,Akka不会扫描邮箱队列来获取下一个匹配的消息。无法处理某个消息通常被认为是失败情况,除非这个行为被重写。 30 | 31 | ### 子Actor 32 | 每个actor都是一个潜在的监管者:如果它创建了子actor来委托处理子任务,它会自动地监管它们。子actor列表维护在actor的上下文中,actor可以访问它。对列表的更改是通过创建(`context.actorOf(...)`)或者停止(`context.stop(child)`)子actor来完成,并且这些更改会立刻生效。实际的创建和停止操作是在幕后以异步方式完成的,这样它们就不会“阻塞”其监管者。 33 | 34 | ### 监管策略 35 | Actor的最后一部分是它用来处理其子actor错误状况的机制。错误处理是由Akka透明完成的,针对每个出现的失败,将应用[监管与监控](04_supervision_and_monitoring.md)中所描述的一个策略。由于策略是actor系统组织结构的基础,所以一旦actor被创建,它就不能被修改。 36 | 37 | 考虑到对每个actor只有唯一的策略,这意味着:如果一个actor的子actor们应用了不同的策略,则这些子actor应该按照相同的策略来进行分组,并放在一个中间的监管者下,又一次转向了根据任务到子任务的划分来组织actor系统的结构的设计方法。 38 | 39 | ### 当Actor终止时 40 | 当一个actor终止——即失败了且不能用重启来解决、停止它自己或者被它的监管者停止——它会释放其资源,将其邮箱中所有未处理的消息放进系统的“死信邮箱(dead letter mailbox)”,即将所有消息作为死信重定向到事件流中。而actor引用中的邮箱将会被一个系统邮箱所替代,将所有的新消息作为死信重定向到事件流中。 但是这些操作只是尽力而为,所以不能依赖它来实现“投递保证”。 41 | 42 | 不是简单地把消息扔掉的想法来源于我们的测试:我们在事件总线上注册了`TestEventListener`来接收死信,然后将每个收到的死信在日志中生成一条警告——这对于更快地解析测试失败非常有帮助。可以想象这个特性也可以用于其它的目的。 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter2/04_supervision_and_monitoring.md: -------------------------------------------------------------------------------- 1 | # 监管与监控 2 | 3 | 这一节将简述监管背后的概念、原语及语义。要了解这些如何转换成真实代码,请参阅相关的Scala和Java API章节。 4 | 5 | ### 监管的意思 6 | 在 [Actor 系统](02_actor_systems.md) 中说过,监管描述的是actor之间的依赖关系:监管者将任务委托给下属,并相应地对下属的失败状况进行响应。当一个下属出现了失败(即抛出一个异常),它自己会将自己和自己所有的下属挂起,然后向自己的监管者发送一个提示失败的消息。基于所监管的工作的性质和失败的性质,监管者可以有4种基本选择: 7 | 8 | 1. 恢复下属,保持下属当前积累的内部状态 9 | 1. 重启下属,清除下属的内部状态 10 | 1. 永久地停止下属 11 | 1. 升级失败(沿监管树向上传递失败),由此失败自己 12 | 13 | 始终要把一个actor视为整个监管树形体系的一部分是很重要的,这解释了第4种选择存在的意义(因为一个监管者同时也是其上方监管者的下属),并且隐含在前3种选择中:恢复actor会恢复其所有下属,重启一个actor也必须重启其所有下属(不过需要看下面的详述获取更多细节),类似地终止一个actor会终止其所有下属。需要强调`Actor`类的`preRestart`钩子(hook)缺省行为是在重启前终止它的所有下属,但这个钩子可以被重写;对所有子actor的递归重启操作在这个钩子之后执行。 14 | 15 | 每个监管者都配置了一个函数,它将所有可能的失败原因(即异常)翻译成以上四种选择之一;注意,这个函数并不将失败actor的标识作为输入。我们很快会发现在有些结构中这种方式可能看起来不够灵活,例如会希望对不同的下属应用不同的策略。在这一点上我们一定要理解监管是为了组建一个递归的失败处理结构。如果你试图在某一个层次做太多事情,这个层次会变得复杂并难以理解,因此这时我们推荐的方法是增加一个监管层次。 16 | 17 | Akka实现的是一种叫“父监管”的形式。Actor只能被其它的actor创建——顶部的actor由库来提供——每一个被创建的actor都由其父亲所监管。这种限制使得actor的监管结构隐式符合其树形层次,并提倡合理的设计方法。需要强调的是这也保证了actor不会成为孤儿或者拥有在系统外界的监管者(被外界意外捕获)。另外,这形成了对actor应用(或其子树)一种自然又干净的关闭过程。 18 | 19 | > 警告 20 | 21 | > 监管相关的父-子沟通,使用了特殊的系统消息及其固有的邮箱,从而和用户消息隔离开来。这意味着,监管相关的事件相对于普通的消息没有确定的顺序关系。在一般情况下,用户不能影响正常消息和失败通知的顺序。相关详细信息和示例,请参见讨论:[消息排序](08_message_delivery_reliability.md#message-ordering)。 22 | 23 | ### 顶级监管者 24 | 25 | ![](guardians.png) 26 | 27 | 一个actor系统在其创建过程中至少要启动三个actor,如上图所示。有关actor路径及相关信息请参见[Actor路径的顶级作用域](05_actor_references_paths_and_addresses.md#toplevel-paths)。 28 | 29 | ##### `/user`: 守护Actor 30 | 31 | 这个名为`"/user"`的守护者,作为所有用户创建actor的父actor,可能是需要打交道最多的。使用`system.actorOf()`创建的actor都是其子actor。这意味着,当该守护者终止时,系统中所有的普通actor都将被关闭。同时也意味着,该守护者的监管策略决定了普通顶级actor是如何被监督的。自Akka 2.1起就可以使用这个设定`akka.actor.guardian-supervisor-strategy`,以一个`SupervisorStrategyConfigurator`的完整类名进行配置。当这个守护者上升一个失败,根守护者的响应是终止该守护者,从而关闭整个actor系统。 32 | 33 | ##### `/system`: 系统守护者 34 | 35 | 这个特殊的守护者被引入,是为了实现正确的关闭顺序,即日志(logging)要保持可用直到所有普通actor终止,即使日志本身也是用actor实现的。其实现方法是:系统守护者观察user守护者,并在收到`Terminated`消息初始化其自己的关闭过程。顶级的系统actor被监管的策略是,对收到的除`ActorInitializationException`和`ActorKilledException`之外的所有`Exception`无限地执行重启,这也将终止其所有子actor。所有其他`Throwable`被上升,然后将导致整个actor系统的关闭。 36 | 37 | ##### `/`: 根守护者 38 | 39 | 根守护者所谓“顶级”actor的祖父,它监督所有在[Actor路径的顶级作用域](05_actor_references_paths_and_addresses.md#toplevel-paths)中定义的特殊actor,使用发现任何`Exception`就终止子actor的`SupervisorStrategy.stoppingStrategy`策略。其他所有Throwable都会被上升……但是上升给谁?所有的真实actor都有一个监管者,但是根守护者没有父actor,因为它就是整个树结构的根。因此这里使用一个虚拟的`ActorRef`,在发现问题后立即停掉其子actor,并在根守护者完全终止之后(所有子actor递归停止),立即把actor系统的`isTerminated`置为`true`。 40 | 41 | ### 重启的含义 42 | 当actor在处理某条消息时失败时,失败的原因可以分成以下三类: 43 | 44 | * 对收到的特定消息的系统错误(即程序错误) 45 | * 处理消息时一些外部资源的(临时性)失败 46 | * actor内部状态崩溃了 47 | 48 | 除非故障能被专门识别,否则所述的第三个原因不能被排除,从而引出内部状态需要被清除的结论。如果监管者确定它的其他子actor或本身不会受到崩溃的影响——例如使用了错误内核模式的能够自我恢复的应用——那么最好只重启这个孩子。具体实现是通过建立底层`Actor`类的新实例,并用新的`ActorRef`更换故障实例;能做到这一点是因为将actor都封装载了特殊的引用中。然后新actor恢复处理其邮箱,这意味着该启动在actor外部是不可见的,显著的异常是在发生失败期间的消息不会被重新处理。 49 | 50 | 重启过程中所发生事件的精确次序是: 51 | 52 | 1. actor被挂起(意味着它不会处理正常消息直到被恢复),并递归挂起其所有子actor 53 | 1. 调用旧实例的 `preRestart` hook (缺省实现是向所有子actor发送终止请求并调用 `postStop`) 54 | 1. 等待所有子actor终止(使用`context.stop()`)直到 `preRestart` 最终结束;这里所有的actor操作都是非阻塞的,最后被杀掉的子actor的终止通知会影响下一步的执行 55 | 1. 再次调用原来提供的工厂生成actor的新实例 56 | 1. 调用新实例的`postRestart`方法(其默认实现是调用`preStart`方法) 57 | 1. 对步骤3中没有被杀死的所有子actor发送重启请求;重启的actor会遵循相同的过程,从步骤2开始 58 | 1. 恢复这个actor 59 | 60 | ### 生命周期监控的含义 61 | 62 | > 注意 63 | 64 | > 生命周期监控在Akka中经常被引作`DeathWatch` 65 | 66 | 与上面所描述的特殊父子关系相对的,每一个actor都可以监控其他任意actor。由于actor从创建到完全可用和重启都是除了监管者之外都不可见的,所以唯一可用于监视的状态变化是可用到失效的转变。监视因此被用于绑定两个actor,使监控者能对另一个actor的终止做出响应,而相应的,监督者是对失败做出响应。 67 | 68 | 生命周期监控是通过监管actor收到`Terminated`消息实现的,其默认行为是抛出一个`DeathPactException`。要开始监听`Terminated`消息,需要调用`ActorContext.watch(targetActorRef)`。要停止监听,需要调用`ActorContext.unwatch(targetActorRef)`。一个重要的特性是,消息将不考虑监控请求和目标终止发生的顺序,也就是说,即使在登记的时候目标已经死了,你仍然会得到消息。 69 | 70 | 如果一个监管者不能简单地重启其子actor,而必须终止它们,这时监控就特别有用,例如在actor初始化时发生错误。在这种情况下,它应该监控这些子actor并重新创建它们,或安排自己在稍后的时间重试。 71 | 72 | 另一个常见的应用情况是,一个actor需要在没有外部资源时失败,该资源也可能是它的子actor之一。如果第三方通过`system.stop(child)`或发送`PoisonPill`的方式终止子actor,其监管者很可能会受到影响。 73 | 74 | ### 一对一策略 vs. 多对一策略 75 | 76 | Akka中有两种类型的监管策略:`OneForOneStrategy` 和`AllForOneStrategy`。两者都配置有从异常类型监管指令间的映射(见[上文](04_supervision_and_monitoring.md#supervision-directives)),并限制了一个孩子被终止之前允许失败的次数。它们之间的区别在于,前者只将所获得的指令应用在发生故障的子actor上,而后者则是应用在所有孩子上。通常情况下,你应该使用`OneForOneStrategy`,这也是默认的策略。 77 | 78 | `AllForOneStrategy`适用的情况是,子actor之间有很紧密的依赖,以至于一个actor的失败会影响其他孩子,即他们是不可分开的。由于重启不清除邮箱,所以往往最好是失败时终止孩子并在监管者显式地重建它们(通过观察孩子们的生命周期);否则你必须确保重启前入队的消息在重启后处理是没有问题的。 79 | 80 | 通常停止一个孩子(即对失败不再响应)不会自动终止多对一策略中其他的孩子;可以很容易地通过观察它们的生命周期来做到这点:如果`Terminated`的消息不能被监管者处理,它会抛出一个`DeathPactException`,并(这取决于其监管者)将重新启动,默认`preRestart`操作会终止所有的孩子。当然这也可以被显式地处理。 81 | 82 | 请注意,在多对一监管者下创建一个临时的actor会导致一个问题:临时actor的失败上升会使所有永久actor受到影响。如果这不是所期望的,安装一个中间监管者;这可以很容易地通过为工作者声明大小为1的路由器来完成,请参阅路由[routing-scala](../chapter3/06_routing.md)或[routing-java](#TODO)。 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter2/06_location_transparency.md: -------------------------------------------------------------------------------- 1 | # 位置透明性 2 | 3 | 上一节讲到了如何使用actor路径来实现位置透明性。这个特殊的功能需要额外的解释,因为“透明远程调用”在不同的上下文中(编程语言,平台,技术)有非常不同的用法。 4 | 5 | ### 天生的分布式 6 | Akka中所有的东西都是被设计为在分布式环境下工作的:actor之间所有的互操作都是使用纯粹的消息传递机制,所有的操作都是异步的。付出这些努力是为了保证其所有功能,无论是在单一的JVM上还是在拥有很多机器的集群里都能同样有效。实现这一点的关键是从远程到本地进行优化,而不是从本地到远程进行一般化。参阅这篇[`经典论文`](http://doc.akka.io/docs/misc/smli_tr-94-29.pdf)来了解关于为什么第二种方式注定要失败的详细讨论。 7 | 8 | ### 破坏透明性的方式 9 | 由于设计分布式执行过程对可以做的事情添加了一些限制,Akka所满足的约束并不一定在使用akka的应用程序中也满足。最明显的一条是网络上发送的所有消息都必须是可序列化的。而不那么明显的是,这也包括在远程节点上创建actor时,用作actor工厂的闭包(即在`Props`里)。 10 | 11 | 另一个结果是所有元素都需要知道所有交互是完全异步的,在一个计算机网络中这意味着一个消息可能需要好几分钟才能到达接收方(跟配置有关)。还意味着消息丢失的概率比在单一的jvm中(接近0,但仍不能完全保证!)高得多。 12 | 13 | ### 远程调用如何使用? 14 | 我们把透明性的想法限制在“Akka中几乎没有为远程调用层设计的API”:而完全由配置来驱动。你只需要按照之前的章节概括的那些原则来编写你的应用,然后在配置文件里指定远程部署的actor子树。这样你的应用可以不用通过修改代码来实现扩展。API中唯一允许编程来影响远程部署的部分是`Props`包含的一个属性,这个属性可能被设为一个特定的 `Deploy` 实例;这与在配置文件中进行部署设置具有相同的效果(如果两者都有,那么配置文件优先)。 15 | 16 | ### Peer-to-Peer vs. Client-Server 17 | Akka Remoting是以对等网络方式进行actor系统连接的通信模块,它是Akka集群的基础。远程处理的设计取决于两个(相关)的设计决策: 18 | 19 | * 涉及系统之间的通信是对称的:如果系统A可连接到系统B,那么B系统必须也能够独立连接到系统A。 20 | * 通信系统中的角色按照连接的模式是对称的:不存在系统只接受连接,也没有系统只发起连接。 21 | 22 | 这些决定的结果是,它不可能按照预定义的角色安全地创建纯粹的“客户端-服务器”设置(违反假设2 ),并使用网络地址转换(NAT)或负载平衡器(违反假设1)。 23 | 24 | 对于“客户端-服务器”的设置,最好是使用HTTP或Akka I/O 。 25 | 26 | ### 使用路由来进行垂直扩展的标记点 27 | 一个actor系统除了可以在集群中的不同节点上运行不同的部分,还可以通过并行增加actor子树的方法来垂直扩展到多个cpu核上(设想例如搜索引擎并行处理不同的检索词)。新增出来的子树可以使用不同的方法来进行路由,例如循环(round-robin)。要达到这种效果,开发者只需要声明一个“withRouter”的actor,这样系统会创建一个路由actor取而代之,该路由actor会按照期望类型和配置的数目生成子actor,并使用所配置的方式来对这些子actor进行路由。一旦声明了这样的路由,它的配置可以自由地被配置文件里的配置进行重写,包括把它与其(某些)子actor的远程部署进行混合。具体可参阅 [路由器(Scala)](../chapter3/06_routing.md) 和 [路由器(Java)](#TODO)。 28 | 29 | 30 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter2/07_akka_and_the_java_memory_model.md: -------------------------------------------------------------------------------- 1 | # Akka与Java内存模型 2 | 3 | 使用包含Scala和Akka在内的Typesafe平台的主要好处是它简化了并发软件的编写过程。本文将讨论Typesafe平台,尤其是Akka是如何在并发应用中访问共享内存的。 4 | 5 | ### Java内存模型 6 | 在Java 5之前,Java内存模型(JMM)定义是有问题的。当多个线程访问共享内存时很可能得到各种奇怪的结果,例如: 7 | 8 | * 一个线程看不到其它线程所写入的值:可见性问题 9 | * 由于指令没有按期望的顺序执行,一个线程观察到其它线程的 ‘不可能’ 行为:指令重排序问题 10 | 11 | 随着Java 5中JSR 133的实现,很多这种问题都被解决了。 JMM是一组基于 “发生在先” 关系的规则, 限制了一个内存访问行为何时必须在另一个内存访问行为之前发生,以及反过来,它们何时能够不按顺序发生。这些规则的两个例子包括: 12 | 13 | * **监视器锁规则:** 对一个锁的释放先于所有后续对同一个锁的获取 14 | * **volatile变量规则:** 对一个volatile变量的写操作先于所有对同一volatile变量的后续读操作 15 | 16 | 虽然JMM看起来很复杂,但是其规范试图在易用性和编写高性能、可扩展的并发数据结构的能力之间寻找一个平衡。 17 | 18 | ### Actors与Java内存模型 19 | 使用Akka中的Actor实现,有两种方法让多个线程对共享的内存进行操作: 20 | 21 | * 如果一条消息被(例如,从另一个actor)发送到一个actor,大多数情况下消息是不可变的,但是如果这条消息不是一个正确创建的不可变对象,如果没有 “发生先于” 规则, 有可能接收方会看到部分初始化的数据,甚至可能看到无中生有的数据(long/double)。 22 | * 如果一个actor在处理某条消息时改变了自己的内部状态,而之后又在处理其它消息时又访问了这个状态。一条很重要的需要了解的规则是,在使用actor模型时你无法保证,同一个线程会在处理不同的消息时使用同一个actor。 23 | 24 | 为了避免actor中的可见性和重排序问题,Akka保证以下两条 “发生在先” 规则: 25 | 26 | * **actor发送规则 : **一条消息的发送动作先于目标actor对同一条消息的接收。 27 | * **actor后续处理规则: **对同一个actor,一条消息的处理先于下一条消息处理 28 | 29 | > 注意 30 | 31 | > 通俗地说,这意味着当这个actor处理下一个消息的时候,对actor的内部字段的改变是可见的。因此,在你的actor中的域不需要是volitale或是同等可见性的。 32 | 33 | 这两条规则都只应用于同一个actor实例,对不同的actor则无效。 34 | 35 | ### Future与Java内存模型 36 | 一个Future的完成 “先于” 任何注册到它的回调函数的执行。 37 | 38 | 我们建议不要在回调中捕捉(close over)非final的值 (Java中称final,Scala中称val), 如果你**一定**要捕捉非final的域,则它们必须被标记为*volatile*来让它的当前值对回调代码可见。 39 | 40 | 如果你捕捉一个引用,你还必须保证它所指代的实例是线程安全的。我们强烈建议远离使用锁的对象,因为它们会引入性能问题,甚至最坏可能造成死锁。这些是使用synchronized的风险。 41 | 42 | ### STM与Java内存模型 43 | Akka中的软件事务性内存 (STM) 也提供了一条 “发生在先” 规则: 44 | 45 | * **事务性引用规则:** 对一个事务性引用,在提交过程中一次成功的写操作,先于所有对同一事务性引用的后续读操作发生。 46 | 47 | 这条规则非常象JMM中的“volatile 变量”规则。目前Akka STM只支持延迟写,所以对共享内存的实际写操作会被延迟到事务提交之时。在事务中发生的写操作会被存放在一个本地缓冲区内 (事务的写操作集) ,并且对其它事务是不可见的。这就是为什么脏读是不可能的。 48 | 49 | 这些规则在Akka中的实现会随时间而变化,精确的细节甚至可能依赖于所使用的配置。但是它们是建立在其它JMM规则之上的,如监视器锁规则、volatile变量规则。 这意味着Akka用户不需要操心为了提供“发生先于”关系而增加同步,因为这是Akka的工作。这样你可以腾出手来处理业务逻辑,让Akka框架来保证这些规则的满足。 50 | 51 | ### Actor与共享的可变状态 52 | 因为Akka运行在JVM上,所以还有一些其它的规则需要遵守。 53 | 54 | * 捕捉Actor内部状态并暴露给其它线程 55 | 56 | ```scala 57 | 58 | class MyActor extends Actor { 59 | var state = ... 60 | def receive = { 61 | case _ => 62 | // 错误的做法 63 | 64 | // 非常错误,共享可变状态, 65 | // 会让应用莫名其妙地崩溃 66 | Future { state = NewState } 67 | anotherActor ? message onSuccess { r => state = r } 68 | 69 | // 非常错误, 共享可变状态 bug 70 | // "发送者"是一个可变变量,随每个消息改变 71 | Future { expensiveCalculation(sender) } 72 | 73 | //正确的做法 74 | 75 | // 非常安全, "self" 被闭包捕捉是安全的 76 | // 并且它是一个Actor引用, 是线程安全的 77 | Future { expensiveCalculation() } onComplete { f => self ! f.value.get } 78 | 79 | // 非常安全,我们捕捉了一个固定值 80 | // 并且它是一个Actor引用,是线程安全的 81 | val currentSender = sender 82 | Future { expensiveCalculation(currentSender) } 83 | } 84 | } 85 | ``` 86 | 87 | * 消息**应当**是不可变的, 这是为了避开共享可变状态的陷阱。 88 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter2/ActorPath.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/chapter2/ActorPath.png -------------------------------------------------------------------------------- /2.3.6/scala/chapter2/RemoteDeployment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/chapter2/RemoteDeployment.png -------------------------------------------------------------------------------- /2.3.6/scala/chapter2/general.md: -------------------------------------------------------------------------------- 1 | # 概述 2 | 3 | * [术语,概念](01_terminology_concepts.md) 4 | * 并发 vs. 并行 5 | * 异步 vs. 同步 6 | * 非阻塞 vs. 阻塞 7 | * 死锁 vs. 饥饿 vs. 活锁 8 | * 竞态条件 9 | * 非阻塞担保(进展条件) 10 | * 推荐文献 11 | * [Actor系统](02_actor_systems.md) 12 | * 树形结构 13 | * 配置容器 14 | * Actor最佳实践 15 | * 阻塞需要仔细的管理 16 | * 你不应该担心的事 17 | * [什么是Actor?](03_what_is_an_actor.md) 18 | * Actor引用 19 | * 状态 20 | * 行为 21 | * 邮箱 22 | * 子Actor 23 | * 监管策略 24 | * 当Actor终止时 25 | * [监管与监控](04_supervision_and_monitoring.md) 26 | * 监管的意思 27 | * 顶级监管者 28 | * 重启的含义 29 | * 生命周期监控的含义 30 | * 一对一策略 vs. 多对一策略 31 | * [Actor引用, 路径与地址](05_actor_references_paths_and_addresses.md) 32 | * 什么是Actor引用? 33 | * 什么是Actor路径? 34 | * 如何获得Actor引用? 35 | * Actor引用和路径相等性 36 | * 重用Actor路径 37 | * 与远程部署之间的互操作 38 | * 路径中的地址部分用来做什么? 39 | * Actor路径的顶级作用域 40 | * [位置透明性](06_location_transparency.md) 41 | * 天生的分布式 42 | * 破坏透明性的方式 43 | * 远程调用如何使用? 44 | * Peer-to-Peer vs. Client-Server 45 | * 使用路由来进行垂直扩展的标记点 46 | * [Akka与Java内存模型](07_akka_and_the_java_memory_model.md) 47 | * Java内存模型 48 | * Actors与Java内存模型 49 | * Future与Java内存模型 50 | * STM与Java内存模型 51 | * Actor与共享的可变状态 52 | * [消息发送语义](08_message_delivery_reliability.md) 53 | * 一般规则 54 | * JVM内(本地)消息发送规则 55 | * 更高层次的抽象 56 | * 死信 57 | * [配置](09_configuration.md) 58 | * 配置读取的地方 59 | * 当使用JarJar,,OneJar,Assembly或任何jar打包命令(jar-bundler) 60 | * 自定义application.conf 61 | * 包含文件 62 | * 配置日志 63 | * 谈一谈类加载器 64 | * 应用特定设置 65 | * 配置多个ActorSystem 66 | * 从自定义位置读取配置 67 | * Actor部署配置 68 | * 参考配置清单 69 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter2/guardians.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/chapter2/guardians.png -------------------------------------------------------------------------------- /2.3.6/scala/chapter3/04_dispatchers.md: -------------------------------------------------------------------------------- 1 | # 调度器 2 | 3 | Akka ``MessageDispatcher``是维持 Akka Actor “运作”的部分, 可以说它是整个机器的引擎。所有的``MessageDispatcher``实现也同时也是一个``ExecutionContext``,这意味着它们可以用来执行任何代码,例如[Future(Scala)](../chapter4/01_futures.md)。 4 | 5 | ### 缺省派发器 6 | 在没有为Actor作配置的情况下,每一个``ActorSystem``将有一个缺省的派发器。该缺省派发器可以被配置,默认是使用指定的``default-executor``的一个``Dispatcher``。如果一个ActorSystem是使用传入的ExecutionContext创建的,则该ExecutionContext将被用作所有派发器的默认执行器(“executor”)。如果没有给定ExecutionContext,则会回退使用``akka.actor.default-dispatcher.default-executor.fallback``指定的执行器。缺省情况下是使用“fork-join-executor”,它在大多数情况下拥有非常好的性能。 7 | 8 | ### 查找一个派发器 9 | 派发器实现了`ExecutionContext`接口,因此可以用来运行`Future`调用等。 10 | 11 | ```scala 12 | // for use with Futures, Scheduler, etc. 13 | implicit val executionContext = system.dispatchers.lookup("my-dispatcher") 14 | ``` 15 | 16 | ### 为Actor指定派发器 17 | 如果你希望为你的``Actor``设置非缺省的派发器,你需要做两件事,首先是配置派发器: 18 | 19 | ``` 20 | my-dispatcher { 21 | # Dispatcher 是基于事件的派发器的名称 22 | type = Dispatcher 23 | # 使用何种ExecutionService 24 | executor = "fork-join-executor" 25 | # 配置 fork join 池 26 | fork-join-executor { 27 | # 容纳基于因子的并行数量的线程数下限 28 | parallelism-min = 2 29 | # 并行数(线程)... ceil(可用CPU数*因子) 30 | parallelism-factor = 2.0 31 | # 容纳基于因子的并行数量的线程数上限 32 | parallelism-max = 10 33 | } 34 | # Throughput 定义了线程切换到下一个actor之前处理的消息数上限 35 | # 设置成1表示尽可能公平。 36 | throughput = 100 37 | } 38 | ``` 39 | 40 | 以下是另一个使用“thread-pool-executor”的例子: 41 | 42 | ``` 43 | my-thread-pool-dispatcher { 44 | # Dispatcher是基于事件的派发器的名称 45 | type = Dispatcher 46 | # 使用何种 ExecutionService 47 | executor = "thread-pool-executor" 48 | # 配置线程池 49 | thread-pool-executor { 50 | # 容纳基于因子的内核数的线程数下限 51 | core-pool-size-min = 2 52 | # 内核线程数 .. ceil(可用CPU数*倍数) 53 | core-pool-size-factor = 2.0 54 | # 容纳基于倍数的并行数量的线程数上限 55 | core-pool-size-max = 10 56 | } 57 | # Throughput 定义了线程切换到下一个actor之前处理的消息数上限 58 | # 设置成1表示尽可能公平. 59 | throughput = 100 60 | } 61 | ``` 62 | 63 | 更多选项,请参阅[配置](../chapter2/09_configuration.md)的缺省派发器(default-dispatcher)一节。 64 | 65 | 然后可以像往常一样创建actor并在部署配置中定义调度器。 66 | 67 | ```scala 68 | import akka.actor.Props 69 | val myActor = context.actorOf(Props[MyActor], "myactor") 70 | ``` 71 | 72 | ``` 73 | akka.actor.deployment { 74 | /myactor { 75 | dispatcher = my-dispatcher 76 | } 77 | } 78 | ``` 79 | 80 | 部署配置的替代方法是在代码中定义调度器。如果你在部署配置中定义``dispatcher``,则实际使用的将是此值,而不是以编程方式提供的参数。 81 | 82 | ```scala 83 | import akka.actor.Props 84 | val myActor = 85 | context.actorOf(Props[MyActor].withDispatcher("my-dispatcher"), "myactor1") 86 | ``` 87 | 88 | > 注意 89 | 90 | > 你在``withDispatcher``中指定的调度器,和在部署文件指定的``dispatcher``设置其实是配置中的一个路径. 所以在这个例子中它位于配置的顶层,但你可以例如把它放在下面的层次,用“.”来代表子层次,象这样:``"foo.bar.my-dispatcher"`` 91 | 92 | ### 派发器的类型 93 | 94 | 一共有4种类型的消息派发器: 95 | 96 | * Dispatcher 97 | * 这是基于事件的调度器,将一组actor绑定到线程池。如果未指定派发器,则它将被用作默认调度器。 98 | * 可共享性:无限制 99 | * 邮箱:任意,为每一个Actor创建一个 100 | * 使用场景:缺省派发器,Bulkheading 101 | * 底层驱动:``java.util.concurrent.ExecutorService`` 102 | 通过"executor"指定,可使用"fork-join-executor"、"thread-pool-executor"或一个``akka.dispatcher.ExecutorServiceConfigurator``的限定 103 | 104 | * PinnedDispatcher 105 | * 这个调度器为每一个使用它的actor分配一个独立的线程;即每个actor会有其独有的只有一个线程的线程池。 106 | * 可共享性:无 107 | * 邮箱:任意,为每个Actor创建一个 108 | * 使用场景:Bulkheading 109 | * 底层驱动:**任意**``akka.dispatch.ThreadPoolExecutorConfigurator`` 110 | 缺省为一个“thread-pool-executor” 111 | 112 | * BalancingDispatcher 113 | * 这是基于事件的调度器,将尝试从繁忙的actor重新分配工作到空闲的actor。 114 | * 所有actor共享单个邮箱,并从中获取他们的消息。 115 | * 这里假定所有使用此调度器的actor都可以处理发送到其中一个actor的所有的消息;即actor属于actor池,并且对客户端来说没有保证来决定哪个actor实例实际上处理某个特定的消息。 116 | * 可共享性:仅对同一类型的Actor共享 117 | * 邮箱:任意,为所有的Actor创建一个 118 | * 使用场景:Work-sharing 119 | * 底层驱动:``java.util.concurrent.ExecutorService`` 120 | 通过"executor"指定,可使用 “fork-join-executor”, “thread-pool-executor” 或``akka.dispatcher.ExecutorServiceConfigurator``的限定 121 | * 请注意**不能**将``BalancingDispatcher``用作一个**路由器调度程序**。(但是你可以把它用作**Routees**) 122 | 123 | * CallingThreadDispatcher 124 | * 该调度器只在当前线程上调用。该调度器不会创建任何新的线程,但它可以被相同的actor从不同的线程同时使用。更多信息和限制,请参阅[CallingThreadDispatcher](09_testing_actor_systems.md#scala-callingthreaddispatcher)。 125 | * 可共享性:无限制 126 | * 邮箱:任意,每Actor每线程创建一个(需要时) 127 | * 使用场景:测试 128 | * 底层使用:调用的线程 (duh) 129 | 130 | ##### 更多 dispatcher 配置的例子 131 | 配置一个``PinnedDispatcher``: 132 | 133 | ``` 134 | my-pinned-dispatcher { 135 | executor = "thread-pool-executor" 136 | type = PinnedDispatcher 137 | } 138 | ``` 139 | 140 | 然后使用它: 141 | 142 | ```scala 143 | val myActor = 144 | context.actorOf(Props[MyActor].withDispatcher("my-pinned-dispatcher"), "myactor2") 145 | ``` 146 | 147 | 注意``thread-pool-executor``配置按上述``my-thread-pool-dispatcher``的调度程序例子并**不**适用。这是因为每个actor使用``PinnedDispatcher``时,会有其自己的线程池,并且该池将只有一个线程。 148 | 149 | 注意没有保证随时间推移,**相同**的线程会被使用,由于核心池超时被``PinnedDispatcher``用于在空闲actor的情况下降低资源使用率。总是使用相同的线程需要在``PinnedDispatcher``的配置中添加``thread-pool-executor.allow-core-timeout=off``。 150 | 151 | 152 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter3/09_1_testkit-example.md: -------------------------------------------------------------------------------- 1 | # TestKit实例(Scala) 2 | 3 | 这是Ray Roestenburg 在 [他的博客](http://roestenburg.agilesquad.com/2011/02/unit-testing-akka-actors-with-testkit_12.html) 中的示例代码,作了改动以兼容 Akka 2.x。 4 | 5 | ```scala 6 | import scala.util.Random 7 | 8 | import org.scalatest.BeforeAndAfterAll 9 | import org.scalatest.WordSpecLike 10 | import org.scalatest.Matchers 11 | 12 | import com.typesafe.config.ConfigFactory 13 | 14 | import akka.actor.Actor 15 | import akka.actor.ActorRef 16 | import akka.actor.ActorSystem 17 | import akka.actor.Props 18 | import akka.testkit.{ TestActors, DefaultTimeout, ImplicitSender, TestKit } 19 | import scala.concurrent.duration._ 20 | import scala.collection.immutable 21 | 22 | /** 23 | * a Test to show some TestKit examples 24 | */ 25 | class TestKitUsageSpec 26 | extends TestKit(ActorSystem("TestKitUsageSpec", 27 | ConfigFactory.parseString(TestKitUsageSpec.config))) 28 | with DefaultTimeout with ImplicitSender 29 | with WordSpecLike with Matchers with BeforeAndAfterAll { 30 | import TestKitUsageSpec._ 31 | 32 | val echoRef = system.actorOf(TestActors.echoActorProps) 33 | val forwardRef = system.actorOf(Props(classOf[ForwardingActor], testActor)) 34 | val filterRef = system.actorOf(Props(classOf[FilteringActor], testActor)) 35 | val randomHead = Random.nextInt(6) 36 | val randomTail = Random.nextInt(10) 37 | val headList = immutable.Seq().padTo(randomHead, "0") 38 | val tailList = immutable.Seq().padTo(randomTail, "1") 39 | val seqRef = 40 | system.actorOf(Props(classOf[SequencingActor], testActor, headList, tailList)) 41 | 42 | override def afterAll { 43 | shutdown() 44 | } 45 | 46 | "An EchoActor" should { 47 | "Respond with the same message it receives" in { 48 | within(500 millis) { 49 | echoRef ! "test" 50 | expectMsg("test") 51 | } 52 | } 53 | } 54 | "A ForwardingActor" should { 55 | "Forward a message it receives" in { 56 | within(500 millis) { 57 | forwardRef ! "test" 58 | expectMsg("test") 59 | } 60 | } 61 | } 62 | "A FilteringActor" should { 63 | "Filter all messages, except expected messagetypes it receives" in { 64 | var messages = Seq[String]() 65 | within(500 millis) { 66 | filterRef ! "test" 67 | expectMsg("test") 68 | filterRef ! 1 69 | expectNoMsg 70 | filterRef ! "some" 71 | filterRef ! "more" 72 | filterRef ! 1 73 | filterRef ! "text" 74 | filterRef ! 1 75 | 76 | receiveWhile(500 millis) { 77 | case msg: String => messages = msg +: messages 78 | } 79 | } 80 | messages.length should be(3) 81 | messages.reverse should be(Seq("some", "more", "text")) 82 | } 83 | } 84 | "A SequencingActor" should { 85 | "receive an interesting message at some point " in { 86 | within(500 millis) { 87 | ignoreMsg { 88 | case msg: String => msg != "something" 89 | } 90 | seqRef ! "something" 91 | expectMsg("something") 92 | ignoreMsg { 93 | case msg: String => msg == "1" 94 | } 95 | expectNoMsg 96 | ignoreNoMsg 97 | } 98 | } 99 | } 100 | } 101 | 102 | object TestKitUsageSpec { 103 | // Define your test specific configuration here 104 | val config = """ 105 | akka { 106 | loglevel = "WARNING" 107 | } 108 | """ 109 | 110 | /** 111 | * An Actor that forwards every message to a next Actor 112 | */ 113 | class ForwardingActor(next: ActorRef) extends Actor { 114 | def receive = { 115 | case msg => next ! msg 116 | } 117 | } 118 | 119 | /** 120 | * An Actor that only forwards certain messages to a next Actor 121 | */ 122 | class FilteringActor(next: ActorRef) extends Actor { 123 | def receive = { 124 | case msg: String => next ! msg 125 | case _ => None 126 | } 127 | } 128 | 129 | /** 130 | * An actor that sends a sequence of messages with a random head list, an 131 | * interesting value and a random tail list. The idea is that you would 132 | * like to test that the interesting value is received and that you cant 133 | * be bothered with the rest 134 | */ 135 | class SequencingActor(next: ActorRef, head: immutable.Seq[String], 136 | tail: immutable.Seq[String]) extends Actor { 137 | def receive = { 138 | case msg => { 139 | head foreach { next ! _ } 140 | next ! msg 141 | tail foreach { next ! _ } 142 | } 143 | } 144 | } 145 | } 146 | ``` -------------------------------------------------------------------------------- /2.3.6/scala/chapter3/10_actor_dsl.md: -------------------------------------------------------------------------------- 1 | # Actor DSL 2 | 3 | ### The Actor DSL 4 | 简单的actor——例如一次性worker甚或至在REPL中尝试的事物——可以更简洁地使用`Act`特质创建。支持的基础设施通过以下导入绑定: 5 | 6 | ```scala 7 | import akka.actor.ActorDSL._ 8 | import akka.actor.ActorSystem 9 | 10 | implicit val system = ActorSystem("demo") 11 | ``` 12 | 13 | 在这一节的所有代码示例都假定有此导入。下面的所有示例中隐式actor系统都作为`ActorRefFactory`提供服务。要定义一个简单的actor,以下代码就足够了: 14 | 15 | ```scala 16 | val a = actor(new Act { 17 | become { 18 | case "hello" ⇒ sender() ! "hi" 19 | } 20 | }) 21 | ``` 22 | 23 | 在这里,`actor`方法,根据其调用的上下文,取代了``system.actorOf``或 24 | ``context.actorOf``:它需要一个隐式的 `ActorRefFactory`,其中在actor内可以通过以下方式获取``implicit val context: ActorContext``。在actor外,你不得不要声明隐式的`ActorSystem`,或者你可以显式地提供工厂(具体参见下文)。 25 | 26 | 两种发起``context.become``(更换或添加新的行为)的可能方式是分别提供的,从而支持不凌乱的嵌套接收标记语法: 27 | 28 | ```scala 29 | val a = actor(new Act { 30 | become { // this will replace the initial (empty) behavior 31 | case "info" ⇒ sender() ! "A" 32 | case "switch" ⇒ 33 | becomeStacked { // this will stack upon the "A" behavior 34 | case "info" ⇒ sender() ! "B" 35 | case "switch" ⇒ unbecome() // return to the "A" behavior 36 | } 37 | case "lobotomize" ⇒ unbecome() // OH NOES: Actor.emptyBehavior 38 | } 39 | }) 40 | ``` 41 | 42 | 请注意,调用 ``unbecome`` 比 ``becomeStacked`` 次数多将导致原始行为被安装,对`Act`特质来说是空行为(外部``become``只是在构造过程中替换它)。 43 | 44 | ##### 生命周期管理 45 | 46 | 生命周期挂钩也可以暴露为 DSL 元素使用 (见[启动Hook](01_actors.md#start-hook-scala)和[终止Hook](01_actors.md#stop-hook-scala)),在那里如下所示的调用方法可以取代各自挂钩的内容: 47 | 48 | ```scala 49 | val a = actor(new Act { 50 | whenStarting { testActor ! "started" } 51 | whenStopping { testActor ! "stopped" } 52 | }) 53 | ``` 54 | 55 | 如果actor的逻辑生命周期匹配重新启动周期(即 ``whenStopping`` 在重新启动之前执行,并且`` whenStarting``在重启之后执行),上面的代码就足够了。如果这不是所期望的,可以使用下面的两个挂钩(请参阅[重启Hook](01_actors.md#restart-hook-scala)): 56 | 57 | ```scala 58 | val a = actor(new Act { 59 | become { 60 | case "die" ⇒ throw new Exception 61 | } 62 | whenFailing { case m @ (cause, msg) ⇒ testActor ! m } 63 | whenRestarted { cause ⇒ testActor ! cause } 64 | }) 65 | ``` 66 | 67 | 另外还可以创建嵌套actors,即孙子actor,像这样: 68 | 69 | ```scala 70 | // here we pass in the ActorRefFactory explicitly as an example 71 | val a = actor(system, "fred")(new Act { 72 | val b = actor("barney")(new Act { 73 | whenStarting { context.parent ! ("hello from " + self.path) } 74 | }) 75 | become { 76 | case x ⇒ testActor ! x 77 | } 78 | }) 79 | ``` 80 | 81 | > 注意 82 | 83 | > 在某些情况下必须显式传递`ActorRefFactory`给`actor()`方法(当编译器告诉你出现了模糊蕴涵(implicits)时,你会发现的)。 84 | 85 | 孙子actor会被子actor监管;此外这类关系的监管策略也可以使用 DSL 元素进行配置(监管指令是`Act`特质的一部分): 86 | 87 | ```scala 88 | superviseWith(OneForOneStrategy() { 89 | case e: Exception if e.getMessage == "hello" ⇒ Stop 90 | case _: Exception ⇒ Resume 91 | }) 92 | ``` 93 | 94 | ##### 有`Stash`的actor 95 | 96 | 最后并且很重要的一点是:还有一点像魔法一样方便的内置,可以检测静态给定的actor子类型的运行时类,是不是通过`Stash`特质扩展 `RequiresMessageQueue `特质(这是一个复杂表述,即``new Act with Stash``不能工作,因为它的运行时类型被擦除为``Act``的匿名子类型)。目的是为自动根据`Stash`的需要使用适当的基于deque的邮箱类型。如果你想要使用这个魔法,只需扩展 `ActWithStash`: 97 | 98 | ```scala 99 | val a = actor(new ActWithStash { 100 | become { 101 | case 1 ⇒ stash() 102 | case 2 ⇒ 103 | testActor ! 2; unstashAll(); becomeStacked { 104 | case 1 ⇒ testActor ! 1; unbecome() 105 | } 106 | } 107 | }) 108 | ``` 109 | 110 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter3/actors.md: -------------------------------------------------------------------------------- 1 | # Actors 2 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter4/02_agents.md: -------------------------------------------------------------------------------- 1 | # Agents 2 | 3 | > 注:本节未经校验,如有问题欢迎提issue 4 | 5 | Akka中的Agent是受 [Clojure agent](http://clojure.org/agents)启发的. 6 | 7 | Agent 提供对独立位置的异步修改. Agent在其生命周期中绑定到一个单独的存储位置,对这个存储位置的数据的修改(到一个新的状态)仅允许作为一个操作的结果发生。 对其进行修改的操作是函数,该函数被异步地应用于Agent的状态,其返回值成为Agent的新状态。 Agent的状态应该是不可变的。 8 | 9 | 虽然对Agent的修改是异步的,但是其状态总是可以随时被任何线程 来获得(通过 ``get`` 或 ``apply``)而不需要发送消息。 10 | 11 | Agent是响应式的(reactive). 对所有agent的更新操作在一个``ExecutionContext``的不同线程中并发执行。在每一个时刻,每一个Agent最多只有一个 ``send`` 被执行. 从某个线程派发到agent上的操作的执行次序与其发送的次序一致,但有可能与从其它线程源派发来的操作交织在一起。 12 | 13 | > 注意 14 | 15 | > Agent对创建它们的节点是本地的。这意味着你一般不应包括它们在消息中,因为可能会被传递到远程actor或作为远程actor的构造函数参数;那些远程Actor不能读取或更新Agent。 16 | 17 | ### 创建Agent 18 | 创建Agent时,调用 ``Agent(value)`` ,传入它的初始值并提供一个隐式的``ExecutionContext``供其使用,在这些例子中我们将使用默认的全局量,不过你的方法可能不同(YMMV : Your Method May Vary): 19 | 20 | ```scala 21 | import scala.concurrent.ExecutionContext.Implicits.global 22 | import akka.agent.Agent 23 | val agent = Agent(5) 24 | ``` 25 | 26 | ### 读取 Agent 的值 27 | Agent可以用括号调用来去引用 (你可以获取一个Agent的值) ,像这样: 28 | 29 | ```scala 30 | val result = agent() 31 | ``` 32 | 33 | 或者使用 get 方法: 34 | 35 | ```scala 36 | val result = agent.get 37 | ``` 38 | 39 | 读取Agent的当前值不包括任何消息传递,并立即执行。所以说虽然Agent的更新的异步的,对它的状态的读取却是同步的。 40 | 41 | ### 更新 Agent (send & alter) 42 | 更新Agent有两种方法:send一个函数来转换当前的值,或直接send一个新值。Agent会自动异步地应用新的值或函数。更新是以一种“发射后不管”的方式完成的,唯一的保证是它会被应用。 至于什么时候应用则没有保证,但是从同一个线程发到Agent的操作将被顺序应用。你通过调用``send``函数来应用一个值或函数。 43 | 44 | ```scala 45 | // send a value, enqueues this change 46 | // of the value of the Agent 47 | agent send 7 48 | 49 | // send a function, enqueues this change 50 | // to the value of the Agent 51 | agent send (_ + 1) 52 | agent send (_ * 2) 53 | ``` 54 | 55 | 你也可以在一个独立的线程中派发一个函数来改变其内部状态。这样将不使用响应式线程池,并可以被用于长时间运行或阻塞的操作。 相应的方法是 ``sendOff`` 。 派发器不管使用 ``sendOff`` 还是 ``send`` 都会顺序执行。 56 | 57 | ```scala 58 | // the ExecutionContext you want to run the function on 59 | implicit val ec = someExecutionContext() 60 | // sendOff a function 61 | agent sendOff longRunningOrBlockingFunction 62 | ``` 63 | 64 | 所有的``send``都有一个对应的``alter``方法来返回一个``Future``。参考[Futures](01_futures.md)来获取``Future``的更多信息。 65 | 66 | ```scala 67 | // alter a value 68 | val f1: Future[Int] = agent alter 7 69 | 70 | // alter a function 71 | val f2: Future[Int] = agent alter (_ + 1) 72 | val f3: Future[Int] = agent alter (_ * 2) 73 | ``` 74 | 75 | ```scala 76 | // the ExecutionContext you want to run the function on 77 | implicit val ec = someExecutionContext() 78 | // alterOff a function 79 | val f4: Future[Int] = agent alterOff longRunningOrBlockingFunction 80 | ``` 81 | 82 | ### 等待Agent的返回值 83 | 也可以获得一个Agent值的``Future``,将在所有当前排队的更新请求都完成以后完成: 84 | 85 | ```scala 86 | val future = agent.future 87 | ``` 88 | 89 | 参考[Futures](01_futures.md)来获取``Future``的更多信息。 90 | 91 | ### Monadic 用法 92 | Agent 也支持 monadic 操作, 这样你就可以用for-comprehensions对操作进行组合. 在 monadic 用法中, 旧的Agent不会变化,而是创建新的Agent。 所以老的值(Agents)仍像原来一样可用。这就是所谓的‘持久’. 93 | 94 | monadic 用法示例: 95 | 96 | ```scala 97 | import scala.concurrent.ExecutionContext.Implicits.global 98 | val agent1 = Agent(3) 99 | val agent2 = Agent(5) 100 | 101 | // uses foreach 102 | for (value <- agent1) 103 | println(value) 104 | 105 | // uses map 106 | val agent3 = for (value <- agent1) yield value + 1 107 | 108 | // or using map directly 109 | val agent4 = agent1 map (_ + 1) 110 | 111 | // uses flatMap 112 | val agent5 = for { 113 | value1 <- agent1 114 | value2 <- agent2 115 | } yield value1 + value2 116 | ``` 117 | 118 | ### 配置 119 | 有一些配置属性是针对Agent模块的,请参阅[参考配置](../chapter2/09_configuration.md#config-akka-agent)。 120 | 121 | ### 废弃的事务性Agent 122 | Agent参与封闭 STM 事务是 2.3 废弃的功能。 123 | 124 | 如果Agent在一个封闭的事务中使用,然后它将参与该事务。如果你在一个事务内发送到Agent,然后对该Agent的派发将暂停直到该事务被提交,如果事务中止则丢弃该派发。下面是一个示例: 125 | 126 | ```scala 127 | import scala.concurrent.ExecutionContext.Implicits.global 128 | import akka.agent.Agent 129 | import scala.concurrent.duration._ 130 | import scala.concurrent.stm._ 131 | 132 | def transfer(from: Agent[Int], to: Agent[Int], amount: Int): Boolean = { 133 | atomic { txn => 134 | if (from.get < amount) false 135 | else { 136 | from send (_ - amount) 137 | to send (_ + amount) 138 | true 139 | } 140 | } 141 | } 142 | 143 | val from = Agent(100) 144 | val to = Agent(20) 145 | val ok = transfer(from, to, 50) 146 | 147 | val fromValue = from.future // -> 50 148 | val toValue = to.future // -> 70 149 | ``` 150 | 151 | 152 | 153 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter4/futures_and_agents.md: -------------------------------------------------------------------------------- 1 | # Futures与Agents 2 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter5/01_cluster_cpecification.md: -------------------------------------------------------------------------------- 1 | # 集群规格 2 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter5/02_cluster_usage.md: -------------------------------------------------------------------------------- 1 | # 集群用法 2 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter5/05_io.md: -------------------------------------------------------------------------------- 1 | # I/O 2 | 3 | > 注:本节未经校验,如有问题欢迎提issue 4 | 5 | ### 介绍 6 | ``akka.io``包是由Akka和[spray.io](spray.io)团队协作开发的。它的设计结合了``spray-io``模块的经验,并共同进行了改进,使其适应基于actor服务的更加普遍的消费需求。 7 | 8 | 该 I/O 实现的指导设计目标是要达到极端的可扩展性,要毫不妥协地提供一个API正确匹配底层传输机制,并且是完全的事件驱动、无阻塞和异步。该API命中注定是网络协议实现和构建更高抽象的坚实基础;它不是为终端用户提供的全套的高级别的NIO包装。 9 | 10 | ### 术语,概念 11 | I/O API完全是基于actor的,意味着所有的操作实现都是通过消息传递而不是直接方法调用。每个 I/O 驱动程序 (TCP、 UDP) 有一个特殊的actor,被称为一个**管理器**,用作 API 的入口点。I/O 被分成几个驱动程序。用于某个特定驱动程序的管理器是通过 ``IO`` 入口点获取的。例如下面的代码查找 TCP 管理器,并返回其 ``ActorRef``: 12 | 13 | ```scala 14 | import akka.io.{ IO, Tcp } 15 | import context.system // implicitly used by IO(Tcp) 16 | 17 | val manager = IO(Tcp) 18 | ``` 19 | 20 | 管理器接收 I/O 命令消息并实例化工作actor作为回应。工作actor将自身返回给 API 用户作为发送该命令的答复。例如给TCP 管理器发送``Connect``命令后,管理器创建了代表 TCP 连接的actor。当该actor通过发送一个``Connected``消息宣布自身后,所有与给定 TCP 连接相关的操作都可以通过发送消息到连接actor来调用。 21 | 22 | ##### DeathWatch和资源管理 23 | 24 | I/O 工作actor接收命令,并且也发出事件。它们通常需要一个用户端对应的actor监听这些事件 (此类事件可以是入站的连接,传入的字节或写操作确认)。这些工作actor**观察**它们的对应监听。如果监听器停止工作,则工作actor将自动释放它所拥有的任何资源。这种设计使得该 API 更能抵抗资源泄漏。 25 | 26 | 多亏I/O API是完全基于actor设计的,相反的方向也可以工作:一个负责处理连接的用户actor可以观察连接actor,如果它意外终止也将收到通知。 27 | 28 | ##### 写模型(Ack, Nack) 29 | I/O设备有一个最大吞吐量来限制写操作的频率和大小。当一个应用程序试图推相比设备处理能力更多的数据时,驱动程序不得不缓冲字节,直到设备能够继续写他们。缓冲可以处理短暂的密集写入——但没有缓冲区是无限的。这时需要"流控制"来避免设备缓冲区不足的问题。 30 | 31 | Akka支持两种类型的流量控制: 32 | 33 | * *基于Ack*,当写操作成功的时候,驱动程序通知写者。 34 | 35 | * *基于Nack*,当写操作失败时,驱动程序会通知写者。 36 | 37 | 每一种模型在Akka I/O的 TCP 和 UDP 实现中都可用。 38 | 39 | 单独的写操作可以通过在写入消息(TCP中的``Write`` 和UDP中的``Send``)中提供一个 ack 对象来确认。写操作完成时工作者将发送 ack 对象给写actor。这可以用于实现*基于Ack*的流量控制;只有当老数据被确认时才发送新数据。 40 | 41 | 如果写入(或任何其他命令)失败,驱动程序会发送具有该命令一个特殊消息(UDP 和 TCP中是``CommandFailed``)来通知actor。此消息也会通知写者一个失败,作为那个写的一个nack。请注意,在基于nack 的流控制设置中,写者必须准备到,失败的写操作可能不是最近写操作的事实。例如,对于``W1``的写入失败通知可能在后来的写命令 ``W2``和``W3``被发送之后到达。如果写者想要重发送任何nack消息,它可能需要保留一个挂起消息的缓冲区。 42 | 43 | > 警告 44 | 45 | > 一个确认的写并不意味着确认送达或存储的;收到一个写ack只是表明I/O 驱动程序成功处理了写操作。这里描述的 Ack/Nack 协议是一种流量控制手段而不是错误处理。换句话说,数据仍然可能会丢失,即使每一个写操作都被确认。 46 | 47 | ##### ByteString 48 | 为了保持隔离,actor应该只通过不可变对象沟通。``ByteString`` 是bytes的不可的容器。它被用在Akka I/O系统中,作为在jvm上处理IO的传统字节容器,如``Array[Byte]``和``ByteBuffer``的一种高效的、 不可变的替代者。 49 | 50 | ByteString 是一个[绳状](rope-like 注:本节未经校验,如有问题欢迎提issue 4 | 5 | UDP 无连接的数据报协议,在JDK 级别上提供两种不同的通信方式: 6 | 7 | * 套接字可以自由地发送数据报到任何目的地,并从任何来源接收数据报 8 | * 套接字被限定只和一个特定的远程套接字地址通信 9 | 10 | 低级API中区分是——令人困惑地——通过是否在套接字上调用`connect`方法(甚至当`connect`被调用,协议仍然是无连接的)。UDP 使用的这两种形式是使用不同的 IO 扩展提供的,如下所述。 11 | 12 | ### 无连接UDP 13 | ##### 简单发送 14 | 15 | ```scala 16 | class SimpleSender(remote: InetSocketAddress) extends Actor { 17 | import context.system 18 | IO(Udp) ! Udp.SimpleSender 19 | 20 | def receive = { 21 | case Udp.SimpleSenderReady => 22 | context.become(ready(sender())) 23 | } 24 | 25 | def ready(send: ActorRef): Receive = { 26 | case msg: String => 27 | send ! Udp.Send(ByteString(msg), remote) 28 | } 29 | } 30 | ``` 31 | 32 | UDP 使用最简单的形式是只发送数据报,而不需要得到回复。为此目的一个"简单的发送者"工具如上所示。UDP 扩展使用`SimpleSender`消息查询 ,由`SimpleSenderReady`通知回答。此消息的发送者是新创建的发送者actor,从此时起可以用于将数据报发送到任意的目的地 ;在此示例中,它将只发送任何收到的utf-8编码的`String`到一个预定义的远程地址。 33 | 34 | > 注意 35 | 36 | > 简单的发送者不会关闭本身,因为它无法知道什么时候完成工作了。当你想要关闭该发送者的短暂绑定的端口时,你需要发送一个 `PoisonPill`给它。 37 | 38 | ##### 绑定(和发送) 39 | 40 | ```scala 41 | class Listener(nextActor: ActorRef) extends Actor { 42 | import context.system 43 | IO(Udp) ! Udp.Bind(self, new InetSocketAddress("localhost", 0)) 44 | 45 | def receive = { 46 | case Udp.Bound(local) => 47 | context.become(ready(sender())) 48 | } 49 | 50 | def ready(socket: ActorRef): Receive = { 51 | case Udp.Received(data, remote) => 52 | val processed = // parse data etc., e.g. using PipelineStage 53 | socket ! Udp.Send(data, remote) // example server echoes back 54 | nextActor ! processed 55 | case Udp.Unbind => socket ! Udp.Unbind 56 | case Udp.Unbound => context.stop(self) 57 | } 58 | } 59 | ``` 60 | 61 | 如果你想要实现一个 UDP 服务器侦听套接字来接收传入数据报,则你需要使用`Bind`命令,如上所示。指定的本地地址可能会有一个为零的端口,此时操作系统会自动选择一个自由端口并将它分配给新的套接字。通过检查`Bound`消息可以发现实际上绑定的是哪个端口。 62 | 63 | `Bound`消息的发送者是管理新套接字的那个actor。发送数据报是通过使用`Send`消息类型实现的,并且套接字可以通过发送一个 `Unbind` 命令来关闭,这种情况下套接字actor会回复一个`Unbound`通知。 64 | 65 | 接收的数据报发送到被`Bind`消息指定的actor,`Bound`消息将被发送给`Bind`的发送者。 66 | 67 | ### 连接的 UDP 68 | 通过基于连接的 UDP API 提供的服务,类似于我们前面所述的bind-and-send服务,但主要区别是连接只是能够将发送到它连接到de ``remoteAddress``,并将只能从该地址接收数据报。 69 | 70 | ```scala 71 | class Connected(remote: InetSocketAddress) extends Actor { 72 | import context.system 73 | IO(UdpConnected) ! UdpConnected.Connect(self, remote) 74 | 75 | def receive = { 76 | case UdpConnected.Connected => 77 | context.become(ready(sender())) 78 | } 79 | 80 | def ready(connection: ActorRef): Receive = { 81 | case UdpConnected.Received(data) => 82 | // process data, send it on, etc. 83 | case msg: String => 84 | connection ! UdpConnected.Send(ByteString(msg)) 85 | case d @ UdpConnected.Disconnect => connection ! d 86 | case UdpConnected.Disconnected => context.stop(self) 87 | } 88 | } 89 | 90 | ``` 91 | 92 | 因此在这里的例子看起来非常类似于前一个示例,最大的区别是`Send`和`Received`消息中没有远程地址信息。 93 | 94 | > 注意 95 | 96 | > 还有相比无连接的,使用基于连接的 UDP API有小的性能好处。如果系统启用了一个安全管理器,每个无连接的消息发送要经过一个安全检查,而在基于连接的 UDP 的情况下,安全检查连接后被缓存,因此写操作不会遭受额外的性能惩罚。 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter5/09_camel.md: -------------------------------------------------------------------------------- 1 | # Camel 2 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter5/networking.md: -------------------------------------------------------------------------------- 1 | # 网络 2 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter6/04_duration.md: -------------------------------------------------------------------------------- 1 | # Duration 2 | 3 | > 注:本节未经校验,如有问题欢迎提issue 4 | 5 | Duration在Akka库中被广泛使用,这代表一个特殊的数据类型——`scala.concurrent.duration.Duration`。这个类型的值可以表示无限(`Duration.Inf`, `Duration.MinusInf`)或有限的时间段,或是`Duration.Undefined`。 6 | 7 | ### 有限与无限 8 | 试图将无限的duration转换成一个具体的时间单位,如秒,将引发异常,在编译时有不同类型可用于区分两者: 9 | 10 | * `FiniteDuration` 保证是有限的,调用 `toNanos` 和相关方法是安全的 11 | * `Duration`可以是有限或无限的,因此这种类型只用与有限性并不重要的场合 ;这是 `FiniteDuration` 的超类。 12 | 13 | ### Scala 14 | 在Scala,时间段可以通过一个迷你DSL来创建,并支持所有期望的算术操作: 15 | 16 | ```scala 17 | import scala.concurrent.duration._ 18 | 19 | val fivesec = 5.seconds 20 | val threemillis = 3.millis 21 | val diff = fivesec - threemillis 22 | assert(diff < fivesec) 23 | val fourmillis = threemillis * 4 / 3 // you cannot write it the other way around 24 | val n = threemillis / (1 millisecond) 25 | ``` 26 | 27 | > 注意 28 | 29 | > 如果表达式划定了明显的边界(例如在括号里或在参数列表里),你可以省略".",但是如果时间单位是一行代码的最后一个词,建议你加上它,否则行末分号推断可能会出错,这取决于下一行是如何开始的。 30 | 31 | > Java 32 | 33 | > Java提供的语法糖比较少,所以你必须用方法调用来拼出要进行的操作: 34 | 35 | ```java 36 | import scala.concurrent.duration.Duration; 37 | import scala.concurrent.duration.Deadline; 38 | ``` 39 | 40 | ```java 41 | final Duration fivesec = Duration.create(5, "seconds"); 42 | final Duration threemillis = Duration.create("3 millis"); 43 | final Duration diff = fivesec.minus(threemillis); 44 | assert diff.lt(fivesec); 45 | assert Duration.Zero().lt(Duration.Inf()); 46 | ``` 47 | 48 | ### Deadline 49 | Duration 有一个兄弟类,名为 `Deadline`, 表示一个持有绝对的时间点的类,并且支持通过计算当前时间到deadline之间的差距来生成Duration。当你想要保持一个总体的期限,而无需记录——自己关注使用时间时,这非常有用: 50 | 51 | ```scala 52 | val deadline = 10.seconds.fromNow 53 | // do something 54 | val rest = deadline.timeLeft 55 | ``` 56 | 57 | 在Java中使用duration来创建dealine: 58 | 59 | ```java 60 | final Deadline deadline = Duration.create(10, "seconds").fromNow(); 61 | final Duration rest = deadline.timeLeft(); 62 | ``` 63 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter6/05_circuit_breaker.md: -------------------------------------------------------------------------------- 1 | # 线路断路器 2 | 3 | > 注:本节未经校验,如有问题欢迎提issue 4 | 5 | ### 为什么使用它们? 6 | 线路断路器用于提供稳定性并防止在分布式系统中的级联故障。它们应该结合在远程系统之间的接口使用明智的超时,以防止单个组件的故障拖垮所有组件。 7 | 8 | 作为一个例子,我们有一个web 应用程序与远程的第三方web服务进行交互。假如第三方已用完了他们的容量,他们的数据库也在高荷载作用下熔化。假设数据库在这种情况下失败,第三方 web 服务用了很长的时间来返回一个错误。这进一步使调用在长一段时间后失败。回到我们的 web 应用程序,用户已注意到其表单提交似乎比需要的使用了更长的时间。当然用户知道要做的是点击刷新按钮,将更多的请求添加到其已在运行的请求中。这最终导致 web 应用程序由于资源枯竭而失败。这将会影响所有用户,甚至是那些没有使用依赖于此第三方 web 服务的功能的。 9 | 10 | 为 web 服务的调用引入断路器会导致请求开始快速失败,让用户知道有什么地方不对劲,并且他们不需要刷新他们的请求。这还局限失效行为只影响到那些正在使用此第三方功能依赖的用户,因为没有资源枯竭,其他用户不再受影响。电路断路器还可以允许聪明的开发者来标记使用不可用功能的网站部分,或也许在断路器处于打开状态时,显示出一些适当的缓存内容。 11 | 12 | Akka库提供名为 `akka.pattern.CircuitBreaker`的断路器实现,具有如下所述的行为。 13 | 14 | ### 他们是做什么工作的? 15 | 16 | * 在正常操作期间,断路器处于`Closed`状态: 17 | * 异常或超过配置的 ``callTimeout`` 的调用增加一个失败计数 18 | * 成功重置失败计数为零 19 | * 当失败计数达到 ``maxFailures`` 时,断路器跳入`Open`状态 20 | * 在`Open`状态: 21 | * 所有调用通过 `CircuitBreakerOpenException` 快速失败 22 | * 经过配置的 `resetTimeout`,断路器进入`Half-Open`状态 23 | * 在`Half-Open`状态: 24 | * 第一个调用被允许尝试,而不通过快速失败 25 | * 其他调用就像在`Open`状态一样快速失败 26 | * 如果第一次调用成功,断路器是重置回`Closed`状态 27 | * 如果第一次调用失败,断路器再次跳入`Open`状态并经历另一个完整的`resetTimeout` 28 | * 状态转换监听器: 29 | * 可以为每个状态条目通过 `onOpen`、 `onClose` 和 `onHalfOpen` 提供回调 30 | * 这些都在提供的 `ExecutionContext` 中执行。 31 | 32 | ![](../images/circuit-breaker-states.png) 33 | 34 | ### 例子 35 | ##### 初始化 36 | 下面是如何配置一个`CircuitBreaker`: 37 | * 最多失败5次 38 | * 调用超时时间为 10 秒 39 | * 重置超时时间为 1 分钟 40 | 41 | ###### Scala 42 | ```scala 43 | import scala.concurrent.duration._ 44 | import akka.pattern.CircuitBreaker 45 | import akka.pattern.pipe 46 | import akka.actor.Actor 47 | import akka.actor.ActorLogging 48 | import scala.concurrent.Future 49 | import akka.event.Logging 50 | 51 | class DangerousActor extends Actor with ActorLogging { 52 | import context.dispatcher 53 | 54 | val breaker = 55 | new CircuitBreaker(context.system.scheduler, 56 | maxFailures = 5, 57 | callTimeout = 10.seconds, 58 | resetTimeout = 1.minute).onOpen(notifyMeOnOpen()) 59 | 60 | def notifyMeOnOpen(): Unit = 61 | log.warning("My CircuitBreaker is now open, and will not close for one minute") 62 | ``` 63 | 64 | ###### Java 65 | ```java 66 | import akka.actor.UntypedActor; 67 | import scala.concurrent.Future; 68 | import akka.event.LoggingAdapter; 69 | import scala.concurrent.duration.Duration; 70 | import akka.pattern.CircuitBreaker; 71 | import akka.event.Logging; 72 | 73 | import static akka.pattern.Patterns.pipe; 74 | import static akka.dispatch.Futures.future; 75 | 76 | import java.util.concurrent.Callable; 77 | 78 | public class DangerousJavaActor extends UntypedActor { 79 | 80 | private final CircuitBreaker breaker; 81 | private final LoggingAdapter log = Logging.getLogger(getContext().system(), this); 82 | 83 | public DangerousJavaActor() { 84 | this.breaker = new CircuitBreaker( 85 | getContext().dispatcher(), getContext().system().scheduler(), 86 | 5, Duration.create(10, "s"), Duration.create(1, "m")) 87 | .onOpen(new Runnable() { 88 | public void run() { 89 | notifyMeOnOpen(); 90 | } 91 | }); 92 | } 93 | 94 | public void notifyMeOnOpen() { 95 | log.warning("My CircuitBreaker is now open, and will not close for one minute"); 96 | } 97 | ``` 98 | 99 | ##### 调用保护 100 | 下面是如何将`CircuitBreaker`用于保护一个异步调用,以及一个同步调用: 101 | 102 | ###### Scala 103 | ```scala 104 | def dangerousCall: String = "This really isn't that dangerous of a call after all" 105 | 106 | def receive = { 107 | case "is my middle name" => 108 | breaker.withCircuitBreaker(Future(dangerousCall)) pipeTo sender() 109 | case "block for me" => 110 | sender() ! breaker.withSyncCircuitBreaker(dangerousCall) 111 | } 112 | ``` 113 | 114 | ###### Java 115 | ```java 116 | public String dangerousCall() { 117 | return "This really isn't that dangerous of a call after all"; 118 | } 119 | 120 | @Override 121 | public void onReceive(Object message) { 122 | if (message instanceof String) { 123 | String m = (String) message; 124 | if ("is my middle name".equals(m)) { 125 | pipe(breaker.callWithCircuitBreaker( 126 | new Callable>() { 127 | public Future call() throws Exception { 128 | return future( 129 | new Callable() { 130 | public String call() { 131 | return dangerousCall(); 132 | } 133 | }, getContext().dispatcher()); 134 | } 135 | }), getContext().dispatcher()).to(getSender()); 136 | } 137 | if ("block for me".equals(m)) { 138 | getSender().tell(breaker 139 | .callWithSyncCircuitBreaker( 140 | new Callable() { 141 | @Override 142 | public String call() throws Exception { 143 | return dangerousCall(); 144 | } 145 | }), getSelf()); 146 | } 147 | } 148 | } 149 | ``` 150 | 151 | > 注意 152 | 153 | > 使用`CircuitBreaker`伴生对象的`apply`或`create`方法将返回在调用者的线程中执行回调的`CircuitBreaker`。如果异步`Future`不必要的时候,这可以是很有用的,例如仅调用同步的API。 154 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter6/06_akka_extensions.md: -------------------------------------------------------------------------------- 1 | # Akka扩展 2 | 3 | > 注:本节未经校验,如有问题欢迎提issue 4 | 5 | 如果想要为Akka添加特性,有一个非常优美而且强大的工具,称为 Akka 扩展。它由两部分组成: ``Extension`` 和 ``ExtensionId``. 6 | 7 | Extensions 在每个 ``ActorSystem`` 中只会加载一次, 并被Akka所管理。 你可以选择按需加载你的Extension或是在 ``ActorSystem`` 创建时通过Akka配置来加载。 关于这些细节,见下文 “从配置中加载” 的部分. 8 | 9 | > 警告 10 | 11 | > 由于扩展是hook到Akka自身的,所以扩展的实现者需要保证自己扩展的线程安全性。 12 | 13 | ### 构建一个扩展 14 | 现在我们来创建一个扩展示例,它的功能是对某件事发生的次数进行统计。 15 | 16 | 首先定义 ``Extension`` 的功能: 17 | 18 | ```scala 19 | import akka.actor.Extension 20 | 21 | class CountExtensionImpl extends Extension { 22 | //Since this Extension is a shared instance 23 | // per ActorSystem we need to be threadsafe 24 | private val counter = new AtomicLong(0) 25 | 26 | //This is the operation this Extension provides 27 | def increment() = counter.incrementAndGet() 28 | } 29 | ``` 30 | 31 | 然后需要为扩展指定一个 ``ExtensionId``,这样我们可以获取它的实例. 32 | 33 | ```scala 34 | import akka.actor.ActorSystem 35 | import akka.actor.ExtensionId 36 | import akka.actor.ExtensionIdProvider 37 | import akka.actor.ExtendedActorSystem 38 | 39 | object CountExtension 40 | extends ExtensionId[CountExtensionImpl] 41 | with ExtensionIdProvider { 42 | //The lookup method is required by ExtensionIdProvider, 43 | // so we return ourselves here, this allows us 44 | // to configure our extension to be loaded when 45 | // the ActorSystem starts up 46 | override def lookup = CountExtension 47 | 48 | //This method will be called by Akka 49 | // to instantiate our Extension 50 | override def createExtension(system: ExtendedActorSystem) = new CountExtensionImpl 51 | 52 | /** 53 | * Java API: retrieve the Count extension for the given system. 54 | */ 55 | override def get(system: ActorSystem): CountExtensionImpl = super.get(system) 56 | } 57 | ``` 58 | 59 | 好了!然后我们就可以使用它了: 60 | 61 | ```scala 62 | CountExtension(system).increment 63 | ``` 64 | 65 | 或者在Akka Actor中使用: 66 | 67 | ```scala 68 | class MyActor extends Actor { 69 | def receive = { 70 | case someMessage => 71 | CountExtension(context.system).increment() 72 | } 73 | } 74 | ``` 75 | 76 | 你也可以将扩展藏在 trait 里: 77 | 78 | ```scala 79 | trait Counting { self: Actor => 80 | def increment() = CountExtension(context.system).increment() 81 | } 82 | class MyCounterActor extends Actor with Counting { 83 | def receive = { 84 | case someMessage => increment() 85 | } 86 | } 87 | ``` 88 | 89 | 这样就搞定了! 90 | 91 | ### 从配置中加载 92 | 为了能够从Akka配置中加载扩展,你必须在为`ActorSystem`提供的配置文件中的 ``akka.extensions`` 部分加上 ``ExtensionId`` 或 ``ExtensionIdProvider``实现类的完整路径。 93 | 94 | ``` 95 | akka { 96 | extensions = ["docs.extension.CountExtension"] 97 | } 98 | ``` 99 | 100 | ### 实用性 101 | 充分发挥你的想象力,天空才是极限! 顺便提一下,你知道 Akka的``Typed Actor``, ``Serialization``和其它一些特性都是以Akka扩展的形式实现的吗? 102 | 103 | ##### 应用特定设置 104 | 可以用 [Configuration]() 来指定应用特有的设置。将这些设置放在一个扩展里是一个好习惯。 105 | 106 | 配置示例: 107 | 108 | ``` 109 | myapp { 110 | db { 111 | uri = "mongodb://example1.com:27017,example2.com:27017" 112 | } 113 | circuit-breaker { 114 | timeout = 30 seconds 115 | } 116 | } 117 | ``` 118 | 119 | ``Extension``的实现: 120 | 121 | ```scala 122 | import akka.actor.ActorSystem 123 | import akka.actor.Extension 124 | import akka.actor.ExtensionId 125 | import akka.actor.ExtensionIdProvider 126 | import akka.actor.ExtendedActorSystem 127 | import scala.concurrent.duration.Duration 128 | import com.typesafe.config.Config 129 | import java.util.concurrent.TimeUnit 130 | 131 | class SettingsImpl(config: Config) extends Extension { 132 | val DbUri: String = config.getString("myapp.db.uri") 133 | val CircuitBreakerTimeout: Duration = 134 | Duration(config.getMilliseconds("myapp.circuit-breaker.timeout"), 135 | TimeUnit.MILLISECONDS) 136 | } 137 | object Settings extends ExtensionId[SettingsImpl] with ExtensionIdProvider { 138 | 139 | override def lookup = Settings 140 | 141 | override def createExtension(system: ExtendedActorSystem) = 142 | new SettingsImpl(system.settings.config) 143 | 144 | /** 145 | * Java API: retrieve the Settings extension for the given system. 146 | */ 147 | override def get(system: ActorSystem): SettingsImpl = super.get(system) 148 | } 149 | ``` 150 | 151 | 使用它: 152 | 153 | ```scala 154 | class MyActor extends Actor { 155 | val settings = Settings(context.system) 156 | val connection = connect(settings.DbUri, settings.CircuitBreakerTimeout) 157 | ``` 158 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter6/07_microkernel.md: -------------------------------------------------------------------------------- 1 | # 微内核 2 | 3 | > 注:本节未经校验,如有问题欢迎提issue 4 | 5 | Akka微内核的目的是提供一个捆绑机制,以便将 Akka 应用程序作为一个单一有效载荷分发,而不需要在 Java 应用程序服务器中运行,或手动创建一个启动脚本。 6 | 7 | Akka 微内核包含在[Akka下载](http://akka.io/downloads)中. 8 | 9 | 要通过微内核运行应用,你需要创建一个 Bootable 类来处理应用的启动和关闭。下面例子中有介绍。 10 | 11 | 将你的应用jar包放在 ``deploy`` 目录下,并把依赖放入``lib``目录下以便自动装载并放在类路径中。 12 | 13 | 要启动内核使用 ``bin`` 目录下的脚本, 将应用启动类传进来. 14 | 15 | 以下是akka下载包中的一个应用与微内核一起运行的例子. 它可以用以下的命令运行 (在unix系统上): 16 | 启动脚本添加 ``config`` 目录作为类路径第一个元素,其次是``lib/*``。它以``akka.kernel.Main``为主类运行 java 并提供引导类作为参数。 17 | 18 | (基于 unix 的系统)示例命令: 19 | 20 | ``` 21 | bin/akka sample.kernel.hello.HelloKernel 22 | ``` 23 | 24 | 使用 ``Ctrl-C`` 来中断并退出微内核. 25 | 26 | 在Windows机器上你可以使用 ``bin/akka.bat`` 脚本. 27 | 28 | 以下是Hello Kernel 示例 (参考 ``HelloKernel``创建一个Bootable 类): 29 | 30 | ```scala 31 | package sample.kernel.hello 32 | 33 | import akka.actor.{ Actor, ActorSystem, Props } 34 | import akka.kernel.Bootable 35 | 36 | case object Start 37 | 38 | class HelloActor extends Actor { 39 | val worldActor = context.actorOf(Props[WorldActor]) 40 | 41 | def receive = { 42 | case Start => worldActor ! "Hello" 43 | case message: String => 44 | println("Received message '%s'" format message) 45 | } 46 | } 47 | 48 | class WorldActor extends Actor { 49 | def receive = { 50 | case message: String => sender() ! (message.toUpperCase + " world!") 51 | } 52 | } 53 | 54 | class HelloKernel extends Bootable { 55 | val system = ActorSystem("hellokernel") 56 | 57 | def startup = { 58 | system.actorOf(Props[HelloActor]) ! Start 59 | } 60 | 61 | def shutdown = { 62 | system.shutdown() 63 | } 64 | } 65 | ``` 66 | 67 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter6/utilities.md: -------------------------------------------------------------------------------- 1 | # 实用工具 2 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter7/howto_common_patterns.md: -------------------------------------------------------------------------------- 1 | # 如何使用:常用模式 2 | 3 | > 注:本节未经校验,如有问题欢迎提issue 4 | 5 | 本节列出了一些常见的actor模式,它们已被发现是有用的、优雅的或有启发意义的。所有主题都是受欢迎的,列出的示例主题包括消息路由策略,监督模式,重启处理等。作为一个特殊的奖励,这一节补充标记了贡献者的名字,如果每个Akka使用者在他或她的代码中发现重复出现的模式,并为所有人分享它的好处是多么美好的事情啊。在适和的情况下也可能加入``akka.pattern``包来创建一个[类OTP库(OTP-like library)](http://www.erlang.org/doc/man_index.html)。 6 | 7 | ### 限制消息 8 | 9 | 贡献者:Kaspar Fischer 10 | 11 | "一个消息节流器以确保消息不会以太高的速率发送。" 12 | 13 | 该模式详见[在Akka2中做消息限流](http://letitcrash.com/post/28901663062/throttling-messages-in-akka-2)。 14 | 15 | ### 跨节点平衡负载 16 | 17 | 贡献者:Derek Wyatt 18 | 19 | "很多时候,人们需要BalancingDispatcher的功能中包含在不同节点上拥有独立邮箱的Actor工作的规则。在这篇文章我们将探索实现这样一个概念。" 20 | 21 | 该模式详见[Akka2跨节点负载均衡](http://letitcrash.com/post/29044669086/balancing-workload-across-nodes-with-akka-2>)。 22 | 23 | ### 工作拉取模式来限流和分发工作,并防止邮箱溢出 24 | 25 | 贡献者:Michael Pollmeier 26 | 27 | "如果创建工作的速度实际上比执行它块,这种模式可以确保你的邮箱不会溢出 —— 当邮箱最终变得太满时这会导致内存溢出错误。它也让你围绕你的群集分配工作,动态地扩展规模,并且是完全无阻塞的。这是‘负载均衡模式’的一个特例。 28 | 29 | 该模式详见[工作拉取模式来限流和分发工作,并防止邮箱溢出](http://www.michaelpollmeier.com/akka-work-pulling-pattern/)。 30 | 31 | ### 有序终止 32 | 33 | 贡献者:Derek Wyatt 34 | 35 | "当一个actor停止时,它的子actor以未知顺序停止。子actor终止是异步的,因而是不确定的。 36 | 37 | 如果actor的孩子有顺序依赖关系,则你可能需要确保这些子actor以特定顺序关闭,从而使其postStop() 方法按正确顺序调用。" 38 | 39 | 该模式详见[一种Akka2终止器](http://letitcrash.com/post/29773618510/an-akka-2-terminator)。 40 | 41 | ### Akka AMQP 代理 42 | 43 | 贡献者:Fabrice Drouin 44 | 45 | "“AMQP 代理”是将AMQP与Akka结合进行跨计算节点网络工作分发的简单方法。你将仍然编写“本地”代码,进行很少的配置,并将最终拥有一个分布式的、弹性的、容错的网格,其计算节点可以几乎以任何语言编写。" 46 | 47 | 该模式详见[Akka AMQP 代理](http://letitcrash.com/post/29988753572/akka-amqp-proxies)。 48 | 49 | ### Akka2 关闭模式 50 | 51 | 贡献者:Derek Wyatt 52 | 53 | "当一切都结束时你如何告诉Akka关闭ActorSystem?原来竟然没有这样一个神奇的标志,没有配置设置,没有可以注册特殊回调的地方,也没有杰出的关机童话仙子用她的荣光在那完美的一刻恩典你的应用程序。她就是很普通刻薄。 54 | 55 | 在这篇文章中,我们将讨论为什么是这种情况,并为你提供一个简单的选项"在正确的时间"关闭,以及一个并不是-那么-简单-的选项来达到同样的目的。" 56 | 57 | 该模式详见[Akka2 关闭模式](http://letitcrash.com/post/30165507578/shutdown-patterns-in-akka-2)。 58 | 59 | ### Akka分布式(内存中)图处理 60 | 61 | 贡献者:Adelbert Chang 62 | 63 | "图在数学和计算机科学(以及其他领域)中一直是一个有趣的研究结构,而且在社交网络如Facebook和Twitter中变得更加有趣,其底层网络结构可以很好地由图来描述"。 64 | 65 | 该模式详见[Akka分布式(内存中)图处理](http://letitcrash.com/post/30257014291/distributed-in-memory-graph-processing-with-akka)。 66 | 67 | ### 案例研究:使用actor自动更新缓存 68 | 贡献者:Eric Pederson 69 | 70 | "我们最近需要在一个缓慢的后端系统前构建一个高速缓存系统,并符合下列要求: 71 | 72 | 后端系统中的数据是不断更新的,所以需要每隔N分钟更新缓存。对后端系统的直接请求需要被限流。我们建立的缓存系统使用了Akka actor和 Scala 中函数作为头等对象的支持。" 73 | 74 | 该模式详见[案例研究:使用actor自动更新缓存](http://letitcrash.com/post/30509298968/case-study-an-auto-updating-cache-using-actors)。 75 | 76 | ### 使用蜘蛛模式在actor系统中发现消息流 77 | 78 | 贡献者:Raymond Roestenburg 79 | 80 | "构建actor系统是有趣的,可是调试它们可能很困难,你大多情况下需要在多个机器中浏览大量日志文件,来了解到底发生了什么。我敢肯定你在啃日志时会想,“嘿,这个消息跑哪了?”,“为什么这个消息引起这种效果”或“为什么这个actor永远得不到消息?” 81 | 82 | 这是蜘蛛模式的进来。" 83 | 84 | 该模式详见[使用蜘蛛模式在actor系统中发现消息流](http://letitcrash.com/post/30585282971/discovering-message-flows-in-actor-systems-with-the)。 85 | 86 | ### 调度周期性消息 87 | 88 | 此模式描述了如何安排周期性消息给自己,有两种不同方式。 89 | 90 | 第一种方法是在actor构造函数中设置定期消息调度,并在 ``postStop`` 中取消定时发送,否则我们可能会有多个已注册的消息发送到相同的actor。 91 | 92 | > 注意 93 | 94 | > 用这种方法被调度的定期消息发送将在actor重启时被重新启动。这也意味着在重新启动期间,两个tick消息之间的时间间隔可能会漂移,它基于你重新启动调度预定的消息时的时间到最后一个消息的发送时间,以及初始延迟是多长时间。最糟糕的情况是``interval``加上``initialDelay``。 95 | 96 | ```scala 97 | class ScheduleInConstructor extends Actor { 98 | import context.dispatcher 99 | val tick = 100 | context.system.scheduler.schedule(500 millis, 1000 millis, self, "tick") 101 | 102 | override def postStop() = tick.cancel() 103 | 104 | def receive = { 105 | case "tick" => 106 | // do something useful here 107 | } 108 | } 109 | ``` 110 | 111 | 第二种变体在actor的``preStart``方法中建立了一个初始的消息发送,然后当actor接收到此消息时设置一个新的消息发送。你还必须重写 ``postRestart``,所以我们不会调用 ``preStart`` 并重新调度一个初始消息的发送。 112 | 113 | > 注意 114 | 115 | > 用这种方法,即使actor负载很高,我们也不会被tick消息填满邮箱,而只会在收到前一个tick消息之后安排新tick消息发送。 116 | 117 | ```scala 118 | class ScheduleInReceive extends Actor { 119 | import context._ 120 | 121 | override def preStart() = 122 | system.scheduler.scheduleOnce(500 millis, self, "tick") 123 | 124 | // override postRestart so we don't call preStart and schedule a new message 125 | override def postRestart(reason: Throwable) = {} 126 | 127 | def receive = { 128 | case "tick" => 129 | // send another periodic tick after the specified delay 130 | system.scheduler.scheduleOnce(1000 millis, self, "tick") 131 | // do something useful here 132 | } 133 | } 134 | ``` 135 | 136 | ### 模板模式 137 | *贡献者:N. N.* 138 | 139 | 这是一种特别好的模式,因为它甚至伴随着一些空的示例代码: 140 | 141 | ```scala 142 | class ScalaTemplate { 143 | println("Hello, Template!") 144 | // uninteresting stuff ... 145 | } 146 | ``` 147 | 148 | > 注意 149 | 150 | > 流传一句话:这是成名的最简单方法! 151 | 152 | 请在该文件的结尾保留这个模式。 153 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter8/03_actors.md: -------------------------------------------------------------------------------- 1 | # Actors(使用Java的Lambda支持) 2 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter8/04_fsm.md: -------------------------------------------------------------------------------- 1 | # FSM(使用Java的Lambda支持) 2 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter8/05_external_contributions.md: -------------------------------------------------------------------------------- 1 | # 外部贡献 2 | 3 | > 注:本节未经校验,如有问题欢迎提issue 4 | 5 | 该子项目用来作为外部开发人员贡献模块的地方,随着时间的推移它可能会,也可能不会进入正式支持的代码中。这种转变可以发生的条件包括: 6 | 7 | * 必须有足够的兴趣把模块列入标准的发行版中, 8 | * 必须积极维护模块 9 | * 代码质量必须足够好,允许由Akka核心开发团队有效的维护 10 | 11 | 如果贡献被发现不足以"起飞",它可能会再次在稍后的时间移除。 12 | 13 | ### 买者自负 14 | 15 | 在此子项目中的模块并不都得服从小版本之间的二进制兼容规则。次要版本中可能引入破坏 API 的更改并且没有通知,只是基于用户的反馈意见。一个模块可能未经事先通知而丢弃。Typesafe订阅并不包括对这些模块的支持。 16 | 17 | ### 当前模块的列表 18 | 19 | * [可靠的代理模式](http://doc.akka.io/docs/akka/2.3.6/contrib/reliable-proxy.html) 20 | * 可靠代理简介 21 | * 它保证的到底是什么? 22 | * 连接到目标 23 | * 如何使用它 24 | * 配置 25 | * Actor契约 26 | * 它处理的消息 27 | * 它发送的消息 28 | * 它升级的异常 29 | * 它的参数 30 | 31 | * [Actor消息节流](http://doc.akka.io/docs/akka/2.3.6/contrib/throttle.html) 32 | * 介绍 33 | * 如何使用它 34 | * 保障 35 | 36 | * [Java 日志记录 (JUL)](http://doc.akka.io/docs/akka/2.3.6/contrib/jul.html) 37 | 38 | * [使用显式确认的邮箱](http://doc.akka.io/docs/akka/2.3.6/contrib/peek-mailbox.html)[ 39 | 40 | * [群集单例](http://doc.akka.io/docs/akka/2.3.6/contrib/cluster-singleton.html) 41 | * 需要意识到的潜在问题 42 | * 一个例子 43 | 44 | * [群集Sharding](http://doc.akka.io/docs/akka/2.3.6/contrib/cluster-sharding.html) 45 | * 一个Java示例 46 | * 一个Scala示例 47 | * 它是如何工作 48 | * 仅代理模式 49 | * 钝化 50 | * 配置 51 | 52 | * [分布式发布订阅群集](http://doc.akka.io/docs/akka/2.3.6/contrib/distributed-pub-sub.html) 53 | * 一个Java示例 54 | * 一个Scala示例 55 | * DistributedPubSubExtension 56 | 57 | * [群集客户机](http://doc.akka.io/docs/akka/2.3.6/contrib/cluster-client.html) 58 | * 一个例子 59 | * ClusterReceptionistExtension 60 | 61 | * [聚合器模式](http://doc.akka.io/docs/akka/2.3.6/contrib/aggregator.html) 62 | * 介绍 63 | * 使用 64 | * 样本用例 - AccountBalanceRetriever 65 | * 样本用例 - 多个响应聚合和链接 66 | * 陷阱 67 | 68 | ### 利用这些贡献的建议方式 69 | 由于Akka团队不限制到此子项目的更新,即使在二进制兼容的切换版本中,而且有可能在没有警告的情况下删除模块,因此建议将源文件复制到你自己的代码基中,更改包名称。通过这种方式,你可以选择何时更新或哪些修补程序需要包括进来(以保持二进制兼容性,如果需要的话),而且更高版本的Akka不可能破坏你的应用程序。 70 | 71 | ### 建议的贡献格式 72 | 73 | 每个贡献应该是一个自包含的单元,包括一个源文件或一个专门使用的包,没有对此子项目中其他模块的依赖;不过它可以依赖于Akka发布。这将确保贡献可以单独移动到标准发布中。该模块应在 ``akka.contrib`` 的一个子包中。 74 | 75 | 每个模块必须伴随一个测试套件验证其提供的功能,可能辅之以集成和单元测试。测试应遵守[开发者指南](),并放在``src/test/scala`` 或``src/test/java``目录中(被测试的模块需要正确匹配包名)。例如,如果该模块被称为 ``akka.contrib.pattern.ReliableProxy``,则其测试套件应命名为 ``akka.contrib.pattern.ReliableProxySpec``。 76 | 77 | 每个模块还必须有用[reStructured Text](http://sphinx.pocoo.org/rest.html)编写的恰当的文档。文档应该是一个单一的 ``.rst`` 文件,在``akka-contrib/docs``目录中,包括从``index.rst``(此文件)的链接。 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter8/experimental_modules.md: -------------------------------------------------------------------------------- 1 | # 实验模块 2 | 3 | > 注:本节未经校验,如有问题欢迎提issue 4 | 5 | 以下几个Akka模块被标记作为实验性的,这意味着它们处于早期访问模式,这也意味着他们没有包含在商业支持中。将它们作为实验模块提早发布的目的是使其更容易获得和根据反馈改进,或甚至发现该模块并不是很有用。 6 | 7 | 实验模块并非都要服从微版本间二进制兼容的规定。在根据用户反馈完善和简化时,破坏 API 的更改可能在不注意的情况下在次要版本中引入。实验模块可能在没有标记为废弃的情况下在次要版本被弃用。 8 | 9 | * [持久性](../chapter3/08_persistence.md) 10 | * [多节点测试](02_multi_node_testing.md) 11 | * Actor(Java Lambda 的支持)[不在此scala文档中介绍] 12 | * FSM(Java Lambda 的支持)[不在此scala文档中介绍] 13 | 14 | 标记模块为实验性的另一个原因是模块没有足够时间来证明有一个可以长时间肩负维护责任的人。这些模块位于``akka-contrib``子项目中: 15 | 16 | * [外部贡献](contrib.md)TODO -------------------------------------------------------------------------------- /2.3.6/scala/chapter9/01_building_akka.md: -------------------------------------------------------------------------------- 1 | # 构建Akka 2 | 3 | > 注:本节未经校验,如有问题欢迎提issue 4 | 5 | 此页介绍如何从最新的源代码构建和运行Akka。 6 | 7 | ### 获取源代码 8 | 9 | Akka使用 [Git](http://git-scm.com) 并托管于[Github](http://github.com)。 10 | 11 | 你首先需要在你的计算机上安装了 Git。然后你可以从http://github.com/akka/akka源代码存储库克隆。 12 | 13 | 举个例子: 14 | 15 | git clone git://github.com/akka/akka.git 16 | 17 | 如果你以前已经被克隆存储库,则你可以使用``git pull``更新代码: 18 | 19 | ### sbt-简单生成工具 20 | Akka使用优秀的 [sbt](https://github.com/harrah/xsbt) 构建系统。所以你要做的第一件事是要下载并安装sbt。你可以在 [sbt 安装文档](https://github.com/harrah/xsbt/wiki/Setup)阅读更多。 21 | 22 | 所有你需要构建Akka的 sbt 命令会在下面介绍。如果你想要了解更多有关 sbt 的内容,并在自己项目中使用它,请阅读 [sbt 文档](https://github.com/harrah/xsbt/wiki)。 23 | 24 | Akka sbt 构建文件是 ``project/AkkaBuild.scala``。 25 | 26 | ### 构建Akka 27 | 首先请确保你在Akka代码目录中: 28 | 29 | cd akka 30 | 31 | ##### 构建 32 | 要编译的Akka核心模块使用``compile``命令: 33 | 34 | sbt compile 35 | 36 | 可以使用``test``命令来运行所有测试: 37 | 38 | sbt test 39 | 40 | 如果编译和测试成功然,则你就会拥有一份可以工作的Akka最新的开发版本。 41 | 42 | ##### 并行执行 43 | 44 | 默认情况下测试按顺序执行。他们可以并行执行来减少构建时间,如果硬件能控制更大的内存和 cpu 使用率。将以下系统属性添加到sbt的启动脚本来激活并行执行: 45 | 46 | -Dakka.parallelExecution=true 47 | 48 | ##### 长时间运行和时间敏感试验 49 | 默认情况下长时间运行的测试(主要是群集测试)和时间敏感测试 (取决于运行它的机器的性能) 是禁用的。你可以通过添加以下标志启用它们: 50 | 51 | -Dakka.test.tags.include=long-running 52 | -Dakka.test.tags.include=timing 53 | 54 | 或者如果你需要启用两者: 55 | 56 | -Dakka.test.tags.include=long-running,timing 57 | 58 | ##### 发布到Ivy本地存储库 59 | 如果你想要将项目部署到Ivy本地资源库 (例如,从 sbt 项目中使用), 使用``publish-local``命令: 60 | 61 | sbt publish-local 62 | 63 | > 注意 64 | 65 | > Akka使用 ScalaDoc 为 API 文档生成类图。这需要安装 Graphviz 软件包的``dot``命令来避免错误。你可以通过添加``-Dakka.scaladoc.diagrams=false``标志来禁用图生成 66 | 67 | ##### sbt 交互模式 68 | 请注意在上面的例子我们调用 ``sbt compile`` 和 ``sbt test``等等,但sbt也有一种互动的模式。如果你键入``sbt``就进入了 sbt 交互式提示符,并可以直接输入命令。这节省了为每个命令启动一个新的 JVM 实例的开销,从而可以更快、更方便。 69 | 70 | 例如,Akka构建一般是这样做的: 71 | 72 | % sbt 73 | [info] Set current project to default (in build file:/.../akka/project/plugins/) 74 | [info] Set current project to akka (in build file:/.../akka/) 75 | > compile 76 | ... 77 | > test 78 | ... 79 | 80 | ##### sbt 批处理模式 81 | 也可以在单个调用中组合命令。例如,可以像这样测试和发布Akka到本地的Ivy资源库中: 82 | 83 | sbt test publish-local 84 | 85 | ### 依赖 86 | 你可以查看通过``sbt update``创建的Ivy依赖解析信息,并在 ``~/.ivy2/cache``中找到。例如,``~/.ivy2/cache/com.typesafe.akka-akka-remote-compile.xml`` 文件包含Akka远程模块编译依赖的解析信息。如果在 web 浏览器中打开此文件,你会得到一个易于导航的依赖关系视图。 87 | 88 | 89 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter9/02_multi_jvm_testing.md: -------------------------------------------------------------------------------- 1 | # 多JVM测试 2 | 3 | > 注:本节未经校验,如有问题欢迎提issue 4 | 5 | 同时在多个 Jvm 中运行应用程序 (main方法的对象) 和 ScalaTest 测试的支持。对于需要多个系统相互沟通的集成测试很有用。 6 | 7 | ### 安装程序 8 | 多JVM测试是 sbt 插件,你可以在 http://github.com/typesafehub/sbt-multi-jvm 找到。 9 | 10 | 你可以作为一个插件添加它,在 project/plugins.sbt 添加以下内容: 11 | 12 | addSbtPlugin ("com.typesafe.sbt"%"sbt 多 jvm"%"0.3.8") 13 | 14 | 然后,你可以通过在``build.sbt`` 或 ``project/Build.scala``包含``MultiJvm``和设置添加多JVM 测试。请注意 MultiJvm 测试源代码位于 ``src/multi-jvm/...``而不是在``src/test/...``。 15 | 16 | 下面是使用 MultiJvm 插件的 sbt 0.13 下的 build.sbt 文件示例: 17 | 18 | ```scala 19 | import com.typesafe.sbt.SbtMultiJvm 20 | import com.typesafe.sbt.SbtMultiJvm.MultiJvmKeys.MultiJvm 21 | 22 | val akkaVersion = "2.3.6" 23 | 24 | val project = Project( 25 | id = "akka-sample-multi-node-scala", 26 | base = file("."), 27 | settings = Project.defaultSettings ++ SbtMultiJvm.multiJvmSettings ++ Seq( 28 | name := "akka-sample-multi-node-scala", 29 | version := "2.3.6", 30 | scalaVersion := "2.10.4", 31 | libraryDependencies ++= Seq( 32 | "com.typesafe.akka" %% "akka-remote" % akkaVersion, 33 | "com.typesafe.akka" %% "akka-multi-node-testkit" % akkaVersion, 34 | "org.scalatest" %% "scalatest" % "2.0" % "test"), 35 | // make sure that MultiJvm test are compiled by the default test compilation 36 | compile in MultiJvm <<= (compile in MultiJvm) triggeredBy (compile in Test), 37 | // disable parallel tests 38 | parallelExecution in Test := false, 39 | // make sure that MultiJvm tests are executed by the default test target, 40 | // and combine the results from ordinary test and multi-jvm tests 41 | executeTests in Test <<= (executeTests in Test, executeTests in MultiJvm) map { 42 | case (testResults, multiNodeResults) => 43 | val overall = 44 | if (testResults.overall.id < multiNodeResults.overall.id) 45 | multiNodeResults.overall 46 | else 47 | testResults.overall 48 | Tests.Output(overall, 49 | testResults.events ++ multiNodeResults.events, 50 | testResults.summaries ++ multiNodeResults.summaries) 51 | } 52 | ) 53 | ) configs (MultiJvm) 54 | ``` 55 | 56 | 你可以为分支 Jvm 指定 JVM 选项: 57 | 58 | jvmOptions in MultiJvm := Seq("-Xmx256M") 59 | 60 | ### 运行测试 61 | 多JVM任务是类似于正常的任务:``test``, ``test-only`` 和``run``,但在``multi-jvm``配置下。 62 | 63 | 所以在Akka中,要运行akka-remote 中的所有多JVM测试(在sbt 提示符中): 64 | 65 | akka-remote-tests/multi-jvm:test 66 | 67 | 或可以首先修改``akka-remote-tests``项目,然后运行测试: 68 | 69 | project akka-remote-tests 70 | multi-jvm:test 71 | 72 | 使用``test-only``运行单个测试: 73 | 74 | multi-jvm:test-only akka.remote.RandomRoutedRemoteActor 75 | 76 | 可以列出多个测试名称来运行多个特定的测试。使用sbt的 tab 键可以很容易地完成测试的名称。 77 | 78 | 也可以通过在测试名称后和``--``包括这些选项,来指定 JVM 选项为``test-only``。举个例子: 79 | 80 | multi-jvm:test-only akka.remote.RandomRoutedRemoteActor -- -Dsome.option=something 81 | 82 | ### 创建应用程序测试 83 | 84 | 测试通过一种命名约定被发现并结合起来。MultiJvm 测试源代码位于``src/multi-jvm/...``。测试按以下模式命名: 85 | 86 | {TestName}MultiJvm{NodeName} 87 | 88 | 也就是,每个测试在其名字中有``MultiJvm``。前面的部分将测试/应用划分在单个``TestName``组下并将一起运行。后面的部分``NodeName``,是为每个分叉的 JVM分配的不同的名称。 89 | 90 | 因此若要创建名为``Sample``的3-节点测试,你可以如下创建三个应用程序: 91 | 92 | ```scala 93 | package sample 94 | 95 | object SampleMultiJvmNode1 { 96 | def main(args: Array[String]) { 97 | println("Hello from node 1") 98 | } 99 | } 100 | 101 | object SampleMultiJvmNode2 { 102 | def main(args: Array[String]) { 103 | println("Hello from node 2") 104 | } 105 | } 106 | 107 | object SampleMultiJvmNode3 { 108 | def main(args: Array[String]) { 109 | println("Hello from node 3") 110 | } 111 | } 112 | ``` 113 | 114 | 当你在sbt命令行中调用``multi-jvm:run sample.Sample``,会产生三个 Jvm,分别用于每个节点。看起来会像这样: 115 | 116 | > multi-jvm:run sample.Sample 117 | ... 118 | [info] * sample.Sample 119 | [JVM-1] Hello from node 1 120 | [JVM-2] Hello from node 2 121 | [JVM-3] Hello from node 3 122 | [success] Total time: ... 123 | 124 | ### 更改默认设置 125 | 你可以通过在项目中添加以下配置来更改多JVM测试的源代码目录的名称: 126 | 127 | unmanagedSourceDirectories in MultiJvm <<= 128 | Seq(baseDirectory(_ / "src/some_directory_here")).join 129 | 130 | 你可以更改``MultiJvm``标识符。例如,使用 ``multiJvmMarker`` 设置更改它为``ClusterTest`` : 131 | 132 | multiJvmMarker in MultiJvm := "ClusterTest" 133 | 134 | 现在,你的测试应该命名为 ``{TestName}ClusterTest{NodeName}``。 135 | 136 | ### JVM 实例配置 137 | 你可以为每个生成的 Jvm定义特定 JVM 选项。通过创建一个以节点的名字命名的带有``.opts``后缀的文件,把它们放在测试的同一个目录中。 138 | 139 | 例如,为``SampleMultiJvmNode1``提供 JVM 选项``-Dakka.remote.port=9991`` 和``-Xmx256m``,让我们创建三个 ``*.opts`` 文件并向其中添加选项。使用空格分隔多个选项。 140 | 141 | 142 | ``SampleMultiJvmNode1.opts``: 143 | 144 | -Dakka.remote.port=9991 -Xmx256m 145 | 146 | ``SampleMultiJvmNode2.opts``: 147 | 148 | -Dakka.remote.port=9992 -Xmx256m 149 | 150 | ``SampleMultiJvmNode3.opts``: 151 | 152 | -Dakka.remote.port=9993 -Xmx256m 153 | 154 | ### ScalaTest 155 | 除了应用程序外,它还支持创建 ScalaTest 测试。要这样做,要如上所述使用相同的命名约定,但创建 ScalaTest 套件,而不是对象的main方法。你需要在类路径上有 ScalaTest。这里是一个类似于上面例子的ScalaTest代码: 156 | 157 | package sample 158 | 159 | import org.scalatest.WordSpec 160 | import org.scalatest.matchers.MustMatchers 161 | 162 | class SpecMultiJvmNode1 extends WordSpec with MustMatchers { 163 | "A node" should { 164 | "be able to say hello" in { 165 | val message = "Hello from node 1" 166 | message must be("Hello from node 1") 167 | } 168 | } 169 | } 170 | 171 | class SpecMultiJvmNode2 extends WordSpec with MustMatchers { 172 | "A node" should { 173 | "be able to say hello" in { 174 | val message = "Hello from node 2" 175 | message must be("Hello from node 2") 176 | } 177 | } 178 | } 179 | 180 | 你需要在sbt提示中运行``multi-jvm:test-only sample.Spec``来执行这些测试。 181 | 182 | ### 多节点添加 183 | 此外对``SbtMultiJvm``插件有一些补充,以适应[实验模块](../chapter8/experimental_modules.md)一节中描述的[多节点测试](../chapter8/02_multi_node_testing.md)。 184 | 185 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter9/03_io_layer_design.md: -------------------------------------------------------------------------------- 1 | # I/O层设计 2 | 3 | > 注:本节未经校验,如有问题欢迎提issue 4 | 5 | ``akka.io`` 包已由Akka和[``spray.io``](spray.io) 团队协作开发。其设计采用``spray-io`` 模块的开发经验,并加以改进为更一般基于actor的服务使用。 6 | 7 | ### 要求 8 | 为了形成通用的可扩展的IO层基础,使之适合于广泛的应用,在Akka remoting 和spray HTTP 是原有基础上,为设计的关键驱动因素建立了以下要求: 9 | 10 | * 数以百万计的并发连接的可扩展性 11 | 12 | * 从数据输入通道到进入目标actor邮箱要有最低可能的延迟 13 | 14 | * 最大的吞吐量 15 | 16 | * 在两个方向的可选back-pressure (即在议定允许的地方对本地发送者限流,同时允许本地读者对远程发送者限流) 17 | 18 | * 一个纯粹基于actor的 API 和不可变的数据表示形式 19 | 20 | * 通过很瘦的SPI集成新运输方式的可扩展性;目标是不会强迫迫I/O 机制到最低共同标准,而是相反,完全允许特定协议的用户级API。 21 | 22 | ### 基本体系结构 23 | 每个传输实现,可作为一个单独的Akka扩展,提供一个`ActorRef`代表联系客户端代码的初始点。这个"管理器"可接受请求建立一个通信通道 (例如连接或侦听一个TCP套接字)。每个通信通道都由一个特定actor代表,暴露给客户端代码,在其整个生命周期服务于与此通道的所有交互。 24 | 25 | 实现的核心要素是传输特定"selector"的actor ;例如TCP中它将包装一个`java.nio.channels.Selector`。通道actor通过发送相应消息到其指定的选择器actor,来注册其感兴趣的渠道的读或写。然而,实际的通道读写是由通道actor自己完成的,这样将选择器actor从耗时的任务中解放出来,从而保证了低延迟。选择器actor唯一的责任是管理的底层的选择器的键集合和实际选择操作,这是唯一会阻塞的操作。 26 | 27 | 通道到选择器的指定由管理actor操作。并且在通道的整个生存期内都保持不变。从而管理actor基于一些特定于实现的分配逻辑在一个或多个选择器actor中 "编制(stripes)" 新渠道。这种逻辑可能 (部分地) 委派给选择器actor,例如,当他们认为自己有能力处理的时候可以选择拒绝被指定一个新渠道。 28 | 29 | 管理actor创建 (并因此监督) 选择器actor,它们相应地创建并监督其频道actor。某一单一传输实现的actor层次结构因此包含三个截然不同的actor层次,管理actor在顶部,通道actor在叶子节点,选择器actor在中间。 30 | 31 | 背压(Back-pressure)输出通过允许用户能够在其`Write`消息中指定它是否想收到会写入操作系统内核的排队确认消息来实现。背压输入通过向通道actor发送消息,暂时禁用通道的阅读兴趣,直到通过相应的恢复命令重新启用读操作来实现。在流量控制的运输情况下 ——例如 TCP —— 在接收端不消费数据的行为 (从而使数据保持在内核读取缓冲区中) 会传播回给发送者,跨网络链接这两个机制。 32 | 33 | ### 设计的好处 34 | 整个实现保持在actor模型内,允许我们删除显式线程处理逻辑的需要,同时也意味着有没有涉及锁 (除了那些底层传输工具库的部分)。只编写actor代码会使实现更加简洁,同时Akka高效的actor消息传递没有对这一好处带来很大的开销。事实上 I/O 基于事件的性质能很好地映射到actor模型,在此模型中我们期望明确的性能和可伸缩性优势,而不是传统的解决方案的显式线程管理和同步。 35 | 36 | 监督层次结构的另一个好处是,清理资源是自然而然的: 关闭一个选择器的actor会自动清理所有通道actor,允许通道的恰当关闭,并将适当的消息发送到用户级客户端actor。DeathWatch允许通道actor注意到其用户级别的处理器actor的消亡,并在这种情况下也以一种有序的方式终止 ;这自然就减少了泄露未关闭通道的可能性。 37 | 38 | 使用 `ActorRef` 暴露所有功能的选择,确保了这些引用可以被自由的分发和代理,并在用户认为合适的时候处理一般情况,包括使用远程处理和生命周期监测(只是随便列出两个)。 39 | 40 | ### 怎样去添加一个新的传输 41 | 最好的开始是研究 TCP 引用的实现,从中可以良好的获取其基本工作原理,然后设计和实施,对新的协议是类似的,但也会有问题。有 I/O 机制之间差异巨大 (例如比较文件 I/O 和消息代理) ,此 I/O 层的目标是明确**不能**把他们都硬塞进一个统一的 API,这就是为什么只有基本体系结构的思想记录在这里。 42 | 43 | 44 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter9/04_developer_guidelines.md: -------------------------------------------------------------------------------- 1 | # 开发指南 2 | 3 | > 注:本节未经校验,如有问题欢迎提issue 4 | 5 | > 注意 6 | 7 | > 首先阅读[Akka贡献者指南](https://github.com/akka/akka/blob/master/CONTRIBUTING.md)。 8 | 9 | ### 代码风格 10 | Akka代码风格遵循 Scala 风格指南。唯一的例外是块注释的样式: 11 | 12 | ```scala 13 | /** 14 | * Style mandated by "Scala Style Guide" 15 | */ 16 | 17 | /** 18 | * Style adopted in the Akka codebase 19 | */ 20 | ``` 21 | 22 | Akka使用 ``Scalariform`` 作为构建的一部分的格式化源代码。所以随便修改,然后运行的 ``sbt compile``,它将重新格式化为Akka标准代码。 23 | 24 | ### 过程 25 | 26 | * 请确保你已经签署了Akka CLA,如果没有,在[这里签署](http://www.typesafe.com/contribute/cla)。 27 | * 选择一个ticket,如果没有适合你的就创建一个。 28 | * 首先在功能分支工作。类似``wip---``这样命名。 29 | * 当你完成后,创建一个 GitHub Pull-Request 到目标分支,并且向Akka邮件列表发送邮件表示你希望它被审阅。 30 | * 审查达成一致后,Akka核心团队将对它进行合并。 31 | 32 | ### 提交消息 33 | 请按照如下指导方针创建公共提交和编写提交消息。 34 | 35 | 1. 如果你的工作跨越多个本地提交 (例如 ; 如果你在主题分支工作时的安全点提交,或在长时间工作分支做合并/rebase 等)则请**不要**提交所有,而是重写历史,将多个提交挤压到单个大提交中,并在此编写良好的提交消息(如下讨论)。有[一篇好的文章](http://sandofsky.com/blog/git-workflow.html)介绍了如何做到这一点。每个提交都应该是能够用于隔离、cherry picked等。 36 | 37 | 2. 第一行应该是一个描述性的句子,说明提交在做什么。应该达到只是读这一行就能够充分了解提交做了什么。它**不是**只列出ticket编号、打入"次要修复"或类似的话。在第一行末尾加上以`#`开头的ticket编号。如果提交是一个小的修复程序,则已完成。否则请看下一条。 38 | 39 | 3. 单行描述之后应该是一个空行,然后跟一个提交细节的枚举列表。 40 | 41 | 示例: 42 | 43 | Completed replication over BookKeeper based transaction log. Fixes #XXX 44 | 45 | * Details 1 46 | * Details 2 47 | * Details 3 48 | 49 | ### 测试 50 | 签入的所有代码都**应该**有测试。所有的测试都是用``ScalaTest`` 和 ``ScalaCheck``编写。 51 | 52 | * 命名测试为 **Test.scala**,如果他们不依赖于任何外部的东西。这使得必经之快乐。 53 | * 命名测试为 **Spec.scala**,如果他们具有外部依赖项。 54 | 55 | ##### Actor测试工具包 56 | 测试actor的有用套件:[akka.util.TestKit](http://github.com/akka/akka/tree/v2.3.6/akka-testkit/src/main/scala/akka/testkit/TestKit.scala)。它提供了确认收到的答复及其时间的断言,更多文档参考[测试actor系统模块](../chapter3/09_testing_actor_systems.md)中。 57 | 58 | ##### 多JVM测试 59 | 包含在示例中的是一个多 jvm 测试的 sbt 特质,将分枝 Jvm用于多节点测试。它支持运行应用程序 (含main方法的对象) 和运行 ScalaTest 测试。 60 | 61 | ##### NetworkFailureTest 62 | 你可以使用 'NetworkFailureTest' 特质来测试网络故障。 -------------------------------------------------------------------------------- /2.3.6/scala/chapter9/05_documentation_guidelines.md: -------------------------------------------------------------------------------- 1 | # 文档指南 2 | 3 | 4 | The Akka documentation uses `reStructuredText`_ as its markup language and is 5 | built using `Sphinx`_. 6 | 7 | .. _reStructuredText: http://docutils.sourceforge.net/rst.html 8 | .. _sphinx: http://sphinx.pocoo.org 9 | 10 | 11 | Sphinx 12 | ====== 13 | 14 | For more details see `The Sphinx Documentation `_ 15 | 16 | reStructuredText 17 | ================ 18 | 19 | For more details see `The reST Quickref `_ 20 | 21 | Sections 22 | -------- 23 | 24 | Section headings are very flexible in reST. We use the following convention in 25 | the Akka documentation: 26 | 27 | * ``#`` (over and under) for module headings 28 | * ``=`` for sections 29 | * ``-`` for subsections 30 | * ``^`` for subsubsections 31 | * ``~`` for subsubsubsections 32 | 33 | 34 | Cross-referencing 35 | ----------------- 36 | 37 | Sections that may be cross-referenced across the documentation should be marked 38 | with a reference. To mark a section use ``.. _ref-name:`` before the section 39 | heading. The section can then be linked with ``:ref:`ref-name```. These are 40 | unique references across the entire documentation. 41 | 42 | For example:: 43 | 44 | .. _akka-module: 45 | 46 | ############# 47 | Akka Module 48 | ############# 49 | 50 | This is the module documentation. 51 | 52 | .. _akka-section: 53 | 54 | Akka Section 55 | ============ 56 | 57 | Akka Subsection 58 | --------------- 59 | 60 | Here is a reference to "akka section": :ref:`akka-section` which will have the 61 | name "Akka Section". 62 | 63 | Build the documentation 64 | ======================= 65 | 66 | First install `Sphinx`_. See below. 67 | 68 | Building 69 | -------- 70 | 71 | For the html version of the docs:: 72 | 73 | sbt sphinx:generate-html 74 | 75 | open /akka-docs/target/sphinx/html/index.html 76 | 77 | For the pdf version of the docs:: 78 | 79 | sbt sphinx:generate-pdf 80 | 81 | open /akka-docs/target/sphinx/latex/AkkaJava.pdf 82 | or 83 | open /akka-docs/target/sphinx/latex/AkkaScala.pdf 84 | 85 | Installing Sphinx on OS X 86 | ------------------------- 87 | 88 | Install `Homebrew `_ 89 | 90 | Install Python and pip: 91 | 92 | :: 93 | 94 | brew install python 95 | /usr/local/share/python/easy_install pip 96 | 97 | Add the Homebrew Python path to your $PATH: 98 | 99 | :: 100 | 101 | /usr/local/Cellar/python/2.7.5/bin 102 | 103 | 104 | More information in case of trouble: 105 | https://github.com/mxcl/homebrew/wiki/Homebrew-and-Python 106 | 107 | Install sphinx: 108 | 109 | :: 110 | 111 | pip install sphinx 112 | 113 | Add sphinx_build to your $PATH: 114 | 115 | :: 116 | 117 | /usr/local/share/python 118 | 119 | Install BasicTeX package from: 120 | http://www.tug.org/mactex/morepackages.html 121 | 122 | Add texlive bin to $PATH: 123 | 124 | :: 125 | 126 | /usr/local/texlive/2013basic/bin/universal-darwin 127 | 128 | Add missing tex packages: 129 | 130 | :: 131 | 132 | sudo tlmgr update --self 133 | sudo tlmgr install titlesec 134 | sudo tlmgr install framed 135 | sudo tlmgr install threeparttable 136 | sudo tlmgr install wrapfig 137 | sudo tlmgr install helvetic 138 | sudo tlmgr install courier 139 | sudo tlmgr install multirow 140 | 141 | If you get the error "unknown locale: UTF-8" when generating the documentation the solution is to define the following environment variables: 142 | 143 | :: 144 | 145 | export LANG=en_US.UTF-8 146 | export LC_ALL=en_US.UTF-8 147 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter9/06_team.md: -------------------------------------------------------------------------------- 1 | # 团队 2 | 3 | =================== ========================== 4 | Name Role 5 | =================== ========================== 6 | Jonas Bonér Founder, Despot, Committer 7 | Viktor Klang Honorary Member 8 | Roland Kuhn Project Lead 9 | Patrik Nordwall Core Team 10 | Björn Antonsson Core Team 11 | Endre Varga Core Team 12 | Mathias Doenitz Committer 13 | Johannes Rudolph Committer 14 | Raymond Roestenburg Committer 15 | Piotr Gabryanczyk Committer 16 | Helena Edelson Committer 17 | Martin Krasser Committer 18 | Henrik Engström Alumnus 19 | Peter Vlugter Alumnus 20 | Derek Williams Alumnus 21 | Debasish Ghosh Alumnus 22 | Ross McDonald Alumnus 23 | Eckhart Hertzler Alumnus 24 | Mikael Högqvist Alumnus 25 | Tim Perrett Alumnus 26 | Jeanfrancois Arcand Alumnus 27 | Jan Van Besien Alumnus 28 | Michael Kober Alumnus 29 | Peter Veentjer Alumnus 30 | Irmo Manie Alumnus 31 | Heiko Seeberger Alumnus 32 | Hiram Chirino Alumnus 33 | Scott Clasen Alumnus 34 | =================== ========================== 35 | -------------------------------------------------------------------------------- /2.3.6/scala/chapter9/information_for_akka_developers.md: -------------------------------------------------------------------------------- 1 | # Akka开发者信息 2 | -------------------------------------------------------------------------------- /2.3.6/scala/images/actor_lifecycle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/images/actor_lifecycle.png -------------------------------------------------------------------------------- /2.3.6/scala/images/akka-remote-testconductor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/images/akka-remote-testconductor.png -------------------------------------------------------------------------------- /2.3.6/scala/images/association_lifecycle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/images/association_lifecycle.png -------------------------------------------------------------------------------- /2.3.6/scala/images/benchmark-akka-sample-trading-throughput.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/images/benchmark-akka-sample-trading-throughput.png -------------------------------------------------------------------------------- /2.3.6/scala/images/build-path.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/images/build-path.png -------------------------------------------------------------------------------- /2.3.6/scala/images/camel-pubsub.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/images/camel-pubsub.png -------------------------------------------------------------------------------- /2.3.6/scala/images/camel-pubsub2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/images/camel-pubsub2.png -------------------------------------------------------------------------------- /2.3.6/scala/images/circuit-breaker-states.dot: -------------------------------------------------------------------------------- 1 | digraph circuit_breaker { 2 | rankdir = "LR"; 3 | size = "6,5"; 4 | graph [ bgcolor = "transparent" ] 5 | node [ fontname = "Helvetica", 6 | fontsize = 14, 7 | shape = circle, 8 | color = white, 9 | style = filled ]; 10 | edge [ fontname = "Helvetica", fontsize = 12 ] 11 | Closed [ fillcolor = green2 ]; 12 | "Half-Open" [fillcolor = yellow2 ]; 13 | Open [ fillcolor = red2 ]; 14 | Closed -> Closed [ label = "Success" ]; 15 | "Half-Open" -> Open [ label = "Trip Breaker" ]; 16 | "Half-Open" -> Closed [ label = "Reset Breaker" ]; 17 | Closed -> Open [ label = "Trip Breaker" ]; 18 | Open -> Open [ label = "Calls failing fast" ]; 19 | Open -> "Half-Open" [ label = "Attempt Reset" ]; -------------------------------------------------------------------------------- /2.3.6/scala/images/circuit-breaker-states.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/images/circuit-breaker-states.png -------------------------------------------------------------------------------- /2.3.6/scala/images/clojure-trees.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/images/clojure-trees.png -------------------------------------------------------------------------------- /2.3.6/scala/images/diagnostics-window.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/images/diagnostics-window.png -------------------------------------------------------------------------------- /2.3.6/scala/images/example-code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/images/example-code.png -------------------------------------------------------------------------------- /2.3.6/scala/images/faulttolerancesample-failure-flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/images/faulttolerancesample-failure-flow.png -------------------------------------------------------------------------------- /2.3.6/scala/images/faulttolerancesample-normal-flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/images/faulttolerancesample-normal-flow.png -------------------------------------------------------------------------------- /2.3.6/scala/images/import-project.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/images/import-project.png -------------------------------------------------------------------------------- /2.3.6/scala/images/install-beta2-updatesite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/images/install-beta2-updatesite.png -------------------------------------------------------------------------------- /2.3.6/scala/images/member-states.drawing: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/images/member-states.drawing -------------------------------------------------------------------------------- /2.3.6/scala/images/member-states.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/images/member-states.png -------------------------------------------------------------------------------- /2.3.6/scala/images/more.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/images/more.png -------------------------------------------------------------------------------- /2.3.6/scala/images/phi1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/images/phi1.png -------------------------------------------------------------------------------- /2.3.6/scala/images/phi2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/images/phi2.png -------------------------------------------------------------------------------- /2.3.6/scala/images/phi3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/images/phi3.png -------------------------------------------------------------------------------- /2.3.6/scala/images/pi-formula.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/images/pi-formula.png -------------------------------------------------------------------------------- /2.3.6/scala/images/quickfix.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/images/quickfix.png -------------------------------------------------------------------------------- /2.3.6/scala/images/run-config.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jasonqu/akka-doc-cn/691d6e6d25f57a8c4fbbb5aebd59ce591e24bc13/2.3.6/scala/images/run-config.png -------------------------------------------------------------------------------- /2.3.6/scala/images/tcp-message-protocol_bind-connect-maxed-out.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 2013-01-23 14:28ZCanvas 1Layer 1TcpManagerTcpSelectorUser ActorBind(…) / Connect(…)Maximum number of channels registered with TcpSelectorsCommandFailed(command)**Maximum number of channels registered with TcpSelectorsBind/Connect when max Capacity is reached(via Router)Retry(command, retriesLeft)*(via Router)* if retriesLeft > 0** if retriesLeft == 0 4 | -------------------------------------------------------------------------------- /2.3.6/scala/images/tcp-message-protocol_closing.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 2013-01-23 14:28ZCanvas 1Layer 1Connection EstablishedUser ActorTcpConnectionClosed / ConfirmedClosed / AbortedNo Connection EstablishedClose / ConfirmedClose / AbortClosing a Connection 4 | -------------------------------------------------------------------------------- /2.3.6/scala/images/tcp-message-protocol_noticing-close.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 2013-01-23 14:28ZCanvas 1Layer 1Connection EstablishedHandlerTcpConnectionClosed / ConfirmedClosed / Aborted / PeerClosed / ErrorClosed(cause)No Connection EstablishedNoticing that a Connection was closed 4 | -------------------------------------------------------------------------------- /2.3.6/scala/images/tcp-message-protocol_receiving.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 2013-01-23 14:28ZCanvas 1Layer 1Connection EstablishedTcpSelectorHandlerTcpConnectionChannelReadableReadInterestReceived(data)Connection EstablishedReceiving Data from a Connection 4 | -------------------------------------------------------------------------------- /2.3.6/scala/images/tcp-message-protocol_unbinding.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 2013-01-22 22:05ZCanvas 1Layer 1User ActorUnboundUnbindServer BoundTcpListenerServer UnboundUnbinding a Server 4 | -------------------------------------------------------------------------------- /2.3.6/scala/images/tcp-message-protocol_writing.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 2013-01-23 14:28ZCanvas 1Layer 1Connection EstablishedTcpSelectorUser ActorTcpConnectionChannelWriteable**WriteInterest**ck***Connection EstablishedWrite(data, ack)Writing to a Connection* if a preceding write is still uncompleted** if all preceding writes have been completed*** if the write has been completed successfully and write.ack != Tcp.NoAck CommandFailed(write)* 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | akka文档中文翻译 2 | =========== 3 | 4 | 该文档是[Akka官方文档](http://akka.io/docs)的中文翻译。使用[Gitbook](https://www.gitbook.io/)制作。 5 | 6 | 本文大量参考了[上海广谈信息技术有限公司](http://www.gtan.com/)的[《Akka 2.0文档》](http://www.gtan.com/welfare04.html)。 7 | [广谈公益](http://www.gtan.com/welfare.html)还有很多优秀的资源,如感兴趣请移步参考。 8 | 9 | ### 贡献力量 10 | 11 | 欢迎大家对该文档贡献力量,提出[宝贵意见](../../issues),修改并提交[Pull Requests](../../pulls)。 12 | 13 | 如果对scala和akka感兴趣,欢迎加入“无水scala群”:231809997,有各路scala高手帮你释疑。 14 | 15 | 对贡献的要求是保持术语和代码的一致 16 | 17 | * **术语的一致**:以[《Akka 2.0文档》](http://www.gtan.com/welfare04.html)的术语为准,如果有更好的选择,欢迎[提出issue](../../issues) 18 | * **代码的一致**:书的内容放在`版本号/语言/`目录下,如`2.3.6/scala/`,生成的html文件放在`版本号/语言/book/`目录下。如非必要,不要提交其他无关内容或生成的内容。 19 | 20 | ### 翻译进度与状态 21 | 22 | ##### 2.3.6 scala 23 | 24 | * [x] Introduction 25 | * [x] 引言 26 | * [x] Akka是什么? 27 | * [x] 为什么使用Akka? 28 | * [x] 入门 29 | * [x] 必修的“Hello World” 30 | * [x] 用例和部署场景 31 | * [x] Akka使用实例 32 | * [x] 概述 33 | * [x] 术语,概念 34 | * [x] Actor系统 35 | * [x] 什么是Actor? 36 | * [x] 监管与监控 37 | * [x] Actor引用, 路径与地址 38 | * [x] 位置透明性 39 | * [x] Akka与Java内存模型 40 | * [x] 消息发送语义 41 | * [x] 配置 42 | * [x] Actors 43 | * [x] Actors 44 | * [x] 类型Actor 45 | * [x] 容错 46 | * [x] 调度器 47 | * [x] 邮箱 48 | * [x] 路由 49 | * [x] 有限状态机(FSM) 50 | * [x] 持久化 51 | * [x] 测试Actor系统 52 | * [x] Actor DSL 53 | * [ ] Futures与Agents 54 | * [ ] Futures (翻译完成,待校验) 55 | * [ ] Agents (翻译完成,待校验) 56 | * [ ] 网络 57 | * [ ] 集群规格 58 | * [ ] 集群用法 59 | * [ ] 远程 (翻译完成,待校验) 60 | * [ ] 序列化 (翻译完成,待校验) 61 | * [ ] I/O (翻译完成,待校验) 62 | * [ ] 使用TCP (翻译完成,待校验) 63 | * [ ] 使用UDP (翻译完成,待校验) 64 | * [ ] ZeroMQ (翻译完成,待校验) 65 | * [ ] Camel 66 | * [ ] 实用工具 67 | * [ ] 事件总线 (翻译完成,待校验) 68 | * [ ] 日志 (翻译完成,待校验) 69 | * [ ] 调度器 (翻译完成,待校验) 70 | * [ ] Duration (翻译完成,待校验) 71 | * [ ] 线路断路器 (翻译完成,待校验) 72 | * [ ] Akka扩展 (翻译完成,待校验) 73 | * [ ] 微内核 (翻译完成,待校验) 74 | * [ ] 如何使用:常用模式 (翻译完成,待校验) 75 | * [ ] 消息限流 76 | * [ ] 跨节点平衡工作负载 77 | * [ ] 工作拉取模式,来限流和分发工作,防止邮箱溢出 78 | * [ ] 顺序终止 79 | * [ ] Akka AMQP代理 80 | * [ ] Akka 2中的关闭模式 81 | * [ ] 使用Akka做分布式(内存)图像处理 82 | * [ ] 案例分析:一个使用Actor的自动更新缓存 83 | * [ ] 使用蜘蛛模式发现actor系统的消息流向 84 | * [ ] 周期信息调度 85 | * [ ] 模板模式 86 | * [ ] 实验模块 87 | * [x] 持久化 88 | * [ ] 多节点测试 (翻译完成,待校验) 89 | * [ ] Actors(使用Java的Lambda支持) not supported 90 | * [ ] FSM(使用Java的Lambda支持) not supported 91 | * [ ] 外部贡献 (翻译完成,待校验) 92 | * [ ] Akka开发者信息 93 | * [ ] 构建Akka (翻译完成,待校验) 94 | * [ ] 多JVM测试 (翻译完成,待校验) 95 | * [ ] I/O层设计 (翻译完成,待校验) 96 | * [ ] 开发指南 (翻译完成,待校验) 97 | * [ ] 文档指南 not supported 98 | * [ ] 团队 not supported 99 | * [ ] 工程信息 100 | * [ ] 迁移指南 not supported 101 | * [ ] 问题追踪 not supported 102 | * [ ] 许可证 not supported 103 | * [ ] 赞助商 not supported 104 | * [ ] 项目 not supported 105 | * [ ] 附加信息 106 | * [ ] 常见问题 (翻译完成,待校验) 107 | * [ ] 图书 not supported 108 | * [ ] 其他语言绑定 not supported 109 | * [ ] Akka与OSGi not supported 110 | * [ ] 部分HTTP框架名单 not supported 111 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Akka中文文档 8 | 9 | 10 | 11 | 12 | 16 | 17 | 27 | 28 | 29 | 30 | 31 | 38 | 39 |
40 | 41 |
42 |

Akka 2.3.6 (current stable release) for Scala 2.10 and 2.11

43 |
HTML for Java and Scala
44 |
45 |
46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | --------------------------------------------------------------------------------