задний план
Когда я некоторое время назад просматривал код проекта, я обнаружил, что процесс некоторых интерфейсов является относительно долгим.В каждом сервисе согласованность данных гарантируется через транзакции базы данных, но вышестоящий уровень контроллера не гарантирует согласованности.
Я искал в Интернете, но не нашел более зрелой структуры распределенных транзакций, основанной на Go с открытым исходным кодом.
Итак, я собираюсь взглянуть на tcc-транзакцию, написанную большим парнем из соседнего отдела, которая представляет собой структуру распределенных транзакций, основанную на идее tcc.
коды tcc Try, Confirm и Cancel соответственно.
Попробуйте: попробуйте выполнить бизнес
完成所有业务检查(一致性)
预留必须业务资源(准隔离性)
Подтвердить: Подтвердить выполнение бизнеса
真正执行业务
不作任何业务检查
只使用Try阶段预留的业务资源
Confirm操作满足幂等性
Отменить: отменить выполнение дела
释放Try阶段预留的业务资源
Cancel操作满足幂等性
Чтобы понять принцип его реализации, первым шагом будет прогон примера, поставляемого с проектом, то есть кода в части tcc-transaction-tutorial-sample.
Сегодня я в основном расскажу о различных ямах, возникающих в процессе прогона tcc-transaction-tutorial-sample.
зависимая среда
- Java
- Maven
- Git
- MySQL
- Redis
- Zookeeper
- Intellij IDEA
Адрес источника:GitHub.com/ часто детали…
Сам форкаю копию (внесены изменения в конфигурацию):GitHub.com/D майнер Джек и…
Ступая на яму
Приготовьтесь ступить на яму
Шаг 1: Клонируйте код
Используйте "git клонGitHub.com/D майнер Джек и…"Код загрузки команды
Шаг 2. Импортируйте код и выполните сценарий базы данных.
Код импортируется в Intellij IDEA.
Выполните сценарии базы данных в tcc-transaction-http-sample/src/main/dbscripts.
Шаг 3: Измените файл конфигурации
Основная модификация касается параметров конфигурации базы данных. Возьмем, к примеру, tcc-transaction-dubbo-sample, файлы, которые нужно изменить:
tcc-transaction/tcc-transaction-tutorial-sample/tcc-transaction-dubbo-sample/tcc-transaction-dubbo-capital/src/main/resources/tccjdbc.properties
tcc-transaction/tcc-transaction-tutorial-sample/tcc-transaction-dubbo-sample/tcc-transaction-dubbo-redpacket/src/main/resources/tccjdbc.properties
tcc-transaction/tcc-transaction-tutorial-sample/tcc-transaction-dubbo-sample/tcc-transaction-dubbo-order/src/main/resources/tccjdbc.properties
После изменения трех файлов соответствующая конфигурация выглядит следующим образом.
# 根据具体的MySQL版本使用驱动名称
jdbc.driverClassName=com.mysql.cj.jdbc.Driver
# 换成你连接数据库的地址
tcc.jdbc.url=jdbc:mysql://127.0.0.1:3306/TCC?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false
# 换成你需要配置数据库的用户名
jdbc.username=root
# 换成你需要配置数据库的密码
jdbc.password=rootroot
c3p0.initialPoolSize=10
c3p0.minPoolSize=10
c3p0.maxPoolSize=30
c3p0.acquireIncrement=3
c3p0.maxIdleTime=1800
c3p0.checkoutTimeout=30000
В то же время измените подключение к базе данных файла jdbc.proerties в трех проектах tcc-transaction-sample-capital, tcc-transaction-sample-redpacket и tcc-transaction-sample-order.Измененная конфигурация выглядит следующим образом
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/TCC_CAP?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false
tcc.jdbc.url=jdbc:mysql://127.0.0.1:3306/TCC?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false
jdbc.username=root
jdbc.password=rootroot
c3p0.initialPoolSize=10
c3p0.minPoolSize=10
c3p0.maxPoolSize=30
c3p0.acquireIncrement=3
c3p0.maxIdleTime=1800
c3p0.checkoutTimeout=30000
Шаг 4: Запустите проект
Объединив файл README.md проекта и статьи в Интернете, мы знаем, что если вы хотите запустить пример проекта, вам нужно запустить три проекта отдельно.
tcc-транзакция предоставляет две версии:
-
Пример версии на основе связи dubbo
-
Пример версии на основе http связи
Три проекта для этих двух версий:
-
tcc-transaction-dubbo-capital (служба активов аккаунта), tcc-transaction-dubbo-redpacket (служба красных пакетов), tcc-transaction-dubbo-order (служба заказов транзакций)
-
tcc-transaction-http-capital (служба активов учетной записи), tcc-transaction-http-redpacket (служба красных пакетов), tcc-transaction-http-order (служба заказа транзакции)
На самом деле, я запускал обе версии, и только примерная версия, основанная на связи dubbo, в конце концов была успешной (версия http больше всего не удалась, когда она была окончательно подтверждена, в результате чего окончательный статус заказа был неизвестен).
Возьмем в качестве примера пример, основанный на коммуникации dubbo.
Начальная конфигурация tcc-transaction-dubbo-capital выглядит следующим образом.
Начальная конфигурация tcc-transaction-dubbo-redpacket выглядит следующим образом.
Начальная конфигурация tcc-transaction-dubbo-order выглядит следующим образом.
Яма 1: Не могу подключиться к zk
Запустите проект tcc-transaction-dubbo-capital, и появится следующее сообщение об ошибке.
[sample-dubbo-capital]2019-08-31 17:48:05,312 INFO [org.apache.zookeeper.ZooKeeper] Initiating client connection, connectString=127.0.0.1:2181 sessionTimeout=30000 watcher=org.I0Itec.zkclient.ZkClient@32c7bb63
[sample-dubbo-capital]2019-08-31 17:48:05,334 INFO [org.apache.zookeeper.ClientCnxn] Opening socket connection to server 127.0.0.1/127.0.0.1:2181. Will not attempt to authenticate using SASL (unknown error)
[sample-dubbo-capital]2019-08-31 17:48:05,344 WARN [org.apache.zookeeper.ClientCnxn] Session 0x0 for server null, unexpected error, closing socket connection and attempting reconnect
java.net.ConnectException: Connection refused
at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method)
at sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:717)
at org.apache.zookeeper.ClientCnxnSocketNIO.doTransport(ClientCnxnSocketNIO.java:361)
at org.apache.zookeeper.ClientCnxn$SendThread.run(ClientCnxn.java:1081)
[sample-dubbo-capital]2019-08-31 17:48:06,456 INFO [org.apache.zookeeper.ClientCnxn] Opening socket connection to server 127.0.0.1/127.0.0.1:2181. Will not attempt to authenticate using SASL (unknown error)
[sample-dubbo-capital]2019-08-31 17:48:06,459 WARN [org.apache.zookeeper.ClientCnxn] Session 0x0 for server null, unexpected error, closing socket connection and attempting reconnect
java.net.ConnectException: Connection refused
at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method)
at sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:717)
at org.apache.zookeeper.ClientCnxnSocketNIO.doTransport(ClientCnxnSocketNIO.java:361)
at org.apache.zookeeper.ClientCnxn$SendThread.run(ClientCnxn.java:1081)
[sample-dubbo-capital]2019-08-31 17:48:07,566 INFO [org.apache.zookeeper.ClientCnxn] Opening socket connection to server 127.0.0.1/127.0.0.1:2181. Will not attempt to authenticate using SASL (unknown error)
[sample-dubbo-capital]2019-08-31 17:48:07,567 WARN [org.apache.zookeeper.ClientCnxn] Session 0x0 for server null, unexpected error, closing socket connection and attempting reconnect
java.net.ConnectException: Connection refused
Из сообщения об ошибке с первого взгляда видно, что не может подключиться к zk, то есть zookeeper.
Это легко понять, т.к. zk не устанавливается локально, поэтому устанавливайте и запускайте zk через "./zkServer.sh start"
Яма 2: Redis не может подключиться
Сообщение об ошибке при запуске tcc-transaction-dubbo-order выглядит следующим образом:
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: org.mengyun.tcctransaction.sample.dubbo.order.service.PlaceOrderServiceImpl org.mengyun.tcctransaction.sample.dubbo.order.web.controller.OrderController.placeOrderService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'placeOrderServiceImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: org.mengyun.tcctransaction.sample.dubbo.order.service.PaymentServiceImpl org.mengyun.tcctransaction.sample.dubbo.order.service.PlaceOrderServiceImpl.paymentService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'paymentServiceImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: org.mengyun.tcctransaction.sample.dubbo.capital.api.CapitalTradeOrderService org.mengyun.tcctransaction.sample.dubbo.order.service.PaymentServiceImpl.capitalTradeOrderService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'captialTradeOrderService': Post-processing of FactoryBean's singleton object failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'compensableTransactionAspect' defined in class path resource [tcc-transaction.xml]: Cannot resolve reference to bean 'transactionConfigurator' while setting bean property 'transactionConfigurator'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionConfigurator': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.mengyun.tcctransaction.TransactionRepository org.mengyun.tcctransaction.spring.support.SpringTransactionConfigurator.transactionRepository; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionRepository' defined in file [/Users/jackie/workspace/tcc-transaction/tcc-transaction-tutorial-sample/tcc-transaction-dubbo-sample/tcc-transaction-dubbo-order/target/tcc-transaction-dubbo-order-1.2.6/WEB-INF/classes/config/spring/local/appcontext-service-tcc.xml]: Error setting property values; nested exception is org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions (1) are:
PropertyAccessException 1: org.springframework.beans.MethodInvocationException: Property 'jedisPool' threw exception; nested exception is redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:526)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:295)
... 60 more
Это похоже на указанную выше причину: Redis не установлен локально, поэтому соединение с Redis не может быть получено.
Поэтому установите Redis и используйте «redis-server» для запуска Redis.
Яма 3: Причина: org.springframework.jdbc.CannotGetJdbcConnectionException: не удалось получить соединение JDBC
После того, как все три проекта запущены, вы можете увидеть страницу со списком ссылок на продукты, но вы не можете перейти после нажатия на ссылку, и ошибка выглядит следующим образом.
Type Exception Report
Message Request processing failed; nested exception is org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.PersistenceException:
Description The server encountered an unexpected condition that prevented it from fulfilling the request.
Exception
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.PersistenceException:
### Error querying database. Cause: org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is java.sql.SQLException: An attempt by a client to checkout a Connection has timed out.
### The error may exist in URL [jar:file:/Users/jackie/workspace/tcc-transaction/tcc-transaction-tutorial-sample/tcc-transaction-http-sample/tcc-transaction-http-order/target/tcc-transaction-http-order-1.2.6/WEB-INF/lib/tcc-transaction-sample-order-1.2.6.jar!/config/sqlmap/main/sample-product.xml]
### The error may involve org.mengyun.tcctransaction.sample.order.infrastructure.dao.ProductDao.findByShopId
### The error occurred while executing a query
### Cause: org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is java.sql.SQLException: An attempt by a client to checkout a Connection has timed out.
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:965)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:844)
javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:829)
javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:106)
Root Cause
org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.PersistenceException:
### Error querying database. Cause: org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is java.sql.SQLException: An attempt by a client to checkout a Connection has timed out.
### The error may exist in URL [jar:file:/Users/jackie/workspace/tcc-transaction/tcc-transaction-tutorial-sample/tcc-transaction-http-sample/tcc-transaction-http-order/target/tcc-transaction-http-order-1.2.6/WEB-INF/lib/tcc-transaction-sample-order-1.2.6.jar!/config/sqlmap/main/sample-product.xml]
Согласно сообщению об ошибке, устранение неполадок заключается в том, что версия MySQL и версия драйвера базы данных не совпадают.
Локальная версия MySQL — «8.0.11 MySQL Community Server — GPL», но соответствующая версия драйвера в tcc-транзакции —
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.33</version>
</dependency>
изменить на
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.11</version>
</dependency>
При этом для старшей версии нужно добавить useSSL=false после подключенного jdbc-url
Яма 4: Загрузка класса `com.mysql.jdbc.Driver' Это устарело
При запуске tcc-transaction-dubbo-redpacket я вижу в журнале предупреждение "Загрузка класса `com.mysql.jdbc.Driver'. Это устарело".
В результате поиска было обнаружено, что драйвер базы данных com.mysql.jdbc.Driver устарел, и необходимо использовать com.mysql.cj.jdbc.Driver, поэтому конфигурация jdbc.proerties изменена (см. конкретной конфигурации), и запуск нормальный.
Наступив на вышеупомянутую яму, запустите три проекта, завершите процесс и реализуйте поведение при покупке товаров на основе распределенных транзакций. Конкретный процесс показан на следующем рисунке.
Суммировать
Процесс запуска примера проекта не очень гладкий, в основном по нескольким причинам.
- Несоответствие между конфигурацией локальной среды и предоставленным проектом привело ко многим обходным путям, таким как версия MySQL.
- Отсутствует подробная документация для запуска примера проекта.
- Информация, представленная в Интернете, относительно отрывочна и устарела, а шаги, которые можно выполнить в тексте, больше не применимы к текущему коду.
Таким образом, после того, как вы наступили на такое количество ям, чтобы подвести итог, избегайте людей, которые идут сзади, чтобы пойти тем же путем.
Личный публичный аккаунт JackieZheng, добро пожаловать на внимание~