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、