微服务架构
1.架构
- 单体架构:简单方便,高度耦合,扩展性差,适合小型项目。例如:学生管理系统
- 分布式架构:松耦合,扩展性好,但架构复杂,难度大。适合大型互联网项目,例如:京东、淘宝
- 微服务:一种良好的分布式架构方案
①优点:拆分粒度更小、服务更独立、耦合度更低
②缺点:架构非常复杂,运维、监控、部署难度提高
- SpringCloud是微服务架构的一站式解决方案,集成了各种优秀微服务功能组件
2.服务拆分
服务拆分原则
这里我总结了微服务拆分时的几个原则:
- 不同微服务,不要重复开发相同业务
- 微服务数据独立,不要访问其它微服务的数据库
- 微服务可以将自己的业务暴露为接口,供其它微服务调用
3.服务的远程调用
第一步:注册所需要的bean对象
@SpringBootConfiguration
public class RestTemplateConfig {
//.注册spring发送http请求RestTemplate
@Bean
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
第二步,一般在service里面发送请求,这里的user-service我们写在另一个module里面
@Service
public class OrderService { //这里我们发送的是get请求
@Autowired
private OrderMapper orderMapper;
@Autowired
private RestTemplate restTemplate;
public Order queryOrderById(Long orderId) {
// 1.查询订单
Order order = orderMapper.findById(orderId);
//2.访问路径
String url = "http://localhost:8081/user/"+ order.getUserId();
//3.利用RestTemplate发送http请求,查询order当中的userid所对应的对象
User user = restTemplate.getForObject(url, User.class);
// 4.返回
order.setUser(user);
return order;
}
}
4.Eureka
1.Eureka的结构和作用
问题1:order-service如何得知user-service实例地址?
获取地址信息的流程如下:
- user-service服务实例启动后,将自己的信息注册到eureka-server(Eureka服务端)。这个叫服务注册
- eureka-server保存服务名称到服务实例地址列表的映射关系
- order-service根据服务名称,拉取实例地址列表。这个叫服务发现或服务拉取问题2:order-service如何从多个user-service实例中选择具体的实例?
- order-service从实例列表中利用负载均衡算法选中一个实例地址
- 向该实例地址发起远程调用问题3:order-service如何得知某个user-service实例是否依然健康,是不是已经宕机?
- user-service会每隔一段时间(默认30秒)向eureka-server发起请求,报告自己状态,称为心跳
- 当超过一定时间没有发送心跳时,eureka-server会认为微服务实例故障,将该实例从服务列表中剔除
- order-service拉取服务时,就能将故障实例排除了
2.搭建Eureka服务
这是一般重新创建一个moduo来作为eureka服务
(1)依赖文件
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
(2)编写启动类
在启动类加入注解::
@SpringBootApplication
@EnableEurekaServer // Eureka启动注解
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}
(3)配置文件
server:
port: 10086
spring:
application:
name: eureka-server #配置服务器名称
eureka:
client:
service-url: #配置服务器地址
defaultZone: http://127.0.0.1:10086/eureka
3.注册eureka-server服务
依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
yaml配置
spring:
application:
name: orderservice #服务器名称
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka 服务器网址
4.服务拉取和负载均衡DOTO
服务发现
- 引入eureka-client依赖
- 在application.yml中配置eureka-client地址
- 给RestTemplate添加@LoadBalanced注解
- 用服务提供者的服务名称远程调用
5.负载均衡DOTO图要换
1.流程图
基本流程
拦截我们的RestTemplate请求http://userservice/user/1
- RibbonLoadBalancerClient会从请求url中获取服务名称,也就是user-service
- DynamicServerListLoadBalancer根据user-service到eureka拉取服务列表
- eureka返回列表,localhost:8081、localhost:8082
- IRule利用内置负载均衡规则,从列表中选择一个,例如localhost:8081
- RibbonLoadBalancerClient修改请求地址,用localhost:8081替代userservice,得到http://localhost:8081/user/1,发起真实请求
2.负载均衡策略IRule(修改eureka拉取服务后选择的方式)
一般都是在消费者那里配置(即使用了服务远程调用),如果配置的是bean,就是全局的,如果在yml文件当中配置,就是针对单个服务的。
bean方式配置
//配置负载均衡调用选择服务的方式,这是随机方式
@Bean
public IRule randomRule(){
return new RandomRule();
}
yml文件配置
userservice: #配置userservice负载均衡规则
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
饥饿加载
Ribbon默认是采用懒加载,即第一次访问时才会去创建LoadBalanceClient,请求时间会很长。
而饥饿加载则会在项目启动时创建,降低第一次访问的耗时,通过下面配置开启饥饿加载:
ribbon:
eager-load:
enabled: true 开启饥饿加载
clients: userservice 指定饥饿加载的服务器名称
Nacos
1.nacos和eureke对比
1.Nacos与eureka的共同点
1.都支持服务的注册和服务的拉取
2.都支持服务提供者心跳方式做健康检测
2.Nacos与eureka的不同
1.Nacos支持服务端主动检测提供者状态:临时实例采用心跳模式,非临时实例采用主动检测模式
2.临时实例心跳不正常会被剔除,非临时实例则不会被剔除
3.Nacos支持服务列表更变的消息推送模式,服务列表更新更及时
4.Nacos集群默认采用AP方式,当集群中存在非临时实例时,采用CP模式:Eureka采用AP方式
2.Nacos使用(比eureka服务更加丰富)
1.启动命令
bin目录下:startup.cmd -m standalone(后面单词意思是单机启动)
2.在父配置文件当中添加依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.2.6.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
3.在客户端添加依赖和配置文件
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
4.yaml配置文件
spring:
cloud:
nacos:
server-addr: lcalhost:8848
2.Nacos多级存储模型(负载均衡)
spring:
cloud:
nacos:
server-addr: localhost:8848
discovery:
cluster-name: HZ # 集群名称
但是要是想让消费者也按照根据集群选取服务器的方式,也得配置集群名称
修改order-service的application.yml文件,修改负载均衡规则:
```yaml
userservice:
ribbon:
NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule # 负载均衡规则
```
3.在nacos发布配置信息
第一步
idea当中
第二部:在配置文件当中添加依赖
<!--nacos配置管理依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
第三部:在resources添加bootstrap.yaml,因为这个配置文件优先级在application.yml配置文件之前,所以会先读取这个配置文件,在与本身配置文件合并使用
```yaml
spring:
application:
name: userservice # 服务名称
profiles:
active: dev #开发环境,这里是dev
cloud:
nacos:
server-addr: localhost:8848 # Nacos地址
config:
file-extension: yaml # 文件后缀名
3.配置热更新
需要我们调用我们的配置在Nacos配置文件当中的配置的话,使用热部署可以使用下面两种方式进行
第一种方式就是上面统一配置管理的查看是否调用
第二种配置,就是你创建一个pojo类来获取配置文件里的属性(第三方注入bean对象)
nacos总结
nacos配置更改后,微服务可以实现热更新,方式:
1.通过@Value注解注入,结合@RefreshScope来刷新
2.通过@ConfigurationProperties注入,自动刷新
注意事项:
不是所有的配置都合适放在配置中心,维护起来比较麻烦
建议将一些关键的参数,需要运行时调整的参数放到nacos配置中心,一般是自定义配置
3.多环境共享配置
不管是bootstrap里面使用的是一种active开发环境配置,服务名。yaml配置一定会读取,所以我们使用它作为共享文件的配置
总结:微服务会从nacos读取配置文件:
1.服务名-spring.profile.yaml,环境配置
2.服务名.yaml,默认配置,多环境共享
优先级
服务名-环境.yaml>服务名.yaml>本地配置
4.nacos集群的搭建
我们在同一台电脑上设置了多个caose,所以注意端口号不能冲突
文件在java包下的springcloud/基础篇/02里面
Feign
1.远程调用,替换ReatTemlate发送http请求
第一部:引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
第二部:在需要使用feign的服务启动类上添加注解
@EnableFeignClients //feign启动注解
第三步:编写Feign客户端
@FeignClient("userservice")//服务名称
public interface UserClient {
@GetMapping("/user/{id}") //请求路径参数等
User findById(@PathVariable("id")Long id);
第四步调用:
直接创建接口对象,调用方法