笔记74 微服务笔记1
一、远程调用
无论是微服务还是SOA,都面临着服务间的远程调用。常见的远程调用方式有两种:RPC和Http
1.RPC(Remote Procedure Call 远程过程调用)
是一个计算机通信协议。该协议允许运行于一台计算机的程序调用另一台计算机的子程序。那么如何实现RPC?
<1>要实现远程调用,肯定需要通过网络传输数据。A程序提供服务,B程序通过网络将请求参数传递给A,A本地执行后得到结果,再将结果返回给程序B。(采用哪种传输协议?传输的数据格式是什么?)
<2>对调用过程进行封装。
注:采用动态代理进行封装。
假设要对UserService中的queryUserById方法进行调用,那么需要定义一个UserService的接口,里面包含方法queryUserById,然后用动态代理来代理这个接口,当有请求调用queryUserById这个方法时,就启用代理,在动态代理的内部建立socket对请求进行接收和发送。
2.HTTP
Http协议:超文本传输协议,是一种应用层协议。规定了网络传输的请求格式、响应格式、资源定位和操作的方式等。但是底层采用什么网络传输协议,并没有规定,不过现在都是采用TCP协议作为底层传输协议。说到这里,大家可能觉得,Http与RPC的远程调用非常像,都是按照某种规定好的数据格式进行网络通信,有请求,有响应。没错,在这点来看,两者非常相似,但是还是有一些细微差别。
二、遇到的问题
1.通用mybatis中,不能使用int,必须使用Integer。
三、实现服务调用
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.分布式服务所面临的问题:
-
-
-
如何自动注册和发现
-
如何实现状态监管
-
如何实现动态路由
-
-
服务如何实现负载均衡
-
服务如何解决容灾问题
-
服务如何实现统一配置
-
四、