SpringCloud

本文详细介绍了微服务架构的概念,包括单体架构与微服务架构的区别,SpringCloud在微服务中的集成,服务拆分的原则,以及如何利用OpenFeign进行远程调用和网关的配置。重点讲述了服务注册中心(如Nacos)的工作原理和在实际项目中的应用。
摘要由CSDN通过智能技术生成

一、认识微服务

1、单体架构

单体架构:将业务的所有功能集中在一个项目中开发,打成一个包部署。

优点:架构简单、部署成本低。

缺点:团队协作成本高、系统发布效率低、系统可用性差。

2、微服务架构

微服务架构:是服务化思想指导下的一套最佳实践架构方案。服务化,就是把单体架构中的功能模块拆分成多个独立的项目。

粒度小、团队自治、服务自治

官网地址:https://spring.io/projects/spring-cloud.

SpringCloud集成了各种微服务功能组件,并基于SpringBoot实现了这些组件的自动装配,从而提供了良好的开箱即用体验:

服务注册发现:Eureka、Nacos、Consul

统一配置管理:SpringCloudConfig、Nacos

服务远程调用:OpenFeign、Dubbo

统一网关路由:SpringCloudGateway、Zuul

服务链路监控:Zipkin、Sleuth

流控、降级、保护:Hystix、Sentinel

二、拆分原则

一、什么时候拆分

1、创业型项目:先采用单体架构,快速开发,快速试错。随着规模扩大,逐渐拆分。

2、确定的大型项目:资金充足,目标明确,可以直接选择微服务架构,避免后续拆分的麻烦。

二、怎么拆分

1、从拆分目标来说,要做到:

高内聚:每个微服务的职责要尽量单一,包含的业务相互关联度高、完整度高。

低耦合:每个微服务的功能要相对独立,尽量减少对其它微服务的依赖。

2、从拆分方式来说,一般包含两种方式:

纵向拆分:按照业务模块来拆分。

横向拆分:抽取公共服务,提高复用性。

三、总结

什么时候拆分微服务?

初创型公司或项目尽量采用单体项目,快速试错。随着项目发展到达一定规模再做拆分。

如何拆分微服务?

目标:高内聚、低耦合。

方式:纵向拆分、横向拆分。

拆分后碰到的第一个问题是什么,如何解决?

拆分后,某些数据在不同服务,无法直接调用本地方法查询数据。

利用RestTemplate发送Http请求,实现远程调用。

远程调用示例:

替代以前的:@AutoWired   private RestTemplate restTemplate;

使用

@RequiredArgsConstructor
private final RestTemplate restTemplate;
 // 1.获取商品id
 Set<Long> itemIds = vos.stream().map(CartVO::getItemId).collect(Collectors.toSet());
 // 2.查询商品
 ResponseEntity<List<ItemDTO>> response = restTemplate.exchange(
         "http://localhost:8081/items?ids={ids}",
         HttpMethod.GET,
         null,
         new ParameterizedTypeReference<List<ItemDTO>>() {
         },
         Map.of("ids",CollUtil.join(itemIds,","))
 );
 //解析响应
 if(!response.getStatusCode().is2xxSuccessful())
 {
    return;
 }
 List<ItemDTO> items=response.getBody();

 if (CollUtils.isEmpty(items)) {
     return;
 }

三、注册中心原理

服务治理中的三个角色分别是什么?

服务提供者:暴露服务接口,供其它服务调用

服务消费者:调用其它服务提供的接口

注册中心:记录并监控微服务各实例状态,推送服务变更信息

消费者如何知道提供者的地址?

服务提供者会在启动时注册自己信息到注册中心,消费者可以从注册中心订阅和拉取服务信息

消费者如何得知服务状态变更?

服务提供者通过心跳机制向注册中心报告自己的健康状态,当心跳异常时注册中心会将异常服务剔除,并通知订阅了该服务的消费者

当提供者有多个实例时,消费者该选择哪一个?

消费者可以通过负载均衡算法,从多个实例中选择一个

Nacos注册中心

nacos配置文件custom.dev:

PREFER_HOST_MODE=hostname
MODE=standalone
SPRING_DATASOURCE_PLATFORM=mysql
MYSQL_SERVICE_HOST=192.168.64.130
MYSQL_SERVICE_DB_NAME=nacos
MYSQL_SERVICE_PORT=3306
MYSQL_SERVICE_USER=root
MYSQL_SERVICE_PASSWORD=luohai
MYSQL_SERVICE_DB_PARAM=characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai

将上面的内容添加到文件中,取名随意,我这儿就取:custom.dev。然后在服务器的根目录下创建nacos文件夹,将配置文件上传至文件中。

执行docker命令:

docker run -d --name nacos --env-file ./nacos/custom.env -p 8848:8848 -p 9848:9848 -p 9849:9849 --restart=always nacos/nacos-server:v2.1.0-slim

查看日志:docker logs -f nacos

启动成功后访问:http://192.168.64.130:8848/nacos

账号密码都是:nacos

服务注册

服务注册步骤如下:

1、引入nacos discovery依赖:

<!--nacos服务注册发现-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-alibaba-nacos-discovery</artifactId>
<!--排除nacos中以前已经有的ribbon-->
<exclusions>
    <exclusion>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
    </exclusion>
</exclusions>
</dependency>

2、配置Nacos地址

cloud:
  nacos:
    discovery:
      server-addr: 192.168.64.130:8848

服务发现

消费者需要连接nacos以拉取和订阅服务,因此服务发现的前两步与服务注册是一样,后面再加上服务调用即可:

1、引入nacos discovery依赖(同上)

2、配置nacos地址(同上)

服务发现

private final DiscoveryClient discoveryClient;

private void handleCartItems(List<CartVO> vos) {    

// 1.根据服务名称,拉取服务的实例列表    

List<ServiceInstance> instances = discoveryClient.getInstances("item-service");    

// 2.负载均衡,挑选一个实例    

ServiceInstance instance = instances.get(RandomUtil.randomInt(instances.size()));  

  // 3.获取实例的IP和端口    

URI uri = instance.getUri();  

 // ... 略

}

四、OpenFeign

OpenFeign是一个声明式的http客户端,是SpringCloud在Eureka公司开源的Feign基础上改造而来。官方地址:https://github.com/OpenFeign/feign

其作用就是基于SpringMVC的常见注解,帮我们优雅的实现http请求的发送。

以前实现http调用是用如下的代码:

以上调用偏复杂,下面我们就利用OpenFeign这个微服务组件来实现简单化调用

OpenFeign已经被SpringCloud自动装配,实现起来非常简单:

1、引入依赖,包括OpenFeign和负载均衡组件SpringCloudLoadBalancer

<!--OpenFeign-->
<dependency>
<groupId>org.springframework.cloud</groupId>  
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency><!--负载均衡-->
<dependency>  
<groupId>org.springframework.cloud</groupId> 
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>

2、在启动类上通过@EnableFeignClients注解,启用OpenFeign功能

@EnableFeignClients

@SpringBootApplication

public class CartApplication { // ... 略 }

3、OpenFeign已经被SpringCloud自动装配,实现起来非常简单:

3.1 编写FeignClient

@FeignClient(value = "item-service")

public interface ItemClient {    

@GetMapping("/items")    

List<ItemDTO> queryItemByIds(@RequestParam("ids") Collection<Long> ids);

}

3.2 使用FeignClient,实现远程调用

List<ItemDTO> items = itemClient.queryItemByIds(List.of(1,2,3));

五、连接池

OpenFeign对Http请求做了优雅的伪装,不过其底层发起http请求,依赖于其它的框架。这些框架可以自己选择,包括以下三种:

HttpURLConnection:默认实现,不支持连接池

Apache HttpClient :支持连接池

OKHttp:支持连接池

在此我选用OKHttp

1、引入依赖

<!--ok-http-->
<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-okhttp</artifactId>
</dependency>

2、开启连接池功能

feign:
  okhttp:
    enabled: true # 开启OKHttp连接池支持

实例:

当定义的FeignClient不在SpringBootApplication的扫描包范围时,这些FeignClient无法使用。有两种方式解决:

指定FeignClient所在包

@EnableFeignClients(basePackages = "com.hmall.api.clients")

OpenFeign日志

OpenFeign只会在FeignClient所在包的日志级别为DEBUG时,才会输出日志。而且其日志级别有4级:

NONE:不记录任何日志信息,这是默认值。

BASIC:仅记录请求的方法,URL以及响应状态码和执行时间

HEADERS:在BASIC的基础上,额外记录了请求和响应的头信息

FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据。

由于Feign默认的日志级别就是NONE,所以默认我们看不到请求日志。

定义日志级别

要自定义日志级别需要声明一个类型为Logger.Level的Bean,在其中定义日志级别:

public class DefaultFeignConfig {    

 @Bean    

public Logger.Level feignLogLevel() {  

      return Logger.Level.FULL;    

   }

}

但此时这个Bean并未生效,要想配置某个FeignClient的日志,可以在@FeignClient注解中声明:

@FeignClient(value = "item-service", configuration = DefaultFeignConfig.class) 

如果想要全局配置,让所有FeignClient都按照这个日志配置,则需要在@EnableFeignClients注解中声明:

@EnableFeignClients(defaultConfiguration = DefaultFeignConfig.class)

OpenFeign总结

如何利用OpenFeign实现远程调用?

引入OpenFeign和SpringCloudLoadBalancer依赖

利用@EnableFeignClients注解开启OpenFeign功能

编写FeignClient 如何配置OpenFeign的连接池?

引入http客户端依赖,例如OKHttp、HttpClient 配置yaml文件,打开OpenFeign连接池开关 OpenFeign使用的最佳实践方式是什么?

由服务提供者编写独立module,将FeignClient及DTO抽取

如何配置OpenFeign输出日志的级别?

声明类型为Logger.Level的Bean 在@FeignClient或@EnableFeignClients注解上使用

六、网关

网关:就是网络的关口,负责请求的路由、转发、身份校验

在SpringCloud中网关的实现包括两种:

1、网关路由

配置文件:

spring:
  cloud:
    gateway:
      routes: 
        - id: item # 路由规则id,自定义,唯一
          uri: lb://item-service # 路由目标微服务,lb代表负载均衡
          predicates: # 路由断言,判断请求是否符合规则,符合则路由到目标
            - Path=/items/** # 以请求路径做判断,以/items开头则符合
        - id: xx
          uri: lb://xx-service
          predicates:
            - Path=/xx/**

2、创建gateway的项目,然后引入依赖

<dependencies>
    <!--common-->
    <dependency>
        <groupId>com.heima</groupId>
        <artifactId>hm-common</artifactId>
        <version>1.0.0</version>
    </dependency>
    <!--网关-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>
    <!--nacos服务注册发现-->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-alibaba-nacos-discovery</artifactId>
        <version>2.1.0.RELEASE</version>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <!--负载均衡-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-loadbalancer</artifactId>
    </dependency>
</dependencies>
<build>
    <finalName>${project.artifactId}</finalName>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值