微服务技术栈2022-学习这一篇就够了

一.微服务技术栈

1.1认识微服务

1.1.1内容

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.1.2三种技术对比

在这里插入图片描述

1.1.3企业常见的四种情况

在这里插入图片描述

1.1.4SpringCloud

官网:https://spring.io/projects/spring-cloud
在这里插入图片描述
注意版本兼容问题
在这里插入图片描述

1.2分布式服务架构案例

1.2.1服务拆分

在这里插入图片描述
1)导入sql
2)pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>cloud-demo</artifactId>
        <groupId>cn.itcast.demo</groupId>
        <version>1.0</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>user-service</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--mybatis-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
    </dependencies>
    <build>
        <finalName>app</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

3)运行测试
在这里插入图片描述
4)总结
在这里插入图片描述

1.2.2 服务远程调用

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.3eureka注册中心

1.3.1eureka的作用

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.3.2eureka服务的搭建
  1. 引入eureka依赖
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

2)编写启动类

给eureka-server服务编写一个启动类,一定要添加一个@EnableEurekaServer注解,开启eureka的注册中心功能:

package cn.itcast.eureka;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer
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

4)启动并访问
http://127.0.0.1:10086 效果如下
在这里插入图片描述

1.3.2eureka服务注册

1)依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

2)配置文件

spring:
  application:
    name: userservice
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:10086/eureka

3)启动多个user-service实例
在这里插入图片描述
在这里插入图片描述
4)启动
在这里插入图片描述
在这里插入图片描述

1.3.2eureka服务发现

1)依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

2)配置文件

spring:
  application:
    name: orderservice
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:10086/eureka

3)服务拉取和负载均衡
在order-service的OrderApplication中,给RestTemplate这个Bean添加一个@LoadBalanced注解:
在这里插入图片描述
修改order-service服务中的cn.itcast.order.service包下的OrderService类中的queryOrderById方法。修改访问的url路径,用服务名代替ip、端口:
在这里插入图片描述

1.4Ribbon负载均衡原理

Ribbon负载均衡
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

1.5nacos

1.5.1nacos注册中心
  1. 引入依赖
    在cloud-demo父工程的pom文件中的<dependencyManagement>中引入SpringCloudAlibaba的依赖:
<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>

然后在user-service和order-service中的pom文件中引入nacos-discovery依赖:

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

2)配置nacos地址
在user-service和order-service的application.yml中添加nacos地址:

spring:
  cloud:
    nacos:
      server-addr: localhost:8848
  1. 启动
    重启微服务后,登录nacos管理页面,页面如下
    在这里插入图片描述
    4)总结
    在这里插入图片描述
1.5.2nacos服务多级存储模型

在这里插入图片描述
在这里插入图片描述
修改user-service的application.yml文件,添加集群配置:

spring:
  cloud:
    nacos:
      server-addr: localhost:8848
      discovery:
        cluster-name: HZ # 集群名称

我们再次复制一个user-service启动配置,添加属性:

-Dserver.port=8083 -Dspring.cloud.nacos.discovery.cluster-name=SH

在这里插入图片描述
结果:
在这里插入图片描述

在这里插入图片描述

1.5.3nacos同集群优先的负载均衡

1)给order-service配置集群信息
修改order-service的application.yml文件,添加集群配置:

spring:
  cloud:
    nacos:
      server-addr: localhost:8848
      discovery:
        cluster-name: HZ # 集群名称

2)修改负载均衡规则
修改order-service的application.yml文件,修改负载均衡规则:

userservice:
  ribbon:
    NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule # 负载均衡规则 
1.5.4nacos服务权重设置

在这里插入图片描述
在这里插入图片描述

1.5.5nacos环境隔离

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
Nacos的服务实例分为两种l类型:

  • 临时实例:如果实例宕机超过一定时间,会从服务列表剔除,默认的类型。

  • 非临时实例:如果实例宕机,不会从服务列表剔除,也可以叫永久实例。

配置一个服务实例为永久实例:

spring:
  cloud:
    nacos:
      discovery:
        ephemeral: false # 设置为非临时实例

在这里插入图片描述

1.6 Nacos配置管理

1.6.1 统一配置管理

在这里插入图片描述
步奏1) nacos控制台配置信息
在这里插入图片描述
在这里插入图片描述

命名一般是服务名称+“-”+环境名称+“.yaml”,保证唯一性
2)引入nacos-config依赖
首先,在user-service服务中,引入nacos-config的客户端依赖:

<!--nacos配置管理依赖-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

3)添加bootstrap.yaml
然后,在user-service中添加一个bootstrap.yaml(或yml)文件,bootstrap.yml的优先级比application.yml的优先级要高,内容如下:

spring:
  application:
    name: userservice # 服务名称
  profiles:
    active: dev #开发环境,这里是dev 
  cloud:
    nacos:
      server-addr: localhost:8848 # Nacos地址
      config:
        file-extension: yaml # 文件后缀名

在这里插入图片描述
4)代码测试

@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @Value("${pattern.dateformat}")
    private String dateformat;
    
    @GetMapping("now")
    public String now(){
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern(dateformat));
    }
    // ...略
}

在这里插入图片描述

在这里插入图片描述

1.6.2 配置热更新

我们最终的目的,是修改nacos中的配置后,微服务中无需重启即可让配置生效,也就是配置热更新
要实现配置热更新,可以使用两种方式:
1)在@Value注入的变量所在类上添加注解@RefreshScope:
在这里插入图片描述

2)使用@ConfigurationProperties注解代替@Value注解。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.6.3 配置共享

在这里插入图片描述
在这里插入图片描述

优先级:
在这里插入图片描述

1.6.4 搭建Nacos集群

在这里插入图片描述

1.7 Feign远程调用

1.7.1Feign代替RestTemplate远程调用

1)引入依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

2)添加注解
在order-service的启动类添加注解@EnableFeignClients开启Feign的功能:
在这里插入图片描述
3)编写Feign的客户端
新建接口

package cn.itcast.order.client;

import cn.itcast.order.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@FeignClient("userservice")
public interface UserClient {
    @GetMapping("/user/{id}")
    User findById(@PathVariable("id") Long id);
}

4)总结
在这里插入图片描述

1.7.2自定义配置

在这里插入图片描述
下面以日志为例来演示如何自定义配置。

1.7.2.1配置文件方式
feign:  
  client:
    config: 
      userservice: # 针对某个微服务的配置
        loggerLevel: FULL #  日志级别 

或针对所有服务

feign:  
  client:
    config: 
      default: # 这里用default就是全局配置,如果是写服务名称,则是针对某个微服务的配置
        loggerLevel: FULL #  日志级别 

日志的级别分为四种:

  • NONE:不记录任何日志信息,这是默认值。
  • BASIC:仅记录请求的方法,URL以及响应状态码和执行时间
  • HEADERS:在BASIC的基础上,额外记录了请求和响应的头信息
  • FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据。
1.7.2.2Java代码方式
public class DefaultFeignConfiguration  {
    @Bean
    public Logger.Level feignLogLevel(){
        return Logger.Level.BASIC; // 日志级别为BASIC
    }
}

在这里插入图片描述
在这里插入图片描述

1.7.3Feign使用优化

在这里插入图片描述
这里我们用Apache的HttpClient来演示。
1)引入依赖

在order-service的pom文件中引入Apache的HttpClient依赖:

<!--httpClient的依赖 -->
<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-httpclient</artifactId>
</dependency>

2)配置连接池

在order-service的application.yml中添加配置:

feign:
  client:
    config:
      default: # default全局的配置
        loggerLevel: BASIC # 日志级别,BASIC就是基本的请求和响应信息
  httpclient:
    enabled: true # 开启feign对HttpClient的支持
    max-connections: 200 # 最大的连接数
    max-connections-per-route: 50 # 每个路径的最大连接数

1.7.4Feign最佳实践

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.7.5实现基于第二种 抽取的最佳实践

在这里插入图片描述
1)抽取
首先创建一个module,命名为feign-api:
在这里插入图片描述
在这里插入图片描述
在feign-api中然后引入feign的starter依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

然后,order-service中编写的UserClient、User、DefaultFeignConfiguration都复制到feign-api项目中
在这里插入图片描述
2)在order-service中使用feign-api
首先,删除order-service中的UserClient、User、DefaultFeignConfiguration等类或接口。

在order-service的pom文件中中引入feign-api的依赖:

<dependency>
    <groupId>cn.itcast.demo</groupId>
    <artifactId>feign-api</artifactId>
    <version>1.0</version>
</dependency>

修改order-service中的所有与上述三个组件有关的导包部分,改成导入feign-api中的包

3)重启测试
发现报错
在这里插入图片描述
这是因为UserClient现在在cn.itcast.feign.clients包下,

而order-service的@EnableFeignClients注解是在cn.itcast.order包下,不在同一个包,无法扫描到UserClient。
4)解决扫描包问题
在这里插入图片描述
方式2较好
在这里插入图片描述

1.8 Gateway服务网关

1.8.1为什么需要网关

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.8.2gateway快速入门

1)创建gateway模块在这里插入图片描述
引入依赖

<!--网关-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--nacos服务发现依赖-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

2)编写启动类
创建application.yml文件,内容如下:

server:
  port: 10010 # 网关端口
spring:
  application:
    name: gateway # 服务名称
  cloud:
    nacos:
      server-addr: localhost:8848 # nacos地址
    gateway:
      routes: # 网关路由配置
        - id: user-service # 路由id,自定义,只要唯一即可
          # uri: http://127.0.0.1:8081 # 路由的目标地址 http就是固定地址
          uri: lb://userservice # 路由的目标地址 lb就是负载均衡,后面跟服务名称
          predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
            - Path=/user/** # 这个是按照路径匹配,只要以/user/开头就符合要求

本例中,我们将 /user/**开头的请求,代理到lb://userservice,lb是负载均衡,根据服务名拉取服务列表,实现负载均衡。

4)重启测试
在这里插入图片描述
5)流程
在这里插入图片描述
在这里插入图片描述

1.8.3gateway路由断言工厂

我们在配置文件中写的断言规则只是字符串,这些字符串会被Predicate Factory读取并处理,转变为路由判断的条件
例如Path=/user/**是按照路径匹配,这个规则是由
org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory类来处理的,像这样的断言工厂在SpringCloudGateway还有十几个:
在这里插入图片描述

1.8.4过滤器工厂

1)种类
官网:https://spring.io/projects/spring-cloud-gateway
在这里插入图片描述
2)请求头过滤器

spring:
  cloud:
    gateway:
      routes:
      - id: user-service 
        uri: lb://userservice 
        predicates: 
        - Path=/user/** 
        filters: # 过滤器
        - AddRequestHeader=Truth, Itcast is freaking awesome! # 添加请求头

3)默认过滤器-所有服务都生效

spring:
  cloud:
    gateway:
      routes:
      - id: user-service 
        uri: lb://userservice 
        predicates: 
        - Path=/user/**
      default-filters: # 默认过滤项
      - AddRequestHeader=Truth, Itcast is freaking awesome! 

4)总结
在这里插入图片描述

1.8.5全局过滤器

1)作用
全局过滤器的作用也是处理一切进入网关的请求和微服务响应,与GatewayFilter的作用一样。区别在于GatewayFilter通过配置定义,处理逻辑是固定的;而GlobalFilter的逻辑需要自己写代码实现。
定义方式是实现GlobalFilter接口。

public interface GlobalFilter {
    /**
     *  处理当前请求,有必要的话通过{@link GatewayFilterChain}将请求交给下一个过滤器处理
     *
     * @param exchange 请求上下文,里面可以获取Request、Response等信息
     * @param chain 用来把请求委托给下一个过滤器 
     * @return {@code Mono<Void>} 返回标示当前过滤器业务结束
     */
    Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
}

在filter中编写自定义逻辑,可以实现下列功能:

  • 登录状态判断
  • 权限校验
  • 请求限流等
    2)自定义全局过滤器
@Order(-1)
@Component
public class AuthorizeFilter implements GlobalFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 1.获取请求参数
        MultiValueMap<String, String> params = exchange.getRequest().getQueryParams();
        // 2.获取authorization参数
        String auth = params.getFirst("authorization");
        // 3.校验
        if ("admin".equals(auth)) {
            // 放行
            return chain.filter(exchange);
        }
        // 4.拦截
        // 4.1.禁止访问,设置状态码
        exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
        // 4.2.结束处理
        return exchange.getResponse().setComplete();
    }
}

在这里插入图片描述

1.8.6过滤器执行顺序

在这里插入图片描述

在这里插入图片描述

1.8.7跨域问题

跨域:域名不一致就是跨域,主要包括:

  • 域名不同: www.taobao.com 和 www.taobao.org 和 www.jd.com 和 miaosha.jd.com

  • 域名相同,端口不同:localhost:8080和localhost8081

跨域问题:浏览器禁止请求的发起者与服务端发生跨域ajax请求,请求被浏览器拦截的问题

常见报错:
在这里插入图片描述

解决方式:
在gateway服务的application.yml文件中,添加下面的配置:

spring:
  cloud:
    gateway:
      # 。。。
      globalcors: # 全局的跨域处理
        add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题
        corsConfigurations:
          '[/**]':
            allowedOrigins: # 允许哪些网站的跨域请求 
              - "http://localhost:8090"
            allowedMethods: # 允许的跨域ajax的请求方式
              - "GET"
              - "POST"
              - "DELETE"
              - "PUT"
              - "OPTIONS"
            allowedHeaders: "*" # 允许在请求中携带的头信息
            allowCredentials: true # 是否允许携带cookie
            maxAge: 360000 # 这次跨域检测的有效期

在这里插入图片描述

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Cloud微服务技术栈中,mapping映射是指将一个请求URL映射到特定的处理方法上。Spring Cloud提供了一种灵活且方便的方式来实现请求的映射。 首先,我们可以使用注解`@RequestMapping`来定义一个处理请求的方法。该注解可以用于类级别和方法级别,用于定义访问路径和请求方法类型。通过在类级别上定义`@RequestMapping`注解,我们可以为该类的所有方法设置统一的URL前缀。例如,`@RequestMapping("/api/user")`会将路径"/api/user"映射到该类中的所有方法。 其次,Spring Cloud还提供了基于`@GetMapping`、`@PostMapping`等注解的请求映射方式。这些注解在处理GET、POST等常见HTTP方法时非常方便。例如,`@GetMapping("/api/user/{id}")`可以将路径中的变量{id}与方法参数进行绑定,以实现根据id查询用户的功能。 另外,我们还可以使用`@RequestParam`注解来绑定请求中的参数值。通过指定参数的名称和是否必需等属性,我们可以灵活地获取和验证请求参数。例如,`@GetMapping("/api/user") public User getUserById(@RequestParam("id") Long id)`可以将请求路径中的参数id绑定到方法参数id上。 除了上述基本的请求映射方式外,Spring Cloud还支持更复杂的映射逻辑。例如,我们可以使用`@PathVariable`注解来获取路径中的占位符变量,还可以使用`@RequestHeader`注解来绑定请求头的值。 总之,通过Spring Cloud的mapping映射机制,我们可以轻松地将请求映射到对应的处理方法上,实现微服务的具体功能。这种灵活和方便的映射方式是Spring Cloud微服务技术栈的重要组成部分。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值