Open Mavlarn opened 7 years ago
I don't think I would use Hystrix and a transaction together. I have no experience doing so - if others do please chime in.
My reasoning is that there are many ways a fallback can get triggered. Handling a transaction semantic failure, timeout, short-circuit, etc with the same fallback logic sounds like adding extra complexity.
Personally, I would fine a way to separate the transaction aspect into one layer and then wrap that layer with Hystrix (if Hystrix is necessary for resilience purposes)
yes I also find it is not proper to implement dist transaction with fallback.
So, based on this scenario:
How should I fix this?
I know in some cases, I can use MQ to drive the process. But I don't want to use MQ for now.
This seems like a general architectural question and not related to Hystrix.
From a system architecture perspective, if possible, IMHO and YMMV, I would avoid "distributed transactions" / "two phase commits" all together - and I mean, avoid like the plague... :running_man: .
I would ask myself...
P.S. If you want to experience some really funky system behaviour wrap Hystrix commands inside Hystrix commands and then throw one or two Spring @Transactional
annotations into your code. :smile:
@Mavlarn , I notice that you are actually using JMS already...
Why not just create a listener for a message called "reverse order / charge" or something?
@bltb that repo is just a learning project. In my current product, we use spring cloud without mq, and not considering distributed transaction. I just avoid that by designing business process properly.
But now, I have a function as above: 'buying tickets', interacting with 3 other services. So I need to make sure if there is an error in the last service calling, I should rollback the previous service process.
At the beginning, I thought the Hystrix fallback can do the 'rollback' job. But as discussed above, it seems that it is not a good solution.
I have a question about how should I use hystrix fallback to implement distributed transaction. I asked a question in stackoverfow but got no answer, so I ask here. And this is my question:
I am using spring cloud to implement my micro services system, a ticket sale platform. The scenario is, there is a zuul proxy, a eureka registry, and 3 service: user service, order service and ticket service. Services use feign declarative REST Client to communicate with each other.
Now there is a function to buy tickets, the main process is as below:
And I want to use Hystrix Fallback to implement transaction. For example, if the payment process is finished, but some error happened during ticket movement. How to revet user payment, and order status. Because user payment is in other service.
The following is my current solution, I am not sure whether it is proper. Or is there any other better way to do that.
At first, the OrderResource:
Then the OrderService:
Some key points here are:
@HystrixCommand
inOrderResource.create(order)
method, with fallback function.OrderResource.create(order)
will be used again in fallback function. Although the persistence of this order will be roll-backed. But the data in this instance still can be used to check the running.ticketCompositeService
anduserCompositeService
is a feign client. For feign client methodpayForOrder()
, there is another methodpayForOrderFallback()
for fallback.try/catch
forticketCompositeService
anduserCompositeService
call, to make sure the order will be save anyway with 'FAILED' status.It seems that this solution can work at the most of the time. Except that, in fallback function, if there is some error in
userCompositeService.payForOrderFallback(payDTO);
, then the following composite service call will not be called.And, another problem is, I think it is too complicated.
So, for this scenario, how should I implement dist transaction properly and effectively. Any suggestion or advice will help. Thanks.