微服务入门:服务拆分与Eureka
一、微服务概论
传统的服务架构大多为单体架构系统,也就是整个web应用最终打包成一个war包或jar进行部署
这种单体架构有以下优点
- 架构简单便于开发、测试
- 部署在服务器成本低
同时也存在以下缺点
- 耦合性高
就比如一个类似某米商城的web应用,在这个应中订单模块、用户功能等都在一个模块中,它们使用一个服务器和一个数据库,这样的程序耦合度比较高,不利于后期维护
微服务分布式架构
可以将上述的各个功能拆分成不同的模块,每个业务模块作为单独项目进行开发,然后对不同的模块进行部署,从而达到了一个解耦的作用
优点:
- 降低了服务耦合
- 有利于服务升级扩展
二、服务拆分
服务拆分就是将一个项目的不同功能拆分才一个服务,拆分服务有以下注意事项:
- 单一职责:不同微服务,不要重复开发相同业务
- 数据独立:不要访问其他微服务的数据库
- 面向服务:将自己的业务暴露为接口,供其他微服务调用
下面将使用RestTemplate来实现两个模块的服务之前的调用,首先先介绍RestTemplate
1、RestTemplate概述
RestTemplate支持所有的Restful风格方法,RestTemplate 对象在底层通过使用 java.net 包下的实现创建 HTTP 请求
RestTemplate 提供了以下API
方法名 | 描述 |
---|---|
getForObject | 通过GET请求获取响应结果 |
getForEntity | 通过GET请求获取ResponseEntity对象,其包含状态码、响应头和响应数据 |
headForHeaders | 通过HEAD请求资源返回所有的响应头信息 |
postForObject | 用POST请求创建资源,并返回响应数据中响应头的字段Location的数据 |
postForObject | 用Post请求创建资源,获得响应结果 |
put | 通过put方式请求来创建或者更新数据 |
delete | 通过delete方式删除资源 |
2、服务拆分实现
这里准备了两个服务,第一个是order-service与user-service
两个服务的数据库不同,因此不可以联合查询
order-service是用来管理订单信息,请求成功返回的信息有
- 订单id
- 价格price
- 商品名称name
- 数量num
- 用户的ID userId
- 用户信息user(需要从user-service中根据用户id查询)
user-service是管理用户信息,请求成功返回的信息有
- 用户id
- 用户名username
- 住址address
order-service前端控制器:根据id查询订单信息
@GetMapping("{orderId}")
public Order queryOrderByUserId(@PathVariable("orderId") Long orderId) {
// 根据id查询订单并返回
return orderService.queryOrderById(orderId);
}
public Order queryOrderById(Long orderId) {
// 1.查询订单
Order order = orderMapper.findById(orderId);
// 2.返回
return order;
}
user-service前端控制器:根据id查询用户信息
@GetMapping("/{id}")
public User queryById(@PathVariable("id") Long id) {
return userService.queryById(id);
}
public User queryById(Long id) {
return userMapper.findById(id);
}
思路:要想查询订单的信息返回的数据需要有用户信息,那只需要在service层查询出订单信息之后,再利用订单信息中的用户id,像Axios那样访问user-service层的接口,根据id获取到用户信息,接着返回一个User实体类,订单利用set方法给成员变量中的User赋值即可
首先,现在order-service模块将RestTemplate注入到spring容器中
@SpringBootApplication
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
/**
* 完成RestTemplate并注入到spring容器中
* @return
*/
//负载均衡
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
接着在service层访问user-service层的接口
public Order queryOrderById(Long orderId) {
// 1.查询订单
Order order = orderMapper.findById(orderId);
//2.利用RestTemplate查询用户
String url = "http://loaclhost:8081/user/"+order.getUserId();
//restTemplate传递一个User.clss过去目的是为了返回不是一个json,而是返回一个实体类
User user = restTemplate.getForObject(url, User.class);
//3.封装user信息
order.setUser(user);
// 4.返回
return order;
}
接下来同时运行两个服务,在浏览器上请求order-service的接口,就可以得到一条json数据
{
"id": 101,
"price": 699900,
"name": "Apple 苹果 iPhone 12 ",
"num": 1,
"userId": 1,
"user": {
"id": 1,
"username": "张三",
"address": "广东湛江"
}
}
三、Eureka注册中心
上面服务拆分部分不难看出,在restTemplate调用的url中,url以及耦合死了,这明显也是不利于后期的维护
并且如果有多个相同的服务该如何选择调用?
我们又怎么知道每个服务的健康情况?
因此,这里就需要Eureka注册中心
作用:
- 注册服务信息,服务提供者启动时向eureka注册自己的信息
- 拉去服务(user-service),根据服务名称向eureka拉取提供者信息
- 负载均衡(相同的服务选择哪一个?),从服务列表中挑选一个
- 远程调用
- 服务提供者每30s会向Eureka发送一次心跳续约,以便Eureka知道服务提供者的健康状况,心跳不正常者会被剔除
Eureka包含两个组件:Eureka Server和Eureka Client。
Eureka Server提供服务注册服务,各个节点启动后,会在Eureka Server中进行注册,这样EurekaServer中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观的看到。
Eureka Client是一个java客户端,用于简化与Eureka Server的交互,客户端同时也就是一个内置的、使用轮询(round-robin)负载算法的负载均衡器。
1、Eureka注册中心实现步骤
(1)新建一个模块,导入eureka客户端依赖
<!--eureka客户端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
(2)配置Eureka相关信息
spring:
application:
name: eurkaserber #服务名称
eureka:
client:
service-url: #eureka地址信息
defaultZone: http://127.0.0.1:10086/eureka
(3)打开Eureka自动装配开关
//eureka自动装配开关
@EnableEurekaServer
@SpringBootApplication
public class EurekaAplication {
public static void main(String[] args) {
SpringApplication.run(EurekaAplication.class, args);
}
}
(4)注册服务
-
先在要注册的服务中引入依赖
<!--eureka客户端--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
-
在要注册的服务填写有关Ereka配置信息
spring: application: name: userservice #userservice的服务名称 eureka: client: service-url: #eureka地址信息 defaultZone: http://127.0.0.1:10086/eureka
-
在order-service中添加负载均衡注解
@MapperScan("cn.itcast.order.mapper") @SpringBootApplication public class OrderApplication { public static void main(String[] args) { SpringApplication.run(OrderApplication.class, args); } /** * 完成RestTemplate并注入到spring容器中 * @return */ //负载均衡 @LoadBalanced @Bean public RestTemplate restTemplate(){ return new RestTemplate(); } }
-
order-service同上操作,只是服务名称改变
注意的是,千万不要端口号重复了,我这里Eureka的端口号是10086
操作到这里,就可以了,服务以及成功在Ereka中注册了,这时候将三个服务跑起来
用浏览器进入localhost:10086
可以看到注册的服务和其对应的接口地址
小知识:
如果想多开同一个服务,可以右键该服务,选择复制配置
然后更换里面的名称和端口号
-Dserver.port=8082
2、运行
修改order-service中的url地址,不需要将端口号写死了,只需要写服务名称即可
public Order queryOrderById(Long orderId) {
// 1.查询订单
Order order = orderMapper.findById(orderId);
//2.利用RestTemplate查询用户
String url = "http://userservice/user/"+order.getUserId();
//restTemplate传递一个User.clss过去目的是为了返回不是一个json,而是返回一个实体类
User user = restTemplate.getForObject(url, User.class);
//3.封装user信息
order.setUser(user);
// 4.返回
return order;
}
在浏览器上访问order-service的前端控制器,发现还是能返回相同json,说明配置成功!!!
{
"id": 101,
"price": 699900,
"name": "Apple 苹果 iPhone 12 ",
"num": 1,
"userId": 1,
"user": {
"id": 1,
"username": "张三",
"address": "广东湛江"
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/95006.html