WillemJiang closed pull request #135: SCB-330 add user guide and Chinese version of docs URL: https://github.com/apache/incubator-servicecomb-saga/pull/135
This is a PR merged from a forked repository. As GitHub hides the original diff on merge, it is displayed below for the sake of provenance: As this is a foreign pull request (from a fork), the diff is supplied below (as it won't show otherwise due to GitHub magic): diff --git a/README.md b/README.md index e8e62a21..aa9b8400 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Saga [![Build Status](https://travis-ci.org/apache/incubator-servicecomb-saga.svg?branch=master)](https://travis-ci.org/apache/incubator-servicecomb-saga?branch=master) [![Coverage Status](https://coveralls.io/repos/github/apache/incubator-servicecomb-saga/badge.svg?branch=master)](https://coveralls.io/github/apache/incubator-servicecomb-saga?branch=master) [![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html) +# Saga | [??](README_ZH.md) [![Build Status](https://travis-ci.org/apache/incubator-servicecomb-saga.svg?branch=master)](https://travis-ci.org/apache/incubator-servicecomb-saga?branch=master) [![Coverage Status](https://coveralls.io/repos/github/apache/incubator-servicecomb-saga/badge.svg?branch=master)](https://coveralls.io/github/apache/incubator-servicecomb-saga?branch=master) [![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html) Apache ServiceComb (incubating) Saga is an eventually data consistency solution for micro-service applications. Transactions are commited directly in the try phase and compensated in reverse order in the rollback phase comparing to [TCC](http://design.inf.usi.ch/sites/default/files/biblio/rest-tcc.pdf). ## Features @@ -22,6 +22,9 @@ See [Saga Pack Design](docs/design.md) for details. If you are interested in our ## Get Started See [Booking Demo](saga-demo/pack-demo/README.md) for details. +## User Guide +See [User Guide](docs/user_guide.md) for details. + ## Contact Us * [issues](https://issues.apache.org/jira/browse/SCB) * [gitter](https://gitter.im/ServiceCombUsers/Lobby) @@ -31,4 +34,4 @@ See [Booking Demo](saga-demo/pack-demo/README.md) for details. See [Pull Request Guide](http://servicecomb.incubator.apache.org/developers/submit-codes/) for details. ## License -Licensed under an [Apache 2.0](https://github.com/apache/incubator-servicecomb-saga/blob/master/LICENSE) license. +Licensed under an [Apache 2.0 license](https://github.com/apache/incubator-servicecomb-saga/blob/master/LICENSE). diff --git a/README_ZH.md b/README_ZH.md new file mode 100644 index 00000000..2ea467be --- /dev/null +++ b/README_ZH.md @@ -0,0 +1,37 @@ +# Saga | [English](README.md) [![Build Status](https://travis-ci.org/apache/incubator-servicecomb-saga.svg?branch=master)](https://travis-ci.org/apache/incubator-servicecomb-saga?branch=master) [![Coverage Status](https://coveralls.io/repos/github/apache/incubator-servicecomb-saga/badge.svg?branch=master)](https://coveralls.io/github/apache/incubator-servicecomb-saga?branch=master) [![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html) +Apache ServiceComb (incubating) Saga ????????????????????????[TCC](http://design.inf.usi.ch/sites/default/files/biblio/rest-tcc.pdf)????try???Saga??????????rollback???????????????? + +## ?? +* ??????????? +* ?????????????????????? +* ???????????gRPC????????????????Kyro???????????? +* ??????2-3??????????????????????? +* ????????Docker????? +* ???????????????????? + +## ?? +Saga?? **alpha** ? **omega**?????? +* alpha???????????????????????? +* omega??????????agent??????????????alpha??????? + +?????alpha, omega??????????? +![Saga Pack ??](docs/static_files/pack.png) + +?????[Saga Pack ????](docs/design_zh.md). ????Saga??????????????[???Saga??](docs/old_saga.md)????? + +## ???? +?????[??????](saga-demo/pack-demo/README.md)? + +## ???? +?????[????](docs/user_guide_zh.md)? + +## ???? +* [??issues](https://issues.apache.org/jira/browse/SCB) +* [gitter???](https://gitter.im/ServiceCombUsers/Lobby) +* ????: [??](mailto:dev-subscr...@servicecomb.incubator.apache.org) [??](https://lists.apache.org/list.html?dev@servicecomb.apache.org) + +## ?? +?????[??????](http://servicecomb.incubator.apache.org/cn/developers/submit-codes/)? + +## License +[Apache 2.0 license](https://github.com/apache/incubator-servicecomb-saga/blob/master/LICENSE)? diff --git a/alpha/alpha-server/src/test/java/org/apache/servicecomb/saga/alpha/server/AlphaIntegrationTest.java b/alpha/alpha-server/src/test/java/org/apache/servicecomb/saga/alpha/server/AlphaIntegrationTest.java index 497c2443..8b2672ce 100644 --- a/alpha/alpha-server/src/test/java/org/apache/servicecomb/saga/alpha/server/AlphaIntegrationTest.java +++ b/alpha/alpha-server/src/test/java/org/apache/servicecomb/saga/alpha/server/AlphaIntegrationTest.java @@ -389,6 +389,8 @@ public void abortTimeoutSagaStartedEvent() { assertThat(events.get(1).type(), is(TxAbortedEvent.name())); assertThat(events.get(2).type(), is(SagaEndedEvent.name())); + await().atMost(2, SECONDS).until(this::waitTillTimeoutDone); + assertThat(timeoutEntityRepository.count(), is(1L)); Iterable<TxTimeout> timeouts = timeoutEntityRepository.findAll(); timeouts.forEach(timeout -> { @@ -416,6 +418,8 @@ public void abortTimeoutTxStartedEvent() { assertThat(events.get(3).type(), is(TxCompensatedEvent.name())); assertThat(events.get(4).type(), is(SagaEndedEvent.name())); + await().atMost(2, SECONDS).until(this::waitTillTimeoutDone); + assertThat(timeoutEntityRepository.count(), is(1L)); Iterable<TxTimeout> timeouts = timeoutEntityRepository.findAll(); timeouts.forEach(timeout -> { @@ -425,6 +429,15 @@ public void abortTimeoutTxStartedEvent() { }); } + private boolean waitTillTimeoutDone() { + for (TxTimeout txTimeout : timeoutEntityRepository.findAll()) { + if (txTimeout.status().equals(DONE.name())) { + return true; + } + } + return false; + } + private GrpcAck onCompensation(GrpcCompensateCommand command) { return blockingStub.onTxEvent( eventOf(TxCompensatedEvent, diff --git a/docs/design.md b/docs/design.md index d976d1ad..7329b021 100644 --- a/docs/design.md +++ b/docs/design.md @@ -1,4 +1,5 @@ # Saga Pack Design +[![ZH doc](https://img.shields.io/badge/document-??-blue.svg)](design_zh.md) ## Overview Pack contains two components: *alpha* and *omega*. Alpha is the pack leader and backed by database to make sure transaction events stored permanently while omega is the pack worker and embedded inside services to intercept transaction invocation and report events to alpha. diff --git a/docs/design_zh.md b/docs/design_zh.md new file mode 100644 index 00000000..072565ae --- /dev/null +++ b/docs/design_zh.md @@ -0,0 +1,34 @@ +# Saga Pack ???? +[![EN doc](https://img.shields.io/badge/document-English-blue.svg)](design.md) +## ?? +Pack????????? **alpha** ? **omega**? +* alpha???????????????????????????????????????????????????????? +* omega??????????agent??????????????alpha????????????????alpha??????????????? + +![Pack Architecture](static_files/pack.png) + +## Omega?????? +omega??????????agent??????????omega????????????????????id??????????id??Saga??id?????????id??????id????????alpha??????????????????alpha????????????????????????????????????? + +![Omega Internal](static_files/omega_internal.png) + +## ??????? +?????????[Zipkin](https://github.com/openzipkin/zipkin)???????????omega???????????id?????????????????omega????????????id??????????????????????????????????????????????????? + +![Inter-Service Communication](static_files/inter-service_communication.png) + +## ?????? +### ???? +???????????????????????? + +![Successful Scenario](static_files/successful_scenario.png) + +### ???? +??????omega??alpha?????????alpha?????????????????????????????????????????????? + +![Exception Scenario](static_files/exception_scenario.png) + +### ???? +??????????????alpha?????????????????????????????????? + +![Timeout Scenario](static_files/timeout_scenario.png) diff --git a/docs/user_guide.md b/docs/user_guide.md new file mode 100644 index 00000000..a0d9db5d --- /dev/null +++ b/docs/user_guide.md @@ -0,0 +1,101 @@ +# Saga User Guide +[![ZH doc](https://img.shields.io/badge/document-??-blue.svg)](user_guide_zh.md) + +## Prerequisites +You will need: +1. [JDK 1.8][jdk] +2. [Maven 3.x][maven] +3. [Docker][docker] + +[jdk]: http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html +[maven]: https://maven.apache.org/install.html +[docker]: https://www.docker.com/get-docker + +## Build +To build: +```bash +$ git clone https://github.com/apache/incubator-servicecomb-saga.git +$ cd incubator-servicecomb-saga +$ mvn clean install -DskipTests -Pdocker +``` + +## How to use +### Add saga dependencies +```xml + <dependency> + <groupId>org.apache.servicecomb.saga</groupId> + <artifactId>omega-spring-starter</artifactId> + <version>0.0.3-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.apache.servicecomb.saga</groupId> + <artifactId>omega-transport-resttemplate</artifactId> + <version>0.0.3-SNAPSHOT</version> + </dependency> +``` + +### Add saga annotations and corresponding compensation methods +Take a transfer money application as an example: +1. add `@EnableOmega` at application entry to initialize omega configurations and connect to alpha + ```java + @SpringBootApplication + @EnableOmega + public class Application { + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + } + ``` + +2. add `@SagaStart` at the starting point of the global transaction + ```java + @SagaStart(timeout=10) + public boolean transferMoney(String from, String to, int amount) { + transferOut(from, amount); + transferIn(to, amount); + } + ``` + **Note:** By default, timeout is disable. + +3. add `@Compensable` at the sub-transaction and specify its corresponding compensation method + ```java + @Compensable(timeout=5, compensationMethod="cancel") + public boolean transferOut(String from, int amount) { + repo.reduceBalanceByUsername(from, amount); + } + + public boolean cancel(String from, int amount) { + repo.addBalanceByUsername(from, amount); + } + ``` + **Note:** By default, timeout is disable. + + **Note:** If the starting point of global transaction and local transaction overlaps, both `@SagaStart` and `@Compensable` are needed. + +4. Repeat step 3 for the `transferIn` service. + +## How to run +1. run postgreSQL. + ```bash + docker run -d -e "POSTGRES_DB=saga" -e "POSTGRES_USER=saga" -e "POSTGRES_PASSWORD=password" -p 5432:5432 postgres + ``` + +2. run alpha. Before running alpha, please make sure postgreSQL is already up. + ```bash + docker run -d -p 8090:8090 \ + -e "JAVA_OPTS=-Dspring.profiles.active=prd" \ + -e "spring.datasource.url=jdbc:postgresql://{docker.host.address}:5432/saga?useSSL=false" \ + alpha-server:0.0.3-SNAPSHOT + ``` + +3. setup omega. Configure the following values in `application.yaml`. + ```yaml + spring: + application: + name: {application.name} + alpha: + cluster: + address: {alpha.cluster.addresses} + ``` + +Then you can start your micro-services. diff --git a/docs/user_guide_zh.md b/docs/user_guide_zh.md new file mode 100644 index 00000000..6b8ce473 --- /dev/null +++ b/docs/user_guide_zh.md @@ -0,0 +1,100 @@ +# Saga ???? +[![EN doc](https://img.shields.io/badge/document-English-blue.svg)](user_guide.md) + +## ???? +1. ??[JDK 1.8][jdk] +2. ??[Maven 3.x][maven] +3. ??[Docker][docker] + +[jdk]: http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html +[maven]: https://maven.apache.org/install.html +[docker]: https://www.docker.com/get-docker + +## ?? +??Saga???????? +```bash +$ git clone https://github.com/apache/incubator-servicecomb-saga.git +$ cd incubator-servicecomb-saga +$ mvn clean install -DskipTests -Pdocker +``` + +## ???? +### ??Saga??? +```xml + <dependency> + <groupId>org.apache.servicecomb.saga</groupId> + <artifactId>omega-spring-starter</artifactId> + <version>0.0.3-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.apache.servicecomb.saga</groupId> + <artifactId>omega-transport-resttemplate</artifactId> + <version>0.0.3-SNAPSHOT</version> + </dependency> +``` + +### ??Saga??????????? +?????????? +1. ??????? `@EnableOmega` ???????omega?????alpha????? + ```java + @SpringBootApplication + @EnableOmega + public class Application { + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + } + ``` + +2. ?????????? `@SagaStart` ???? + ```java + @SagaStart(timeout=10) + public boolean transferMoney(String from, String to, int amount) { + transferOut(from, amount); + transferIn(to, amount); + } + ``` + **??:** ???????????????????? + +3. ??????? `@Compensable` ??????????????? + ```java + @Compensable(timeout=5, compensationMethod="cancel") + public boolean transferOut(String from, int amount) { + repo.reduceBalanceByUsername(from, amount); + } + + public boolean cancel(String from, int amount) { + repo.addBalanceByUsername(from, amount); + } + ``` + **??:** ???????????????????? + + **??:** ????????????????????? `@SagaStart` ? `@Compensable` ???? + +4. ????????????? + +## ???? +1. ??postgreSQL + ```bash + docker run -d -e "POSTGRES_DB=saga" -e "POSTGRES_USER=saga" -e "POSTGRES_PASSWORD=password" -p 5432:5432 postgres + ``` + +2. ??alpha????alpha?????postgreSQL?????? + ```bash + docker run -d -p 8090:8090 \ + -e "JAVA_OPTS=-Dspring.profiles.active=prd" \ + -e "spring.datasource.url=jdbc:postgresql://{docker.host.address}:5432/saga?useSSL=false" \ + alpha-server:0.0.3-SNAPSHOT + ``` + +3. ??omega?? `application.yaml` ????????? + ```yaml + spring: + application: + name: {application.name} + alpha: + cluster: + address: {alpha.cluster.addresses} + ``` + +??????????????? diff --git a/omega/omega-connector/omega-connector-grpc/src/test/java/org/apache/servicecomb/saga/omega/connector/grpc/LoadBalancedClusterMessageSenderTest.java b/omega/omega-connector/omega-connector-grpc/src/test/java/org/apache/servicecomb/saga/omega/connector/grpc/LoadBalancedClusterMessageSenderTest.java index bb24c5cb..fce9c0b6 100644 --- a/omega/omega-connector/omega-connector-grpc/src/test/java/org/apache/servicecomb/saga/omega/connector/grpc/LoadBalancedClusterMessageSenderTest.java +++ b/omega/omega-connector/omega-connector-grpc/src/test/java/org/apache/servicecomb/saga/omega/connector/grpc/LoadBalancedClusterMessageSenderTest.java @@ -176,7 +176,7 @@ public void resetLatencyOnReconnection() throws Exception { messageSender.send(event); startServerOnPort(deadPort); - await().atMost(2, SECONDS).until(() -> connected.get(deadPort).size() == 3); + await().atMost(3, SECONDS).until(() -> connected.get(deadPort).size() == 3); TxEvent abortedEvent = new TxAbortedEvent(globalTxId, localTxId, parentTxId, compensationMethod, new RuntimeException("oops")); messageSender.send(abortedEvent); diff --git a/saga-demo/pack-demo/booking/pom.xml b/saga-demo/pack-demo/booking/pom.xml index 47a8f9e7..1f88668c 100644 --- a/saga-demo/pack-demo/booking/pom.xml +++ b/saga-demo/pack-demo/booking/pom.xml @@ -41,9 +41,9 @@ <artifactId>omega-spring-starter</artifactId> </dependency> <dependency> - <groupId>org.apache.servicecomb.saga</groupId> - <artifactId>omega-transport-resttemplate</artifactId> - </dependency> + <groupId>org.apache.servicecomb.saga</groupId> + <artifactId>omega-transport-resttemplate</artifactId> + </dependency> </dependencies> <build> ---------------------------------------------------------------- This is an automated message from the Apache Git Service. To respond to the message, please log on GitHub and use the URL above to go to the specific comment. For queries about this service, please contact Infrastructure at: us...@infra.apache.org With regards, Apache Git Services