motan+zookeeper搭建rpc服務
阿新 • • 發佈:2018-11-09
服務提供者
服務端的配置
<?xml version="1.0" encoding="UTF-8"?>
<!--suppress SpringFacetInspection -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:motan="http://api.weibo.com/schema/motan"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://api.weibo.com/schema/motan http://api.weibo.com/schema/motan.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd" >
<!-- enable autowire -->
<context:annotation-config/>
<!--motan服務配置-->
<bean id="empService" class="com.per.service.impl.EmpServiceImpl"/>
<motan:service interface="com.per.service.EmpService" ref="empService" export="demoMotan:8520" basicService="serviceBasicConfig" />
<!-- 註冊中心配置 使用不同註冊中心需要依賴對應的jar包。如果不使用註冊中心,可以把check屬性改為false,忽略註冊失敗。-->
<motan:registry regProtocol="zookeeper" name="zkRegistry" address="127.0.0.1:2181"/>
<!-- 協議配置。為防止多個業務配置衝突,推薦使用id表示具體協議。-->
<motan:protocol id="demoMotan" default="true" name="motan"
maxServerConnection="80000" maxContentLength="10485760"
maxWorkerThread="800" minWorkerThread="20"/>
<!-- 通用配置,多個rpc服務使用相同的基礎配置. group和module定義具體的服務池。export格式為“protocol id:提供服務的埠”-->
<motan:basicService export="demoMotan:8520"
group="demo-emp-rpc" accessLog="false" shareChannel="true" module="emp-rpc"
application="myMotanDemo" registry="zkRegistry" id="serviceBasicConfig"/>
</beans>
定義服務介面
package com.per.service;
import com.per.domain.Emp;
import java.util.List;
public interface EmpService {
public List<Emp> getAllEmp();
public Emp getEmpById(Integer id);
public Integer addEmp(Emp emp);
public Integer deleteEmp(Emp emp);
public Integer updateEmp(Emp emp);
}
定義domain,要實現Serializable介面
package com.per.domain;
import com.alibaba.fastjson.annotation.JSONField;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.beetl.sql.core.annotatoin.AutoID;
import org.beetl.sql.core.annotatoin.Table;
import java.io.Serializable;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "emp")
public class Emp implements Serializable {
@AutoID
private Integer id;
private String name;
@JSONField(name = "dept_id")
private Integer deptId;
}
服務提供者實現service介面
package com.per.service.impl;
import com.per.dao.EmpDao;
import com.per.domain.Emp;
import com.per.service.EmpService;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
public class EmpServiceImpl implements EmpService {
@Autowired
private EmpDao empDao;
@Override
public List<Emp> getAllEmp() {
System.out.println("getAllEmp");
List<Emp> list = empDao.all();
System.out.println(list);
return list;
}
@Override
public Emp getEmpById(Integer id) {
System.out.println("server1 id = " + id);
return empDao.createLambdaQuery().andEq(Emp::getId, id).single();
}
......
實現兩個服務提供者,另一個的配置的埠改為8521
<?xml version="1.0" encoding="UTF-8"?>
<!--suppress SpringFacetInspection -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:motan="http://api.weibo.com/schema/motan"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://api.weibo.com/schema/motan http://api.weibo.com/schema/motan.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- enable autowire -->
<context:annotation-config/>
<!--motan服務配置-->
<bean id="empService" class="com.per.service.impl.EmpServiceImpl"/>
<motan:service interface="com.per.service.EmpService" ref="empService" export="demoMotan:8521" basicService="serviceBasicConfig"/>
<!-- 註冊中心配置 使用不同註冊中心需要依賴對應的jar包。如果不使用註冊中心,可以把check屬性改為false,忽略註冊失敗。-->
<motan:registry regProtocol="zookeeper" name="zkRegistry" address="127.0.0.1:2181"/>
<!-- 協議配置。為防止多個業務配置衝突,推薦使用id表示具體協議。-->
<motan:protocol id="demoMotan" default="true" name="motan"
maxServerConnection="80000" maxContentLength="10485760"
maxWorkerThread="800" minWorkerThread="20"/>
<!-- 通用配置,多個rpc服務使用相同的基礎配置. group和module定義具體的服務池。export格式為“protocol id:提供服務的埠”-->
<motan:basicService export="demoMotan:8521"
group="demo-emp-rpc" accessLog="false" shareChannel="true" module="emp-rpc"
application="myMotanDemo" registry="zkRegistry" id="serviceBasicConfig"/>
</beans>
用springboot啟動,motan可能有bug,要加上MotanSwitcherUtil.setSwitcherValue(MotanConstants.REGISTRY_HEARTBEAT_SWITCHER, true);後才能正常提供服務。
public static void main(String[] args) {
new ClassPathXmlApplicationContext("application.xml");
MotanSwitcherUtil.setSwitcherValue(MotanConstants.REGISTRY_HEARTBEAT_SWITCHER, true);
System.out.println("server1 start!!!!");
}
客戶端
客戶端的配置,負載均衡配置為activeWeight
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:motan="http://api.weibo.com/schema/motan"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://api.weibo.com/schema/motan http://api.weibo.com/schema/motan.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--enabled autowired-->
<context:annotation-config/>
<!-- 註冊中心配置 -->
<!--<motan:registry regProtocol="zookeeper" name="registry" address="192.168.2.239:2181"/>-->
<motan:registry regProtocol="zookeeper" name="zkRegistry" address="127.0.0.1:2181"/>
<!-- motan協議配置 -->
<motan:protocol default="true" name="motan" haStrategy="failover"
loadbalance="activeWeight" maxClientConnection="10" minClientConnection="1"/>
<!-- 通用referer基礎配置 -->
<motan:basicReferer requestTimeout="200" accessLog="false"
retries="2" group="demo-emp-rpc" module="emp-rpc"
application="myMotanDemo" protocol="motan" registry="zkRegistry"
id="basicReferer" throwException="false" check="true"/>
<motan:referer id="empService" interface="com.per.service.EmpService"
connectTimeout="20000" requestTimeout="20000" basicReferer="basicReferer"/>
</beans>
客戶端同樣匯入service介面,路徑要與服務提供者一致
package com.per.service;
import com.per.domain.Emp;
import java.util.List;
public interface EmpService {
public List<Emp> getAllEmp();
public Emp getEmpById(Integer id);
public Integer addEmp(Emp emp);
public Integer deleteEmp(Emp emp);
public Integer updateEmp(Emp emp);
}
啟動客戶端
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:motan-client.xml");
EmpService empService = (EmpService) applicationContext.getBean("empService");
System.out.println("client start...");
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(empService.getEmpById(1));
}
System.out.println("end...");
}
執行結果
客戶端執行結果
服務提供者1的執行結果
服務提供者2的執行結果
修改負載均衡策略為consistent
<motan:protocol default="true" name="motan" haStrategy="failover"
loadbalance="consistent" maxClientConnection="10" minClientConnection="1"/>
服務提供者1的執行結果為
服務提供者2的執行結果為空
剩下的負載均衡策略請自行測試。
負載均衡策略有
- ActiveWeight(預設)
低併發度優先: referer 的某時刻的 call 數越小優先順序越高
由於 Referer List 可能很多,比如上百臺,如果每次都要從這上百個 Referer 或者最低併發的幾個,效能有些損耗,因此 random.nextInt(list.size()) 獲取一個起始的 index,然後獲取最多不超過 MAX_REFERER_COUNT 的狀態是 isAvailable 的 referer 進行判斷 activeCount. - Random:
隨機選擇。在一個截面上碰撞的概率高,但呼叫量越大分佈越均勻,而且按概率使用權重後也比較均勻,有利於動態調整提供者權重。 - RoundRobin
輪循選擇,呼叫比較均勻 - LocalFirst
本地服務優先獲取策略,對referers根據ip順序查詢本地服務,多存在多個本地服務,獲取Active最小的本地服務進行服務。
當不存在本地服務,但是存在遠端RPC服務,則根據ActivWeight獲取遠端RPC服務
當兩者都存在,所有本地服務都應優先於遠端服務,本地RPC服務與遠端RPC服務內部則根據ActiveWeight進行 - Consistent
一致性 Hash,相同引數的請求總是發到同一提供者 - ConfigurableWeight
權重可配置的負載均衡策略