package com.leiyijia.demo.distribute;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 分布式服务接口顺序性调用
* @author leiyijia
*
*/
@RestController
public class OrderServiceControl {
private static final int SERVICE_INSTANCE_NUM = 3; //服务实例部署个数
@Autowired
private OrderService orderService;
@GetMapping("/order")
public String doRequest(String orderId, int seq) {
//这个地方从前端接收请求能保证99%的顺序性,因为每个请求有网络延时不一样的原因,无法保证control接收到前端的请求是100%有序的
//如前端提交的顺序是:request1, request2,request3,而control接收到的请求可能是request1, request3, request2
//这种情况如果要保证100%有序的话,就只能前端请求的时候除了带上唯一id外,还得带上类似seq的顺序号问题
//然后后端根据id+seq进行多个service实例分发,多台service实例可以用zk之类的分布式锁进行轮询获取锁
//如:seq3那个service实例获取到锁后,先检查seq1和seq2有没有执行,没有的话就释放锁,让其他2个service获取锁;如有的话就执行即可
//但是大多数情况没必要(除非要求100%保证顺序性),因为这会加大系统复杂性和降低系统性能
return orderService.doService(orderId, seq, hash(orderId));//根据orderid指定发送到其中一台接口服务
}
/**
* hash分发,也可以改为一致性hash算法
* @param id 唯一键
* @return 服务实例所在的机器号
*/
private int hash(String id) {
return Math.abs(id.hashCode()) % SERVICE_INSTANCE_NUM;
}
}
package com.leiyijia.demo.distribute;
import java.util.Queue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import org.springframework.stereotype.Service;
@Service
public class OrderService {
private static final Queue<String> queue = new LinkedBlockingQueue<String>();
static {
new Thread(new Runnable() {
public void run() {
while(true) {
for(String orderSeq : queue) {
System.out.println("do service , orderID : " + orderSeq);
try {
Thread.sleep(70);//模拟业务处理
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
queue.remove(orderSeq);
}
}
}
}).start();
}
/**
* num用来模拟该服务部署的机器序号
* @param orderId
* @param num
*/
public String doService(String orderId, int seq, int num) {
//如果这里不采用多线程,这样处理即可
/*System.out.println("do service , orderID : " + orderId + ", request seq : " + seq + ", instance num : " + num);
try {
Thread.sleep(100);//模拟业务处理
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/
//如果为了提高性能,这个方法采用多线程处理的话,
//虽然接收到的请求是顺序的,但是多线程执行请求还是可能会顺序错乱
if(num == 1) //模拟实例1的机器接收到请求
queue.add(orderId + "(seq=" +seq + ")");
return "success";
}
}
分布式接口的有序性
©著作权归作者所有,转载或内容合作请联系作者
- 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
- 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
- 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
推荐阅读更多精彩内容
- 1.幂等性 所谓幂等性,就是说一个接口,多次发起同一个请求,你这个接口得保证结果是准确的,比如不能多扣款,不能多插...
- 1.调用顺序 其实分布式系统接口的调用顺序,也是个问题,一般来说是不用保证顺序的。但是有的时候可能确实是需要严格的...
- 面试题 分布式服务接口的幂等性如何设计(比如不能重复扣款)? 面试官心理分析 从这个问题开始,面试官就已经进入了实...