微服务
认识微服务
单体架构:将业务的所有功能集中在一个项目中开发,打成一个包部署。优点:架构简单。部署成本低。缺点:耦合度高。
分布式架构:根据业务功能对系统进行拆分,每个业务模块作为独立项目开发,称为一个服务。优点:降低服务耦合。有利于服务升级拓展。
微服务是一种经过良好架构设计的分布式架构方案,微服务架构特征:
- 单一职责:微服务拆分粒度更小,每一个服务都对应唯一的业务能力,做到单一职责,避免重复业务开发。
- 面向服务:微服务对外暴露业务接口。
- 自治:团队独立、技术独立、数据独立、部署独立。
- 隔离性强:服务调用做好隔离、容错、降级,避免出现级联问题。
微服务这种方案需要技术框架来落地,全球的互联网公司都在积极尝试自己的微服务落地技术。在国内最知名的就是SpringCloud和阿里巴巴的Dubbo。
Springcloud
SpringCloud是目前国内使用最广泛的微服务框架。官网地址:https://spring.io/projects/spring-cloud
SpringCloud集成了各种微服务功能组件,并基于SpringBoot实现了这些组件的自动装配,从而提供了良好的开箱即用体验:
- 服务注册发现:Eureka, Nacos, Consul
- 服务远程调用:OpenFeign, Dubbo
- 服务链路监控:Zipkin, Sleuth
- 统一配置管理:SpringCloudConfig, Nacos
- 统一网关路由:SpringcloudGateway、 Zuul
- 流控、降级、保护:Hystix, Sentinel
服务拆分及远程调用
服务拆分注意事项
- 不同微服务,不要重复开发相同业务
- 微服务数据独立,不要访问其它微服务的数据库
- 微服务可以将自己的业务暴露为接口,供其它微服务调用
- 微服务需要根据业务模块拆分,做到单一职责,不要重复开发相同业务
RestTemplate
在启动类中创建restTemplate并注入Spring容器
@MapperScan("cn.itcast.order.mapper") @SpringBootApplication public class OrderApplication {
public static void main(String[] args) { SpringApplication.run(OrderApplication.class, args); }
@Bean public RestTemplate restTemplate(){ return new RestTemplate(); }
}
|
调用
@Service public class OrderService { @Autowired private OrderMapper orderMapper; @Autowired private RestTemplate restTemplate; public Order queryOrderById(Long orderId) { Order order = orderMapper.findById(orderId); String url = "http://localhost:8081/user/"+order.getUserId(); User user = restTemplate.getForObject(url, User.class); order.setUser(user); return order; } }
|
提供者与消费者
- 服务提供者:一次业务中,被其它微服务调用的服务。(提供接口给其它微服务)
- 服务消费者:一次业务中,调用其它微服务的服务。(调用其它微服务提供的接口)
- 提供者与消费者角色其实是相对的。一个服务可以同时是服务提供者和服务消费者
Eureka注册中心
在Eureka架构中,微服务角色有两类:
- EurekaServer:服务端,注册中心。记录服务信息、心跳监控
- EurekaClient:客户端。
- Provider: 服务提供者注册自己的信息到EurekaServer。每隔30秒向EurekaServer发送心跳。
- consumer: 服务消费者根据服务名称从EurekaServer拉取服务列表,基于服务列表做负载均衡,选中一个微服务后发起远程调用
搭建Eureka服务
- 创建项目,引入依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency>
|
- 启动类添加
@EnableEurekaServer注解
@SpringBootApplication @EnableEurekaServer public class EurekaServerApplication { public static void main(String[] args) { SpringApplication.run(EurekaServerApplication.class, args); } }
|
- 配置文件application.yml
server: port: 10086 spring: application: name: eurekaserver eureka: client: service-url: defaultZone: http://127.0.0.1:10086/eureka
|
服务注册
- 引入依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
|
- 配置文件application.yml
server: port: 8081 spring: application: name: userservice eureka: client: service-url: defaultZone: http://127.0.0.1:10086/eureka
|
idea同一个工程启动多个服务:
- 右击要复制的服务,选择Copy Configuration
- 修改启动端口:点击Modify options,Add vm options,输入
-Dserver.port=8083,点击启动即可
服务发现
- 启动类RestTemplate中添加
@LoadBalanced,启动负载均衡策略。
@Bean @LoadBalanced public RestTemplate restTemplate(){ return new RestTemplate(); }
|
- 调用,将
localhost:8081 替换为 spring.application.name设置的值
@Service public class OrderService { @Autowired private OrderMapper orderMapper; @Autowired private RestTemplate restTemplate; public Order queryOrderById(Long orderId) { Order order = orderMapper.findById(orderId); String url = "http://userservice/user/"+order.getUserId(); User user = restTemplate.getForObject(url, User.class); order.setUser(user); return order; } }
|
Ribbon负载均衡
Ribbon的负载均衡规则是一个叫做IRule的接口来定义的,每一个子接口都是一种规则
通过定义IRule实现可以修改负载均衡规则,有两种方式:
- 代码方式,在启动类中,定义一个新的IRule
@Bean public IRule randomRule(){ return new RandomRule(); }
|
- 配置文件方式,在application.yml中
userservice: ribbon: NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
|
Ribbon饥饿加载
Ribbon默认是采用懒加载,即第一次访问时才会去创建LoadBalanceClient,请求时间会很长。而饥饿加载则会在项目启动时创建,降低第一次访问的耗时,
ribbon: eager-load: enabled: true clients: - userservice
|
Nacos注册中心
Nacos是阿里巴巴的产品,现在是SpringCloud中的一个组件。相比Eureka功能更加丰富,在国内受欢迎程度较高。
官网:https://nacos.io/zh-cn/
Nacos文档:https://nacos.io/zh-cn/docs/what-is-nacos.html
github地址:https://github.com/alibaba/nacos
安装运行
2.5.2版本下载:https://github.com/alibaba/nacos/releases/tag/2.5.2
Windows启动nacos(standalone代表着单机模式运行,非集群模式)
D:\soft\nacos-server-2.5.2\nacos\bin>startup.cmd -m standalone "nacos is starting with standalone"
,--. ,--.'| ,--,: : | Nacos 2.5.2 ,`--.'`| ' : ,---. Running in stand alone mode, All function modules | : : | | ' ,'\ .--.--. Port: 8848 : | \ | : ,--.--. ,---. / / | / / ' Pid: 24540 | : ' '; | / \ / \. ; ,. :| : /`./ Console: http://192.168.32.1:8848/nacos/index.html ' ' ;. ;.--. .-. | / / '' | |: :| : ;_ | | | \ | \__\/: . .. ' / ' | .; : \ \ `. https://nacos.io ' : | ; .' ," .--.; |' ; :__| : | `----. \ | | '`--' / / ,. |' | '.'|\ \ / / /`--' / ' : | ; : .' \ : : `----' '--'. / ; |.' | , .-./\ \ / `--'---' '---' `--`---' `----'
|
服务注册到Nacos
- 在父工程中添加spring-cloud-alibaba的管理依赖
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>2.2.5.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency>
|
- 在子工程中添加nacos客户端依赖
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency>
|
- 在application.yml中添加配置
spring: cloud: nacos: server-addr: localhost:8848
|
- 启动之后在nacos控制台,服务管理-服务列表可以看到服务
nacos服务分级存储模型
服务跨集群调用问题:服务调用尽可能选择本地集群的服务,跨集群调用延迟较高。本地集群不可访问时,再去访问其它集群
设置实例的集群属性,在application.yml中添加配置 spring.cloud.nacos.discovery.cluster-name属性,SH表示集群名称为上海
spring: cloud: nacos: server-addr: localhost:8848 discovery: cluster-name: SH
|