1、遠程調用java
不管是微服務仍是SOA,都面臨着服務間的遠程調用。常見的遠程調用方式有兩種:RPC和Httpspring
1.RPC(Remote Procedure Call 遠程過程調用)apache
是一個計算機通訊協議。該協議容許運行於一臺計算機的程序調用另外一臺計算機的子程序。那麼如何實現RPC?網絡
<1>要實現遠程調用,確定須要經過網絡傳輸數據。A程序提供服務,B程序經過網絡將請求參數傳遞給A,A本地執行後獲得結果,再將結果返回給程序B。(採用哪一種傳輸協議?傳輸的數據格式是什麼?)mybatis
<2>對調用過程進行封裝。app
注:採用動態代理進行封裝。負載均衡
假設要對UserService中的queryUserById方法進行調用,那麼須要定義一個UserService的接口,裏面包含方法queryUserById,而後用動態代理來代理這個接口,當有請求調用queryUserById這個方法時,就啓用代理,在動態代理的內部創建socket對請求進行接收和發送。socket
2.HTTP分佈式
Http協議:超文本傳輸協議,是一種應用層協議。規定了網絡傳輸的請求格式、響應格式、資源定位和操做的方式等。可是底層採用什麼網絡傳輸協議,並無規定,不過如今都是採用TCP協議做爲底層傳輸協議。說到這裏,你們可能以爲,Http與RPC的遠程調用很是像,都是按照某種規定好的數據格式進行網絡通訊,有請求,有響應。沒錯,在這點來看,二者很是類似,可是仍是有一些細微差異。ide
2、遇到的問題
1.通用mybatis中,不能使用int,必須使用Integer。
3、實現服務調用
1.use-service-demo:一個提供根據id查詢用戶的微服務
<1>controller
1 @RestController 2 @RequestMapping("user") 3 public class UserController { 4 5 @Autowired 6 private UserService userService; 7 8 @GetMapping("/{id}") 9 public User getOne(@PathVariable("id") Integer id){ 10 return userService.queryById(id); 11 } 12 13 }
<2>service
1 public interface UserService { 2 User queryById(Integer id); 3 }
1 @Service 2 public class UserServiceImpl implements UserService { 3 4 @Autowired 5 private UserMapper userMapper; 6 7 @Override 8 public User queryById(Integer id) { 9 return userMapper.selectByPrimaryKey(id); 10 } 11 12 13 14 }
<3>dao
使用第三方插件通用mapper。
1 @org.apache.ibatis.annotations.Mapper 2 @Repository 3 public interface UserMapper extends Mapper<User> { 4 5 }
<4>pojo
1 public class User implements Serializable { 2 3 private static final long serialVersionUID = 1L; 4 5 @Id 6 @GeneratedValue(strategy = GenerationType.IDENTITY) 7 private Integer id; 8 private String name; 9 10 public Integer getId() { 11 return id; 12 } 13 14 public void setId(Integer id) { 15 this.id = id; 16 } 17 18 public String getName() { 19 return name; 20 } 21 22 public void setName(String name) { 23 this.name = name; 24 } 25 26 @Override 27 public String toString() { 28 return "User{" + 29 "id=" + id + 30 ", name='" + name + '\'' + 31 '}'; 32 } 33 }
2.consumer-demo:一個服務調用者,經過RestTemplate遠程調用user-service-demo
先在CunsumerDemoApplication.java註冊bean
1 //發送http請求,使用spring的RestTemplate模板工具類 2 @Bean 3 public RestTemplate restTemplate(){ 4 return new RestTemplate(new OkHttp3ClientHttpRequestFactory()); 5 }
<1>controller
1 @RestController 2 @RequestMapping("hello") 3 public class UserController { 4 @Autowired 5 private UserService userService; 6 7 8 @GetMapping("/list") 9 public List<User> queryUsers(@RequestParam("ids") List<Integer> ids){ 10 return userService.queryUserByIds(ids); 11 } 12 }
<2>service
1 @Service 2 public class UserService { 3 @Autowired 4 private UserDao userDao; 5 6 public List<User> queryUserByIds(List<Integer> ids){ 7 List<User> users=new ArrayList<>(); 8 for (Integer id:ids){ 9 User user=this.userDao.queryUserById(id); 10 users.add(user); 11 } 12 return users; 13 } 14 }
<3>dao
1 @Repository 2 public class UserDao { 3 @Autowired 4 private RestTemplate restTemplate; 5 6 public User queryUserById(Integer id){ 7 String url="http://localhost:8081/user/"+id; 8 return this.restTemplate.getForObject(url,User.class); 9 } 10 }
<4>pojo
1 public class User implements Serializable { 2 3 private static final long serialVersionUID = 1L; 4 5 private Integer id; 6 private String name; 7 8 public Integer getId() { 9 return id; 10 } 11 12 public void setId(Integer id) { 13 this.id = id; 14 } 15 16 public String getName() { 17 return name; 18 } 19 20 public void setName(String name) { 21 this.name = name; 22 } 23 24 @Override 25 public String toString() { 26 return "User{" + 27 "id=" + id + 28 ", name='" + name + '\'' + 29 '}'; 30 } 31 }
3.流程圖
4.測試
啓動服務者和消費者
調用服務
5.存在的問題
consumer須要記憶user-service的地址,若是出現變動,可能得不到通知,地址將失效
consumer不清楚user-service的狀態,服務宕機也不知道
user-service只有1臺服務,不具有高可用性
即使user-service造成集羣,consumer還需本身實現負載均衡
6.分佈式服務所面臨的問題:
如何自動註冊和發現
如何實現狀態監管
如何實現動態路由
服務如何實現負載均衡
服務如何解決容災問題
服務如何實現統一配置
4、