微服务网关-Spring Cloud Gateway(下)

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
简介: 微服务网关-Spring Cloud Gateway(下)

正文


六、动态网关


动态网管可以使用配置中心,Redis,和数据库(我用的方法)

直接上代码,其实就是增删改查


package com.xiaojie.entity;
import lombok.Data;
/**
 * @Description: 路由实体类
 * @author: xiaojie
 * @date: 2021.07.15
 */
@Data
public class Route {
    private Integer id;
    private String routeId; //路由id
    private String routeName;//路由名称
    private String routePattern;//路由转发地址,
    private Integer routeType;//路由类型1从注册中心获取,0-转发地址
    private String routeUrl;//转发到的地址
    private Integer isOpen;//是否开放0-否1-开放
    private Integer isUse;//是否可用0-否1-开放
}


package com.xiaojie.mapper;
import com.xiaojie.entity.Route;
import org.apache.ibatis.annotations.*;
import java.util.List;
/**
 * @Description:Mapper接口
 * @author: xiaojie
 * @date: 2021.07.15
 */
public interface RouteMapper {
    @Select("SELECT id,routeId,routeName,routePattern,routeType,routeUrl,is_open isOpen,is_use isUse FROM `tb_route` WHERE is_open=1 and is_use=1;")
    List<Route> selectAllRoute();
    @Insert("INSERT INTO tb_route(routeId,routeName,routePattern,routeType,routeUrl,is_open,is_use) " +
            "VALUES(#{routeId},#{routeName},#{routePattern},#{routeType},#{routeUrl},#{isOpen},#{isUse})")
    @Options(useGeneratedKeys = true, keyProperty = "id")
    Integer add(Route route);
    @Update("UPDATE tb_route set routePattern=#{routePattern},routeUrl=#{routeUrl} WHERE routeId=#{routeId}")
    Integer update(Route route);
    @Delete("DELETE FROM tb_route WHERE routeId=#{routeId}")
    Integer delete(String routeId);
}


package com.xiaojie.service.impl;
import com.xiaojie.entity.Route;
import com.xiaojie.mapper.RouteMapper;
import com.xiaojie.service.RouteService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
import org.springframework.web.util.UriComponentsBuilder;
import reactor.core.publisher.Mono;
import java.net.URI;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * @Description:
 * @author: xiaojie
 * @date: 2021.07.15
 */
@Service
@Slf4j
public class RouteServiceImpl  implements RouteService, ApplicationEventPublisherAware {
    private ApplicationEventPublisher applicationEventPublisher;
    @Autowired
    private RouteMapper routeMapper;
    @Autowired
    private RouteDefinitionWriter routeDefinitionWriter;
    @Override
    public List<Route> getAll() {
        List<Route> routes = routeMapper.selectAllRoute();
        for (Route  route: routes){
            loadRoute(route);
        }
        return routes;
    }
    public void loadRoute(Route route) {
        RouteDefinition definition = new RouteDefinition();
        Map<String, String> predicateParams = new HashMap<>(8);
        PredicateDefinition predicate = new PredicateDefinition();
        FilterDefinition filterDefinition = new FilterDefinition();
        Map<String, String> filterParams = new HashMap<>(8);
        URI uri = null;
        if (1==route.getRouteType()) {
            // 如果配置路由type为1的话 则从注册中心获取服务地址
            uri = UriComponentsBuilder.fromUriString(route.getRouteUrl()).build().toUri();
        } else {
            uri = UriComponentsBuilder.fromHttpUrl(route.getRouteUrl()).build().toUri();
        }
        // 定义的路由唯一的id
        definition.setId(route.getRouteId());
        predicate.setName("Path");
        //路由转发地址
        predicateParams.put("pattern", route.getRoutePattern());
        predicate.setArgs(predicateParams);
        filterDefinition.setName("StripPrefix");
        filterParams.put("_genkey_0", "1");
        filterDefinition.setArgs(filterParams);
        definition.setPredicates(Arrays.asList(predicate));
        definition.setFilters(Arrays.asList(filterDefinition));
        definition.setUri(uri);
        routeDefinitionWriter.save(Mono.just(definition)).subscribe();
        this.applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this));
        log.info("路由刷新成功.............................");
    }
    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.applicationEventPublisher=applicationEventPublisher;
    }
}


定义接口,当修改路由之后,需要刷新路由规则


  @RequestMapping("/refreshGw")
    public Object refreshGw() {
        return routeService.getAll();
    }


SQL如下


/*
 Navicat MySQL Data Transfer
 Source Server         : 本地
 Source Server Type    : MySQL
 Source Server Version : 80024
 Source Host           : localhost:3306
 Source Schema         : my_test
 Target Server Type    : MySQL
 Target Server Version : 80024
 File Encoding         : 65001
 Date: 15/07/2021 15:25:24
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for tb_route
-- ----------------------------
DROP TABLE IF EXISTS `tb_route`;
CREATE TABLE `tb_route`  (
  `id` int NOT NULL AUTO_INCREMENT,
  `routeId` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '路由id',
  `routeName` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '路由名称',
  `routePattern` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '路由转发地址',
  `routeType` tinyint NULL DEFAULT NULL COMMENT '路由类型1从注册中心获取,0-转发地址',
  `routeUrl` varchar(100) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '转发到的地址',
  `is_open` tinyint NULL DEFAULT NULL COMMENT '是否开放0-否1-开放',
  `is_use` tinyint NULL DEFAULT NULL COMMENT '是否可用0-否1-开放',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_bin COMMENT = '动态网关表' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of tb_route
-- ----------------------------
INSERT INTO `tb_route` VALUES (1, 'member', 'xiaojie-member', '/member/**', 1, 'lb://xiaojie-member/', 1, 1);
INSERT INTO `tb_route` VALUES (3, 'baidu', 'xiaojie-baidu', '/bai/**', 0, 'http://www.baidu.com', 1, 1);
SET FOREIGN_KEY_CHECKS = 1;


配置文件如下


server:
  port: 82
####服务网关名称
spring:
  application:
    name: xiaojie-gateway
  cloud:
    gateway:
          ###路由策略
                discovery:
                  locator:
                    enabled: true
    nacos:
      discovery:
        #注册地址
        server-addr: 127.0.0.1:8848,127.0.0.1:8849,127.0.0.1:8850
        #是否开启nacos注册
        enabled: true
        #账号
        username: xiaojie
        #密码
        password: nacos
        #命名空间
        namespace: 28eb29ea-5a04-4714-8ae8-77d37c01166a
        #分组
        group: DEV_GROUP
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    filters: stat
    initialSize: 10
    maxActive: 50
    maxOpenPreparedStatements: 20
    maxWait: 60000
    minEvictableIdleTimeMillis: 300000
    minIdle: 10
    password: root
    poolPreparedStatements: true
    testOnBorrow: false
    testOnReturn: false
    testWhileIdle: true
    timeBetweenEvictionRunsMillis: 60000
    type: com.alibaba.druid.pool.DruidDataSource
    url: jdbc:mysql://127.0.0.1:3306/my_test?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&serverTimezone=Asia/Shanghai&autoReconnect=true
    username: root
    validationQuery: select 1


七、网关解决跨域


package com.xiaojie.filter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
/**
 * @Description: 解决微服务的跨域问题
 * @Author: yan
 * @Date: 2021/5/12 23:18
 * @return: null
 **/
@Component
public class CrossOriginFilter implements GlobalFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        HttpHeaders headers = response.getHeaders();
        headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, "*");
        headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "POST, GET, PUT, OPTIONS, DELETE, PATCH");
        headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
        headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, "*");
        headers.add(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, "*");
        return chain.filter(exchange);
    }
}


八、网关实现限流


使用的算法是令牌桶 Redis+Lua


令牌流与令牌桶


系统会以一定的速度生成令牌,并将其放置到令牌桶中,可以将令牌桶想象成一个缓冲区(可以用队列这种数据结构来实现),当缓冲区填满的时候,新生成的令牌会被扔掉。 这里有两个变量很重要:


第一个是生成令牌的速度,一般称为 rate 。比如,我们设定 rate = 2 ,即每秒钟生成 2 个令牌,也就是每 1/2 秒生成一个令牌;

第二个是令牌桶的大小,一般称为 burst 。比如,我们设定 burst = 10 ,即令牌桶最大只能容纳 10 个令牌。


数据流


数据流是真正的进入系统的流量,对于接口来讲,如果平均每秒钟会调用2次,则认为速率为 2次/s 。


算法原理


系统接收到一个单位数据(对于网络传输,可以是一个包或者一个字节;对于微服务,可以是一个请求)后,从令牌桶中取出一个令牌,然后对数据或请求进行处理。如果令牌桶中没有令牌了,会直接将数据或者请求丢弃。当然,对于微服务,就不能是丢弃这么简单了:可以返回一个异常消息,用于提示用户其请求速率超过了系统限制。


有以下三种情形可能发生:


数据流的速率 等于 令牌流的速率。这种情况下,每个到来的数据包或者请求都能对应一个令牌,然后无延迟地通过队列;

数据流的速率 小于 令牌流的速率。通过队列的数据包或者请求只消耗了一部分令牌,剩下的令牌会在令牌桶里积累下来,直到桶被装满。剩下的令牌可以在突发请求的时候消耗掉。

数据流的速率 大于 令牌流的速率。这意味着桶里的令牌很快就会被耗尽。导致服务中断一段时间,如果数据包或者请求持续到来,将发生丢包或者拒绝响应。

比如前面举的例子,生成令牌的速率和令牌桶的大小分别为 rate = 2, burst = 10 ,则系统能承受的突发请求速率为 10次/s ,平均请求速率为 2次/s 。


摘自:https://blog.csdn.net/xgw1010/article/details/107595141


代码如下

package com.xiaojie.config;
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.cloud.gateway.filter.ratelimit.RateLimiter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
/**
 * @Description:
 * @author: xiaojie
 * @date: 2021.07.16
 */
@Configuration
public class MyKeyResolver {
    /*
     *  ip限流 每一个ip只能在限流的规则内访问的规则,超出规则,进行限流
     * @todo
     * @author xiaojie
     * @date 2021/7/16 9:44
     * @return org.springframework.cloud.gateway.filter.ratelimit.KeyResolver
     */
//    @Bean("ipKeyResolver")
//    @Primary
//    public KeyResolver ipKeyResolver() {
//        return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostString());
//    }
    /*
     *  用户限流 每一个用户的限流规则 访问时需要携带userId 参数
     * @todo
     * @author xiaojie
     * @date 2021/7/16 9:44
     * @return org.springframework.cloud.gateway.filter.ratelimit.KeyResolver
     */
    @Bean("userKeyResolver")
    KeyResolver userKeyResolver() {
        return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("userId"));
    }
    /*
     * 接口限流 根据接口路径限流
     * @todo
     * @author xiaojie 
     * @date 2021/7/16 9:45 
     * @return org.springframework.cloud.gateway.filter.ratelimit.KeyResolver
     */
//    @Bean("apiKeyResolver")
//    KeyResolver apiKeyResolver() {
//        return exchange -> Mono.just(exchange.getRequest().getPath().value());
//    }
}


路由配置如下


server:
  port: 82
####服务网关名称
spring:
  application:
    name: xiaojie-gateway
  cloud:
    gateway:
          ###路由策略
#          routes:
#            ###根据我们的服务名称查找地址实现调用
#            - id: member
#              #uri: http://127.0.0.1:8090
#              uri: lb://xiaojie-member/
#              filters:
#                - StripPrefix=1
#              ###匹配规则
#              predicates:
#                - Path=/member/*
                routes:
                  - id: requestratelimiter_route
                    uri: lb://xiaojie-member/
                    filters:
                      - name: RequestRateLimiter
                        args:
                          #允许用户每秒执行多少请求,而没有任何丢弃的请求。这是令牌桶填充的速率
                          redis-rate-limiter.replenishRate: 1
                          #允许用户在一秒内执行的最大请求数。这是令牌桶可以容纳的令牌数量。将此值设置为零会阻止所有请求。
                          redis-rate-limiter.burstCapacity: 1
                          #每个请求从存储桶中获取的令牌数量,默认为 1
                          redis-rate-limiter.requestedTokens: 1
                          key-resolver:
                            - "#{@userKeyResolver}" #根据用户限流
                      - StripPrefix=1
                    predicates:
                      - Path=/member/*
                #从注册中心获取服务
                discovery:
                  locator:
                    enabled: true
    nacos:
      discovery:
        #注册地址
        server-addr: 127.0.0.1:8848,127.0.0.1:8849,127.0.0.1:8850
        #是否开启nacos注册
        enabled: true
        #账号
        username: xiaojie
        #密码
        password: nacos
        #命名空间
        namespace: 28eb29ea-5a04-4714-8ae8-77d37c01166a
        #分组
        group: DEV_GROUP
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    filters: stat
    initialSize: 10
    maxActive: 50
    maxOpenPreparedStatements: 20
    maxWait: 60000
    minEvictableIdleTimeMillis: 300000
    minIdle: 10
    password: root
    poolPreparedStatements: true
    testOnBorrow: false
    testOnReturn: false
    testWhileIdle: true
    timeBetweenEvictionRunsMillis: 60000
    type: com.alibaba.druid.pool.DruidDataSource
    url: jdbc:mysql://127.0.0.1:3306/my_test?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&serverTimezone=Asia/Shanghai&autoReconnect=true
    username: root
    validationQuery: select 1
    #基于redis实现限流
  redis:
    host: 192.168.6.130
    password: xiaojie
    port: 6379


限流后返回429状态码


动态限流 基于Sentinel


九、设置黑白名单


package com.xiaojie.filter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
/**
 * @Description: 黑名单
 * @author: xiaojie
 * @date: 2021.07.16
 */
@Component
@Slf4j
public class IpFilter implements GlobalFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        String ipAddress = getIpAddress(request);
        log.info("获取的IP地址为{}",ipAddress);
        //实际生产可以基于redis,数据库实现记录
        if ("127.0.0.1".equals(ipAddress)){
            ServerHttpResponse response = exchange.getResponse();
            HttpHeaders httpHeaders = response.getHeaders();
            httpHeaders.setContentType(MediaType.APPLICATION_JSON);
            response.setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
            String msg="已被加入黑名单";
            DataBuffer buffer = response.bufferFactory().wrap(msg.getBytes());
            return response.writeWith(Mono.just(buffer));
        }
        return chain.filter(exchange);
    }
    /*
     * 获取用户真实ip 
     * @todo
     * @author xiaojie 
     * @date 2021/7/16 14:52
     * @return java.lang.String
     */
    public static String getIpAddress(ServerHttpRequest  request) {
        HttpHeaders headers = request.getHeaders();
        String ip = headers.getFirst("x-forwarded-for");
        if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
            // 多次反向代理后会有多个ip值,第一个ip才是真实ip
            if (ip.indexOf(",") != -1) {
                ip = ip.split(",")[0];
            }
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = headers.getFirst("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = headers.getFirst("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = headers.getFirst("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = headers.getFirst("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = headers.getFirst("X-Real-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddress().getAddress().getHostAddress();
        }
        return ip;
    }
}


参考:https://blog.csdn.net/lizz861109/article/details/108530364


https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#the-prefixpath-gatewayfilter-factory


https://blog.csdn.net/qq_32652767/article/details/112257082


https://blog.csdn.net/xgw1010/article/details/107595141


感谢几位大佬

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
6天前
|
负载均衡 安全 Java
【微服务系列笔记】Gateway
Gateway是Spring Cloud生态系统中的网关服务,作为微服务架构的入口,提供路由、负载均衡、限流、鉴权等功能。借助于过滤器和路由器,Gateway能够动态地管理请求流量,保障系统的安全和性能。
38 7
|
6天前
|
SpringCloudAlibaba 负载均衡 Java
【微服务 SpringCloudAlibaba】实用篇 · Gateway服务网关
【微服务 SpringCloudAlibaba】实用篇 · Gateway服务网关
18 0
|
6天前
|
Java Docker 微服务
|
6天前
|
消息中间件 Java RocketMQ
Spring Cloud RocketMQ:构建可靠消息驱动的微服务架构
【4月更文挑战第28天】消息队列在微服务架构中扮演着至关重要的角色,能够实现服务之间的解耦、异步通信以及数据分发。Spring Cloud RocketMQ作为Apache RocketMQ的Spring Cloud集成,为微服务架构提供了可靠的消息传输机制。
30 1
|
6天前
|
Dubbo Java 应用服务中间件
Spring Cloud Dubbo: 微服务通信的高效解决方案
【4月更文挑战第28天】在微服务架构的发展中,服务间的高效通信至关重要。Spring Cloud Dubbo 提供了一种基于 RPC 的通信方式,使得服务间的调用就像本地方法调用一样简单。本篇博客将探讨 Spring Cloud Dubbo 的核心概念,并通过具体实例展示其在项目中的实战应用。
22 2
|
6天前
|
前端开发 Java 应用服务中间件
Springboot解决跨域问题方案总结(包括Nginx,Gateway网关等)
Springboot解决跨域问题方案总结(包括Nginx,Gateway网关等)
|
1天前
|
运维 监控 负载均衡
探索微服务架构下的服务网格
【5月更文挑战第20天】 在当今日益复杂的分布式系统中,微服务架构已成为企业技术栈的重要组成部分。随着微服务数量的膨胀和网络通信的复杂化,传统的服务发现与负载均衡机制显得力不从心。本文将深入探讨服务网格这一新兴模式,它如何在微服务环境中提供更灵活、动态且高效的服务间通信解决方案。我们将剖析服务网格的核心组件、工作原理以及它如何简化分布式系统的运维难题。
|
1天前
|
消息中间件 持续交付 开发者
构建高效微服务架构:后端开发的新趋势
【5月更文挑战第20天】 随着现代软件开发的复杂性日益增加,传统的单体应用架构逐渐显得笨重且难以适应快速变化的市场需求。微服务架构作为解决方案,以其灵活性、可扩展性和技术多样性受到青睐。本文将深入探讨微服务架构的核心概念,设计原则,以及如何通过最佳实践来构建和维护一个高效的微服务体系结构。我们将讨论关键的后端技术栈选择,服务划分策略,数据管理,以及持续集成与部署(CI/CD)流程的重要性。文章旨在为后端开发者提供一套实用的指南和思考框架,以支持他们在未来的软件项目中采用微服务架构。
|
1天前
|
持续交付 API 开发者
构建高效微服务架构:后端开发的新范式
【5月更文挑战第20天】 在现代软件开发的潮流中,微服务架构已成为推动技术创新和服务灵活部署的关键。本文探讨了如何构建一个高效的微服务架构,涵盖其设计理念、技术栈选择以及面临的挑战与应对策略。通过深入分析,我们旨在为后端开发者提供一套实用的指导原则和最佳实践,以支持快速迭代和系统的可扩展性。
|
1天前
|
API 持续交付 开发者
构建高效微服务架构的五大关键技术
【5月更文挑战第20天】 在当前数字化转型的浪潮中,微服务架构因其灵活性、可扩展性而成为众多企业的首选。本文深入剖析了构建和维护高效微服务架构的五大关键技术:容器化技术、服务网格、API网关、持续集成/持续部署(CI/CD)和分布式追踪。通过这些技术的整合使用,可以显著提高系统的可靠性、弹性及开发效率。