<返回更多

从零开始的微服务搭建之路

2021-03-05  今日头条  Java思享汇
加入收藏

随着公司的业务发展,有幸经历了从单体应用迁移到分布式应用,又从分布式应用开始准备搭建微服务应用,以下是公司从零开始搭建微服务的过程,记录并分享出来,希望对大家有所帮助,我们先使用Spring Cloud GateWay作为网关,由于目前还没有服务发现组件,例如eurka,所以需要通过配置文件的方式配置Ribbon作负载均衡。所以以下重点讲解Spring Cloud GateWayRibbon的搭配使用。

网关的由来

微服务提出后,单体应用被拆分成多个服务,为了对外提供统一入口,解耦客户端与内部服务。

「干货」从零开始的微服务搭建之路

单体架构到微服务架构演变

网关的作用

网关能做统一的路由转发、熔断、限流、安全认证、日志监控等。

「干货」从零开始的微服务搭建之路

网关的作用

网关zuul与Spring Cloud Gateway对比

「干货」从零开始的微服务搭建之路

zuul与Spring Cloud Gateway对比

Spring Cloud Gateway核心概念

「干货」从零开始的微服务搭建之路

网关核心概念

1.路由(route) 路由是网关最基础的部分,路由信息由一个ID、一个目的URL、一组断言工厂和一组Filter组成。如果断言为真,则说明请求URL和配置的路由匹配。

2.断言(predicates) JAVA8中的断言函数,Spring Cloud Gateway中的断言函数输入类型是Spring5.0框架中的ServerWebExchange。Spring Cloud Gateway中的断言函数允许开发者去定义匹配来自Http Request中的任何信息,比如请求头和参数等。

3.过滤器(filter) 一个标准的Spring webFilter,Spring Cloud Gateway中的Filter分为两种类型,分别是Gateway Filter和Global Filter。过滤器Filter可以对请求和相应进行处理。

Spring Cloud Gateway工作原理

「干货」从零开始的微服务搭建之路

网关工作原理

Spring Cloud Gateway核心处理流程如上图所示,Gateway的客户端向Spring Cloud Gateway发送请求,请求首先被HttpWebHandlerAdapter进行提取组装成网关上下文,然后网关的上下文会传递到DispatcherHandler。DispatcherHandler是所有请求的分发处理器,DispatcherHandler主要负责分发请求对应的处理器。比如请求分发到对应的RoutePredicateHandlerMApping(路由断言处理映射器)。路由断言处理映射器主要作用用于路由查找,以及找到路由后返回对应的FilterWebHandler。FilterWebHandler主要负责组装Filter链并调用Filter执行一系列的Filter处理,然后再把请求转到后端对应的代理服务处理,处理完毕之后将Response返回到Gateway客户端。

路由断言Factories整理

GatewayFilter Factories整理

Ribbon的LoadBalancer的主要组件

「干货」从零开始的微服务搭建之路

Ribboon主要组件

IRule

IPing

检查实例是否存活。如何ping。实现类:

ServerList

获取服务器列表。

ServerListFilter

在获取的服务器列表中进行获取。

ServerListUpdater

更新服务器列表。

IClientConfig

ILoadBalancer

LoadBalancer的组成:

  1. 一个基于特定条件可能进行存储的服务器列表。
  2. 一个类:通过IRule实现并定义LoadBalancing策略。
  3. 该类定义并实现一种机制,用户确定列表中节点/服务器的实用性/可用性。

LoadBalancer的实现类:

代码实践

pom.xml增加SpringCloud Gateway和Ribbon依赖

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.3.RELEASE</version>
    <relativePath/> 
</parent>
<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>
</dependencies>

代码方式配置网关

@SpringBootApplication
@RestController
public class DemoGatewayApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoGatewayApplication.class, args);
    }

   @Bean
   public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
            .route(r -> r
                .path("/refund/**")
                .filters(f -> f.addRequestHeader("Hello", "World"))
                .uri("http://manage-test.payplatform.speiyou.cn/")
            ).build();
    }

}

yml方式配置网关

spring:
  application:
    name: gateway-service
  cloud:
    gateway:
      routes:
      - id: merchant
        uri: lb://merchant-load-balanced-service
        predicates:
        - Path=/merchant/**
        - Method=POST
      - id: split
        uri: lb://split-load-balanced-service
        predicates:
        - Path=/split/**
        filters:
        - RewritePath=/split, /ledger-split #重写url
      - id: cashier
        uri: lb://cashier-load-balanced-service
        predicates:
        - Path=/cashier/**
        filters:
        - StripPrefix=1 #将cashier过滤掉
        
#ribbon全局配置
ribbon:
  ConnectTimeout: 1000 #服务请求连接超时时间(毫秒)
  ReadTimeout: 3000 #服务请求处理超时时间(毫秒)
  OkToRetryOnAllOperations: true #对超时请求启用重试机制
  MaxAutoRetriesNextServer: 1 #切换重试实例的最大个数
  MaxAutoRetries: 1 # 切换实例后重试最大次数
  NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule #负载均衡算法
  NFLoadBalancerPingClassName: com.talpay.gateway.config.HealthCheck   #健康检查
  NFLoadBalancerPingInterval: 20                                       #设置健康检查间隔,单位秒,默认30秒

merchant-load-balanced-service:
  ribbon:
    listOfServers: 192.168.xxx.xxx:8080

split-load-balanced-service:
  ribbon:
    listOfServers: 192.168.xxx.xxx:8081

cashier-load-balanced-service:
  ribbon:
    listOfServers: 192.168.xxx.xxx:8080

Ribbon服务健康检查

@Slf4j
@Component
public class HealthCheck implements IPing{

    @Autowired
    private RestTemplate restTemplate;

    @Value("${dingtalk.url}")
    private String dingtalkURL; //钉钉报警url

    @Override
    public boolean isAlive(Server server) {
       
        String url = "http://"+ server.getId()+ "/actuator/health";
        try {
            ResponseEntity<String> heath = restTemplate.getForEntity(url, String.class);
            if (heath.getStatusCode() == HttpStatus.OK) {
                log.info("ping " + url + " success ");
                return true;
            }
            log.info("ping " + url + " error and response is " + heath.getBody());
            return false;
        } catch (Exception e) {
            log.error("ping " + url + " failed");
            DingRebotSendUtil.send(dingtalkURL,new TextMessage("网关|ping:" + url + " failed"));
            return false;
        }
    }
}

自定义GlobalFilter

@Component
public class LogGlobalFilter implements GlobalFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest serverHttpRequest= exchange.getRequest();
        String url = serverHttpRequest.getURI().toString();
        System.out.println("url ------>: " + url);//打印每次请求的url
        return chain.filter(exchange);
    }
}

测试结果:

 

「干货」从零开始的微服务搭建之路

第一次触发


「干货」从零开始的微服务搭建之路

第二次触发

以上为真实测试数据,第一次触发链接到生产环境,第二次触发链接到仿真环境。

声明:本站部分内容来自互联网,如有版权侵犯或其他问题请与我们联系,我们将立即删除或处理。
▍相关推荐
更多资讯 >>>