Вам понадобятся:
Получите исходный код:
$ git clone https://github.com/apache/servicecomb-pack.git
$ cd servicecomb-pack
Saga можно собрать одним из следующих способов.
Только создайте исполняемые файлы.
$ mvn clean install -DskipTests
Создайте исполняемые файлы вместе с образом Docker.
$ mnv clean install -DskipTests -Pdocker
Соберите исполняемый файл и дистрибутив saga.
$ mvn clean install -DskipTests -Prelease
После выполнения любой из вышеперечисленных команд вы найдёте исполняемый файл сервера alpha в alpha/alpha-server/target/saga/alpha-server-${version}-exec.jar
.
<dependency>
<groupId>org.apache.servicecomb.pack</groupId>
<artifactId>omega-spring-starter</artifactId>
<version>${pack.version}</version>
</dependency>
<dependency>
<groupId>org.apache.servicecomb.pack</groupId>
<artifactId>omega-transport-resttemplate</artifactId>
<version>${pack.version}</version>
</dependency>
Примечание: пожалуйста, замените ${pack.version}
на актуальную версию.
Миграция Примечание: начиная с версии 0.3.0 мы переименовали репозиторий проекта с saga на pack. Пожалуйста, обновите groupId и имя пакета, если вы переносите своё приложение с saga 0.2.x на pack 0.3.0.
name | 0.2.x | 0.3.x |
---|---|---|
groupId | org.apache.servicecomb.saga | org.apache.servicecomb.pack |
Package Name | org.apache.servicecomb.saga | org.apache.servicecomb.pack |
Добавьте аннотации saga и соответствующие методы компенсации. Возьмём в качестве примера приложение для перевода денег:
Добавьте @SagaStart
в начальной точке глобальной транзакции, чтобы подготовить новый контекст глобальной транзакции. Если вы не укажете SagaStart, то нижележащая подтранзакция будет жаловаться на то, что глобальный идентификатор транзакции не найден.
import org.apache.servicecomb.pack.omega.context.annotations.SagaStart;
@SagaStart(timeout=10)
public boolean transferMoney(String from, String to, int amount) {
transferOut(from, amount);
transferIn(to, amount);
}
Примечание: по умолчанию тайм-аут отключён.
Добавьте @Compensable
к подтранзакции и укажите соответствующий метод компенсации.
import javax.transaction.Transactional;
import org.apache.servicecomb.pack.omega.transaction.annotations.Compensable;
@Compensable(timeout=5, compensationMethod="cancel")
@Transactional
public boolean transferOut(String from, int amount) {
repo.reduceBalanceByUsername(from, amount);
}
@Transactional
public boolean cancel(String from, int amount) {
repo.addBalanceByUsername(from, amount);
}
Примечание Транзакции и методы компенсации должны иметь одинаковые аргументы. Транзакции и компенсации, реализованные службами, должны быть идемпотентными. Мы настоятельно рекомендуем использовать Spring @Transactional для обеспечения локальной транзакции.
Примечание: По умолчанию тайм-аут отключен.
Примечание: Если начальная точка глобальной транзакции и локальной транзакции перекрывается, необходимы как @SagaStart
, так и @Compensable
.
Добавьте параметры alpha.cluster.address
alpha:
cluster:
address: alpha-server.servicecomb.io:8080
Добавьте параметры omega.spec.names
omega:
spec:
names: **Saga**
5. Повторите шаг 2 для сервиса `transferIn`.
6. Начиная с версии pack-0.3.0, вы можете получить доступ к [OmegaContext](https://github.com/apache/servicecomb-pack/blob/master/omega/omega-context/src/main/java/org/apache/servicecomb/pack/omega/context/OmegaContext.java) для gloableTxId и localTxId в методе с аннотацией @Compensable или в методе отмены.
7. Начиная с pack-0.7.0, можно изменить спецификацию распределённой транзакции через параметр alpha.spec.names. В настоящее время поддерживаются режимы saga-db (по умолчанию), tcc-db, saga-akka.
#### Явное прохождение контекста транзакции
В большинстве случаев Omega прозрачно передаёт контекст транзакции (подробности см. в разделе «Межсервисное взаимодействие» в design.md). Передача контекста транзакции осуществляется путём внедрения информации о контексте транзакции на стороне отправителя и извлечения её на стороне получателя. Ниже приведён пример, иллюстрирующий этот процесс:
Сервис A:
```java
@SagaStart
public void foo() {
restTemplate.postForEntity("http://service-b/bar", ...);
}
Сервис B:
@GetMapping("/bar")
@Compensable
public void bar() {
...
}
Вот как это делает Omega:
foo
сервиса A открывает новую глобальную транзакцию.RestTemplate
к сервису B.Omega поддерживает следующие способы неявной передачи контекста транзакции:
OmegaContext
).java.util.concurrent.Executor{Service}
, аннотированный @OmegaContextAware.Итак, возникает проблема: что делать, если не работает неявная передача контекста транзакции? Например, сервис A вызывает сервис B через некоторую библиотеку RPC, и невозможно внести изменения во внедрение или извлечение информации о контексте транзакции. В этой ситуации вам нужна явная передача контекста транзакции. С версии ServiceComb Pack 0.5.0 для этого предоставляются два класса.
Сервис А:
@SagaStart
public void foo(BarCommand cmd) {
TransactionContext localTxContext = omegaContext.getTransactionContext();
someRpc.send(cmd, localTxContext);
}
Сервис В:
public void listen(BarCommand cmd, TransactionContext injectedTxContext) {
bar(cmd, injectedTxContext);
}
@Compensable
public void bar(BarCommand cmd, TransactionContext injectedTxContext) {
...
// TransactionContext localTxContext = omegaContext.getTransactionContext();
}
Обратите внимание, что метод bar
получил контекст введённой транзакции в списке параметров и локальный контекст транзакции из OmegaContext
. Если сервису B необходимо явно передать контекст транзакции другому сервису, следует использовать локальный контекст.
Сервис А:
public class BarCommand {}
public class BarCommandWithTxContext
extends BarCommand implements TransactionContextProperties {
// setter getter для globalTxId
// setter getter для localTxId
}
@SagaStart
public void foo(BarCommand cmd) {
BarCommandWithTxContext cmdWithTxContext = new BarCommandWithTxContext(cmd);
cmdWithTxContext.setGlobalTxId(omegaContext.globalTxId());
cmdWithTxContext.setLocalTxId(omegaContext.localTxId());
someRpc.send(cmdWithTxContext);
}
Сервис В:
public void listen(BarCommandWithTxContext cmdWithTxContext) {
bar(cmdWithTxContext);
}
@Compensable
public void bar(BarCommandWithTxContext cmdWithTxContext) {
...
// TransactionContext localTxContext = omegaContext.getTransactionContext();
}
Аналогично предыдущему подходу, cmdWithTxContext.get{Global,Local}TxId()
также возвращает... Внедрение контекста транзакции.
Начиная с версии pack-0.5.0, к аннотации @SagaStart
добавлен атрибут autoClose
, который используется для управления отправкой события SagaEndedEvent
в Alpha после выполнения аннотированного метода SagaStart
(значение по умолчанию — true
). Если autoClose=false
, вы должны использовать @SageEnd
для отправки события SageEndedEvent
вручную, например:
Сервис A:
@SagaStart(autoClose=false)
public void foo() {
restTemplate.postForEntity("http://service-b/bar", ...);
}
Сервис B:
@GetMapping("/bar")
@Compensable
@SagaEnd
public void bar() {
...
}
Добавьте аннотации TCC и соответствующие методы подтверждения и отмены. Рассмотрим приложение перевода денег в качестве примера:
Добавьте @TccStart
в начальной точке глобальной транзакции:
import org.apache.servicecomb.pack.omega.context.annotations.TccStart;
@TccStart
public boolean transferMoney(String from, String to, int amount) {
transferOut(from, amount);
transferIn(to, amount);
}
Примечание: По умолчанию тайм-аут отключен.
Добавьте @Participate
в подтранзакции и укажите соответствующий метод компенсации:
import javax.transaction.Transactional;
import org.apache.servicecomb.pack.omega.transaction.annotations.Participate;
@Participate(confirmMethod = "confirm", cancelMethod = "cancel")
@Transactional
public void transferOut(String from, int amount) {
// check balance
}
@Transactional
public void confirm(String from, int amount) {
repo.reduceBalanceByUsername(from, amount);
}
@Transactional
public void cancel(String from, int amount) {
repo.addBalanceByUsername(from, amount);
}
Примечание: Методы подтверждения и отмены должны иметь те же аргументы, что и метод участия, методы подтверждения и отмены, реализованные службами, должны быть идемпотентными. Мы настоятельно рекомендуем использовать Spring @Transactional для обеспечения локальной транзакции.
Примечание: Текущая реализация TCC не поддерживает тайм-ауты.
Примечание: Если начальная точка глобальной транзакции и локальной транзакции перекрываются, необходимы как @TccStart
, так и @Participate
.
Добавьте параметры alpha.cluster.address:
alpha:
cluster:
address: alpha-server.servicecomb.io:8080
Добавьте параметры omega.spec.names:
omega:
spec:
names: tcc
Повторите шаг 2 для сервиса transferIn
.
Подобно @Compensable
в Saga, @Participate
также поддерживает явное прохождение транзакции. Подробнее см. Сага — Явное прохождение контекста транзакции.
Запустите PostgreSQL.
docker run -d -e "POSTGRES_DB=saga" -e "POSTGRES_USER=saga" -e "POSTGRES_PASSWORD=password" -p 5432:5432 postgres
Ознакомьтесь с этим документом, если хотите использовать MySQL вместо PostgreSQL.
Запустите Alpha. Перед запуском Alpha убедитесь, что PostgreSQL уже запущен. Вы можете запустить Alpha через Docker или исполняемый файл.
docker run -d -p 8080:8080 -p 8090:8090 -e "JAVA_OPTS=-Dspring.profiles.active=prd -Dspring.datasource.url=jdbc:postgresql://${host_address}:5432/saga?useSSL=false" alpha-server:${saga_version}
java -Dspring.profiles.active=prd -D"spring.datasource.url=jdbc:postgresql://${host_address}:5432/saga?useSSL=false" -jar alpha-server-${saga_version}-exec.jar
Примечание: Пожалуйста, измените ${pack_version}
и ${host_address}
на фактическое значение перед выполнением команды.
Примечание: По умолчанию порт 8080 используется для обслуживания запросов Omega через gRPC. Вот перевод текста на русский язык:
В то время как порт 8090 используется для запроса событий, хранящихся в альфа.
application.yaml
задайте следующие значения:
spring:
application:
name: {application.name}
alpha:
cluster:
address: {alpha.cluster.addresses}
omega:
spec:
names: saga
Затем вы можете запустить свои микросервисы и получить доступ ко всем событиям саги через http://${alpha-server:port}/saga/events.
Подробности см. в разделе Включение SSL.
Экземпляр Alpha может зарегистрироваться в службе обнаружения, Omega получает список экземпляров Alpha и адрес gRPC через службу обнаружения.
Запустите Alpha с параметром spring.cloud.consul.enabled=true
:
java -jar alpha-server-${saga_version}-exec.jar \
--spring.datasource.url=jdbc:postgresql://${host_address}:5432/saga?useSSL=false \
--spring.datasource.username=saga \
--spring.datasource.password=saga \
--spring.cloud.consul.enabled=true \
--spring.cloud.consul.host=${consul_host} \
--spring.cloud.consul.port=${consul_port} \
--spring.profiles.active=prd
Примечание: ${consul_host}
— это хост Consul, а ${consul_port}
— порт Consul.
Примечание: Подробнее см. Spring Cloud Consul 2.x или Spring Cloud Consul 1.x.
Проверьте регистрационную информацию. Отправьте запрос curl http://127.0.0.1:8500/v1/agent/services
, ответом будет следующий JSON:
{
"servicecomb-alpha-server-0-0-0-0-8090": {
"ID": "servicecomb-alpha-server-0-0-0-0-8090",
"Service": "servicecomb-alpha-server",
"Tags": [
"alpha-server-host=0.0.0.0",
"alpha-server-port=8080",
"secure=false"
],
"Meta": {},
"Port": 8090,
"Address": "10.50.7.14",
"Weights": {
"Passing": 1,
"Warning": 1
},
"EnableTagOverride": false
}
}
Примечание: свойство Tags
— это адрес gRPC Alpha.
Примечание: имя экземпляра Alpha по умолчанию — servicecomb-alpha-server
. Вы можете задать его, запустив параметр spring.application.name
.
Настройте Omega. Отредактируйте файл pom.xml
и добавьте зависимость omega-spring-cloud-consul-starter
:
<dependency>
<groupId>org.apache.servicecomb.pack</groupId>
<artifactId>omega-spring-cloud-consul-starter</artifactId>
<version>${pack.version}</version>
</dependency>
Отредактируйте файл application.yaml
, как показано в следующем примере:
spring:
cloud:
consul:
discovery:
register: false
host: 127.0.0.1
port: 8500
alpha:
cluster:
register:
type: consul
Свойство spring.cloud.consul.host
задаёт адрес экземпляра сервера Consul, свойство spring.cloud.consul.port
задаёт порт экземпляра сервера Consul, свойство spring.cloud.consul.discovery.register=false
не регистрирует вас самостоятельно. Подробнее см. Spring Boot Spring Cloud Consul 2.x или Spring Cloud Consul 1.x.
Свойство alpha.cluster.register.type=consul
означает, что Omega получает адрес gRPC от Alpha из Consul.
Совместимость со Spring Boot. Если ваш проект не использует Spring Boot 2.3.X, обратитесь к этому списку, чтобы добавить совместимую версию spring-cloud-starter-consul-discovery:
spring boot | spring-cloud-starter-consul-discovery |
---|---|
2.3.12.RELEASE | 2.2.8.RELEASE |
2.1.x.RELEASE | 2.1.1.RELEASE |
2.0.x.RELEASE | 2.0.2.RELEASE |
|----------------|-------------------------------------------| | 2.1.x.RELEASE | 2.1.1.RELEASE | | 2.0.x.RELEASE | 2.0.3.RELEASE |
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.2.10.RELEASE</version>
</dependency>
</dependencies>
</dependencyManagement>
Note: If you define spring.application.name
parameter when start alpha, you need to specify this service name in Omega via the parameter alpha.cluster.serviceId
.
Run alpha:
run with parameter spring.cloud.zookeeper.enabled=true
:
java -jar alpha-server-${saga_version}-exec.jar \
--spring.datasource.url=jdbc:postgresql://${host_address}:5432/saga?useSSL=false \
--spring.datasource.username=saga \
--spring.datasource.password=saga \
--spring.cloud.zookeeper.enabled=true \
--spring.cloud.zookeeper.connectString=${zookeeper_host}:${zookeeper_port} \
--spring.profiles.active=prd
Note: ${zookeeper_host}
is zookeeper host, ${zookeeper_port}
is zookeeper port.
Note: Check out for more details Spring Cloud Zookeeper 2.x, Spring Cloud Zookeeper 1.x.
Verify registration information:
view znode /services/servicecomb-alapha-server:
{ "name": "servicecomb-alpha-server", "id": "9b2223ae-50e6-49a6-9f3b-87a1ff06a016", "address": "arch-office", "port": 8090, "sslPort": null, "payload": { "@class": "org.springframework.cloud.zookeeper.discovery.ZookeeperInstance", "id": "servicecomb-alpha-server-1", "name": "servicecomb-alpha-server", "metadata": { "servicecomb-alpha-server": "arch-office:8080" } }, "registrationTimeUTC": 1558000134185, "serviceType": "DYNAMIC", "uriSpec": { "parts": [ { "value": "scheme", "variable": true }, { "value": "://", "variable": false }, { "value": "address", "variable": true }, { "value": ":", "variable": false }, { "value": "port", "variable": true } ] } }
**Note**: `metadata` property is alpha gRPC address.
**Note**: Alpha instance name is `servicecomb-alpha-server` by default. You can set it by starting parameter `spring.application.name`.
3. Setup omega:
Edit your `pom.xml` and add the `omega-spring-cloud-zookeeper-starter` dependency:
```xml
<dependency>
<groupId>org.apache.servicecomb.pack</groupId>
<artifactId>omega-spring-cloud-zookeeper-starter</artifactId>
<version>${pack.version}</version>
</dependency>
Edit your application.yaml, as shown in the following example:
spring:
cloud:
zookeeper:
enabled: true
connectString: 127.0.0.1:2181
alpha:
cluster:
register:
type: zookeeper
spring.cloud.zookeeper.connectString
property is set to the Zookeeper server’s instance address. Check out Spring Boot’s Spring Cloud Zookeeper 2.x and Spring Cloud Zookeeper 1.x for more. alpha.cluster.register.type=zookeeper свойство в омеге получает адрес gRPC альфа из Zookeeper.Версия spring boot совместима.
Если ваш проект не использует spring boot 2.3.X, обратитесь к этому списку, чтобы добавить совместимую версию spring-cloud-starter-zookeeper-discovery:
spring boot | spring-cloud-starter-zookeeper-discovery |
---|---|
2.3.12.RELEASE | 2.2.5.RELEASE |
2.1.x.RELEASE | 2.1.1.RELEASE |
1.5.17.RELEASE | 1.2.2.RELEASE |
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
</dependencies>
</dependencyManagement>
Примечание: Если вы определяете параметр spring.application.name
при запуске альфа, вам необходимо указать это имя службы в омеге через параметр alpha.cluster.serviceId
.
Запустите альфа с параметром nacos.client.enabled=true
:
java -jar alpha-server-${saga_version}-exec.jar \
--spring.datasource.url=jdbc:postgresql://${host_address}:5432/saga?useSSL=false \
--spring.datasource.username=saga \
--spring.datasource.password=saga \
--spring.cloud.nacos.discovery.enabled=true \
--spring.cloud.nacos.discovery.serverAddr=${nacos_host}:${nacos_port} \
--nacos.client.enabled=true \
--spring.profiles.active=prd
Примечание: ${nacos_host}
— это хост nacos, ${nacos_port}
— порт nacos.
Примечание: Подробнее см. Spring Cloud Nacos Discovery.
Проверьте регистрационную информацию.
Отправьте запрос curl -X GET 'http://127.0.0.1:8848/nacos/v1/ns/instance/list?serviceName=servicecomb-alpha-server‘
, он ответит следующим JSON:
{ "metadata": {}, "dom": "servicecomb-alpha-server", "cacheMillis": 3000, "useSpecifiedURL": false, "hosts": [ { "valid": true, "marked": false, "metadata": { "preserved.register.source": "SPRING_CLOUD", "servicecomb-alpha-server": "192.168.2.28:8080" }, "instanceId": "192.168.2.28#8090#DEFAULT#DEFAULT_GROUP@@servicecomb-alpha-server", "port": 8090, "healthy": true, "ip": "192.168.2.28", "clusterName": "DEFAULT", "weight": 1, "ephemeral": true, "serviceName": "servicecomb-alpha-server", "enabled": true } ], "name": "DEFAULT_GROUP@@servicecomb-alpha-server", "checksum": "d9e8deefd1c4f198980f4443d7c1b1fd", "lastRefTime": 1562567653565, "env": "", "clusters": "" }
**Примечание:** Свойство `metadata` — это адрес gRPC альфа.
**Примечание**: Имя экземпляра альфа по умолчанию — `servicecomb-alpha-server`. Вы можете установить его, запустив параметр `spring.application.name`.
3. Настройте омегу.
Измените свой `pom.xml` и добавьте зависимость `omega-spring-cloud-nacos-starter`:
```xml
<dependency>
<groupId>org.apache.servicecomb.pack</groupId>
<artifactId>omega-spring-cloud-nacos-starter</artifactId>
<version>${pack.version}</version>
</dependency>
Измените файл application.yaml
, как показано в следующем примере:
spring:
cloud:
nacos:
discovery:
enabled: true
serverAddr: 127.0.0.1:8848
alpha:
cluster:
register:
type: nacos
spring.cloud.nacos.discovery.serverAddr
установлено на адрес экземпляра сервера Nacos, см. Spring Boot [Spring Cloud Nacos Discovery]. Текст запроса написан на английском языке.Для получения более подробной информации см. ](https://nacos.io/en-us/docs/quick-start-spring-cloud.html).
Свойство alpha.cluster.register.type=nacos позволяет омеге получать адрес gRPC альфа от Nacos.
Версия spring boot должна быть совместима.
Если ваш проект не использует spring boot 2.3.X, пожалуйста, обратитесь к этому списку, чтобы добавить совместимую версию spring-cloud-starter-alibaba-nacos-discovery: | spring boot | spring-cloud-starter-alibaba-nacos-discovery | ----------------| ------------- | ------------------------------------- | | 2.3.12.RELEASE | 2.2.6.RELEASE | | 2.1.x.RELEASE | 0.2.2.RELEASE | | 1.5.17.RELEASE | 0.1.2.RELEASE |
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2.2.6.RELEASE</version>
</dependency>
</dependencies>
</dependencyManagement>
Примечание: Если вы определяете параметр spring.application.name при запуске альфа, вам необходимо указать это имя службы в омеге через параметр alpha.cluster.serviceId.
Альфа может быть высокодоступной путём развёртывания нескольких экземпляров, включите поддержку кластера с параметром alpha.cluster.master.enabled=true. [src-TransactionClientHttpRequestInterceptor]: ../omega/omega-transport/omega-transport-resttemplate/src/main/java/org/apache/servicecomb/pack/omega/transport/resttemplate/TransactionClientHttpRequestInterceptor.java [src-TransactionHandlerInterceptor]: ../omega/omega-transport/omega-transport-resttemplate/src/main/java/org/apache/servicecomb/pack/omega/transport/resttemplate/TransactionHandlerInterceptor.java
Альфа поддерживает собственные транспортные средства с помощью параметра alpha.feature.nativetransport=true. Эти собственные транспортные средства добавляют функции, специфичные для конкретной платформы, генерируют меньше мусора и обычно улучшают производительность по сравнению с транспортом на основе NIO.
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )