目录
服务架构演变
单体架构
分布式架构
分布式架构需要考虑的问题
微服务
架构比较
微服务技术对比
服务拆分注意事项
案例
服务远程调用
RestTemplate
Eureka注册中心
RestTemplate存在的问题
服务调用考虑的问题
Eureka的作用
搭建EurekaServer
服务注册
服务发现
Ribbon负载均衡
负载均衡流程
负载均衡策略更改
Ribbon加载方式
微服务开发,实现充分解耦
将业务的所有功能集中在一个项目中开发,打成一个包部署
优点:架构简单、部署成本低
缺点:耦合度高
根据业务功能对系统进行拆分,每个业务模块作为独立项目开发,成为一个服务
优点:降低服务耦合、有利于服务升级拓展
缺点:成本上升,需要搭建集群等
微服务是一种经过良好架构设计的分布式架构方案。
微服务架构特征:
数据准备,两个数据库中分别有一个表
创建项目
有一种远程调用方式为A模块访问B模块的某个方法url地址,然后B模块返回结果给A模块。
现在我们需要实现一个查询订单的功能,这里需要订单模块像用户模块发起一个查询用户的请求。发起请求我们可以采用RestTemplate来实现
首先在Order的引导类中将RestTemplate加载为Bean
@MapperScan("cn.itcast.order.mapper")
@SpringBootApplication
@EnableFeignClients(basePackages = "com.zmt.clients")
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
在OrderService中使用RestTemplate
@Service
public class OrderService {
@Autowired
private OrderMapper orderMapper;
@Autowired
private RestTemplate restTemplate;
public Order queryOrderById(Long orderId) {
// 1.查询订单
Order order = orderMapper.findById(orderId);
//利用RestTemplate查询
String url="http://localhost:8081/user/"+order.getUserId();
//发送请求,得到JSON对象,如果给定需要转化的对象,则会转换为Java对象
User user = restTemplate.getForObject(url, User.class);
order.setUser(user);
// 4.返回
return order;
}
}
采用硬编码的方式去调用服务。不符合分布式中集群的使用场景。
当服务器启动后,会主动将自己的信息注册到Eureka-server中,当一个服务器需要远程调用另一个服务器中心方法时,需要从Eureka-server中拉去对应的地址信息,如果存在多个地址,则采用负载均衡的策略调用对应服务器。存活的服务器每三十秒向Eureka-server中发送一次心跳,当Eureka-server超过30秒没有接收到心跳,则会将对应的地址从注册中心中剔除。防止其他服务器调用到对应地址服务器。
新建一个Maven项目,并配置如下依赖
cloud-demo
cn.itcast.demo
1.0
4.0.0
com.zmt
eureka-serve
org.springframework.cloud
spring-cloud-starter-netflix-eureka-server
编写启动类,并添加注解
@SpringBootApplication
@EnableEurekaServer//开启Eureka服务
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class,args);
}
}
添加配置文件
server:
port: 8082
spring:
application:
name: eureka-serve # 服务名称
eureka:
client:
register-with-eureka: true #false 标识不向注册中心注册自己
fetch-registry: false # false 表示自己就是注册中心,维护服务实例即可,不需要去检索服务
service-url: # eureka的地址信息
defaultZone: http://127.0.0.1:8082/eureka/
随后启动服务
点击进入Eureka界面
现在将用户模块与订单模块注册到Eureka-Server中,需要引入Eureka-Client依赖,并添加配置文件
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
spring:
application:
name: xxx-server
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:8082/eureka/
之后启动服务观察Eureka页面
此时实例数都分别为1,现在测试集群下的实例,一个模块启动多个服务。具体操作如下
启动后观察
在RestTemplate加载为Bean的方法上添加@LocdBalanced注解(意为负载均衡策略),用服务提供者的服务名进行远程调用。
@Bean
@LoadBalanced//负载均衡策略
public RestTemplate restTemplate(){
return new RestTemplate();
}
public Order queryOrderById(Long orderId) {
// 1.查询订单
Order order = orderMapper.findById(orderId);
//将具体的地址修改为服务名称
String url="http://user-server/user/"+order.getUserId();
//发送请求,得到JSON对象,如果给定需要转化的对象,则会转换为Java对象
User user = restTemplate.getForObject(url, User.class);
order.setUser(user);
// 4.返回
return order;
}
访问地址观察结果
使用RestTemplate访问服务名的地址实际上并不是真实的url地址,通过Ribbon将格式转化,从eureka-server中拉去需要转化的信息,然后返回服务列表由Ribbon来决定使用哪个地址
发现服务后,具体如何请求到对应的服务器上,接下来看源码分析
getServer()方法去做具体均衡策略
点击进去观察
进入chooseServer()方法观察
rule中存在如下几个实现类来决定如何实现分配
消费者通过服务者提供的服务名进行远程调用时,请求被Ribbon负载均衡所拦截,Ribbon去eureka-server拉取生产者的信息,eureka-server返回服务列表给Ribbon,由Ribbon选择访问哪个服务器具体拦截方式,通过RestTemplate上面的@LocdBalanced注解拦截,拦截通过RestTemplate发送的请求
1、全局更改(该消费者无论访问哪个服务都使用该策略)
在消费者的启动类下加入IRule的Bean(即,重写默认的IRule),return一个需要的负载均衡策略对象。
2、针对某一生产者的修改
在application.yml中配置生产者的服务名以及负载均衡策略。
user-server: #生产者服务名称
ribbon:
NFLoadBalancerRuleClassName: com.netflix.Loadbalancer.RandomRule #选择负载均衡策略
Ribbon默认采用懒加载方式。也就是用到的时候才会进行加载,这就决定了,第一次访问时,耗时会长一些。也可以在配置文件中选择饥饿加载。具体配置如下
ribbon:
eager-load:
enabled: true #开启饥饿加载
clients:
- user-server
- xxx-server