最新的項目用了dubbo框架,原來只有一臺provider機器提供服務,但是現在需要擴展到多臺provider機,並且由於業務邏輯涉及到了文件加密解密操作,而密鑰又是由客戶提供的,因此出現了第二次請求過來會由dubbo分發到文件所在位置以外的服務機上,就出現了找不到文件的情況。
ok,作爲supportor,開始解決,方案1是直接增加文件服務器來進行,但是由於項目已經上線,改起來麻煩,於是果斷pass;
這樣就有了方案2,修改dubbo的負載均衡策略,使得每次的業務邏輯在一條流水線上進行。
本文會持續更新,來介紹負載均衡
1. consistenthash--一致性hash算法
使用方式,在服務端註冊的時候提供配置
<!-- 聲明需要暴露的服務接口 -->
<dubbo:service interface="DemoService" ref="demoService" loadbalance="consistenthash" />
dubbo對於該算法默認比較的是第一個請求參數,即相同的請求參數會分發到同一臺服務機上。
最開始看到這個解釋的時候瞬間迷茫了(原諒我的理解力),度娘了一下發現也沒有demo,官網也沒有提供,好吧,只能讓我這種懶人自己來寫了。
相關代碼已在上面提供下載,這裏啓動了兩臺服務機,server 1 和server 2
服務端
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
new String[] { "classpath:consumer.xml" });
context.start();
DemoService demoService = (DemoService) context
.getBean("demoService");
while(true){
String hello = demoService.sayHello("word", "1");
String hello1 = demoService.sayHello("word", "2");
System.out.println(hello);
System.out.println(hello1);
}
}
這裏我們看到,demoSerivce.sayHello()方法的第一個參數相同。
直接啓動,結果如下,可以看到,所有的服務都是由機器2來提供的(也有可能都是1,主要看第一次是由那臺服務機提供服務)server 2 say: Hello word, today is 1
server 2 say: Hello word, today is 2
server 2 say: Hello word, today is 1
server 2 say: Hello word, today is 2
server 2 say: Hello word, today is 1
server 2 say: Hello word, today is 2
server 2 say: Hello word, today is 1
server 2 say: Hello word, today is 2
因此開始考慮,一致性是通過什麼來比對呢?看了一致性算法,果然沒看懂,那隻能試一試了。。。
開始考慮普通pojo
創建一個Students類,只有兩個屬性,name和age
Students s1 = new Students();
s1.setName("dog");
s1.setAge(1);
Students s2 = new Students();
s2.setName("cat");
s2.setAge(2);
DemoService demoService = (DemoService) context.getBean("demoService");
while (true) {
String hello = demoService.sayHello(s1);
String hello1 = demoService.sayHello(s2);
System.out.println(hello);
System.out.println(hello1);
}
運行結果如下,server 1 處理所有的cat,server2處理所有的dog
server 1 say: Hello cat, age is 2
server 2 say: Hello dog, age is 1
server 1 say: Hello cat, age is 2
server 2 say: Hello dog, age is 1
server 1 say: Hello cat, age is 2
server 2 say: Hello dog, age is 1
server 1 say: Hello cat, age is 2
server 2 say: Hello dog, age is 1
修改代碼位置,把students對象的創建移動到for循環內
測試結果,說明對比的不是元素屬性是否一致,而是和對象地址有關
server 1 say: Hello dog, age is 1
server 2 say: Hello cat, age is 2
server 2 say: Hello dog, age is 1
server 2 say: Hello cat, age is 2
server 2 say: Hello dog, age is 1
修改Students類的序列化參數,發現結果還是與地址有關
因此,最後項目修改如下,
第一次請求-->隨機生成一個token-->服務機創建臨時文件-->返回文件位置及token
第二次請求,攜帶token和文件位置-->通過token找到對應服務機-->文件加密-->業務結束
PS,由於比對的是地址值,因此需要設置一個web容器級別的token池,以保證對象一致
不過也有缺點,當消費機也是集羣模式的時候,該配置無效。。。因爲不同消費機的token地址不一致...
因此,如果是nginx做的前端負載均衡, 需要通過sticky來實現負載均衡(基於cookie),基本上由同一消費機提供服務,這樣就能保證token同一了
最後,還是用文件服務器比較好,一勞永逸。