微服务架构·网关

学习目标:

了解常用filter常用的功能,对gateway有一定的认知,根据业务痛点,成本做出服务的网关选择 zuul | gateway


前言

微服务架构将单体应用,按照业务领域拆分为多个高内聚低耦合的小型服务,每个小服务运行在独立进程,由不同的团队开发和维护,服务间采用轻量级通信机制,如HTTP RESTful API,或者RPC,独立自动部署,可以采用不同的语言及存储。
微服务体现去中心化、天然分布式,是中台战略落地到IT系统的具体实现方式的技术架构,用来解决企业业务快速发展与创新时面临的系统弹性可扩展、敏捷迭代、技术驱动业务创新等难题。

一、中台战略和微服务?

在这里插入图片描述

简单的理解就是把传统的前后台体系中的后台进行了细分。阿里巴巴提出了大中台小前台的战略。就是强化业务和技术中台,把前端的应用变得更小更灵活。当中台越强大,能力就越强,越能更好的快速响应前台的业务需求。打个比喻,就是土壤越肥沃,越适合生长不同的生物,打造好的生态系统。

#hidden
总结: 没有什么是分层架构解决不了的,如果有。。。那就再拆分一层

二、成型的互联网架构

1.面向服务架构

某电子政务公司的架构图

#Questions
存在的问题?该怎么解决?通用的几种方案?
在这里插入图片描述

微服务的服务发现的三种方式

第一种:如下图所示,传统的服务发现(大部分公司的做法)。服务上线后,通知运维,申请域名,配置路由。调用方通过dns域名解析,经过负载均衡路由,进行服务访问。缺点: LB的单点风险,服务穿透LB,性能也不是太好

在这里插入图片描述

第二种:也叫客户端发现方式。如下图所示。通过服务注册的方式,服务提供者先注册服务。消费者通过注册中心获取相应服务。

并且把LB的功能移动到了消费者的进程内,消费者根据自身路由去获取相应服务。优点是,没有了LB单点问题,也没有了LB的中间一跳,性能也比较好。但是这种方式有一个非常明显的缺点就是具有非常强的耦合性。针对不同的语言,每个服务的客户端都得实现一套服务发现的功能。
在这里插入图片描述

第三种:也叫服务端发现方式,如下图所示。和第二种很相似。但是LB功能独立进程单独部署,所以解决了客户端多语言开发的问题。唯一的缺点就是运维成比较高,每个节点都得部署一个LB的代理,例如nginx。

在这里插入图片描述

客户端 && 服务端发现

客户端发现就是当 A 需要调用 B 服务时,请求注册中心(B 服务在启动时会将信息注册到注册中心),注册中心将一份完整的可用服务列表返回给
A 服务,A 服务自行决定使用哪个 B 服务。

在这里插入图片描述
特点

  • 简单直接,不需要代理的介入
  • 客户端(A)知道所有实际可用的服务地址
  • 客户端(A)需要自己实现负载均衡逻辑

example

  • Eureka
  • Nacos

服务端发现相对于客户端发现,多了一个代理,代理帮 A 从众多的 B 中挑选一个 B。

在这里插入图片描述
特点

  • 由于代理的介入,服务(B)与注册中心,对 A 是不可见的

example

  • ZooKeeper
  • Nginx

2.微服务网关

网关就好比一个公司的门卫。屏蔽内部细节,统一对外服务接口。

假设你的名字叫小不点(很小,这里你就是一个url地址,指向某个网页资源),你住在一个大院子里,你的邻居有很多小伙伴,父母是你的网关。当你想跟院子里的某个小伙伴玩,只要你在院子里大喊一声

在这里插入图片描述

他的名字,他听到了就会回应你,并且跑出来跟你玩。
但是你家长不允许你走出大门,你想与外界发生的一切联系,都必须由父母(网关)用电话帮助你联系。假如你想找你的同学小明聊天,小明家住在很远的另外一个院子里,他家里也有父母(小明的网关)。但是你不知道小明家的电话号码,不过你的班主任老师有一份你们班全体同学的名单和电话号码对照表,你的老师就是你的网关服务器。于是你在家里和父母有了下面的对话:
小不点:妈妈(或爸爸),我想找班主任查一下小明的电话号码行吗?家长:好,你等着。(接着你家长给你的班主任拨了一个电话,问清楚了小明的电话)问到了,他家的号码是211.99.99.99
小不点:太好了!妈(或爸),我想找小明,你再帮我联系一下小明吧。
家长:没问题。(接着家长向电话局发出了请求接通小明家电话的请求,最后一关当然是被转接到了小明家家长那里,然后他家长把电话给转到小明).
就这样你和小明取得了联系。

在微服务架构里,服务的粒度被进一步细分,各个业务服务可以被独立的设计、开发、测试、部署和管理。这时,各个独立部署单元可以用不同的开发测试团队维护,可以使用不同的编程语言和技术平台进行设计,这就要求必须使用一种语言和平 台无关的服务协议作为各个单元间的通讯方式。

在这里插入图片描述

2.1 Zuul 网关

Zuul开源地址 https://github.com/Netflix/zuul

Zuul 1.0 服务架构概述
官方介绍

Zuul网关的核心是一系列的过滤器,这些过滤器可以对请求或者响应结果做一系列过滤,Zuul 提供了一个框架可以支持动态加载,编译,运行这些过滤器,这些过滤器是使用责任链方式顺序对请求或者响应结果进行处理的,这些过滤器直接不会直接进行通信,但是通过责任链传递的RequestContext参数可以共享一些东西。

在zuul中过滤器分为四种:

  • PRE Filters(前置过滤器) :当请求会路由转发到具体后端服务器前执行的过滤器,比如鉴权过滤器,日志过滤器,还有路由选择过滤器
  • ROUTING Filters (路由过滤器):该过滤器作用是把请求具体转发到后端服务器上,一般是通过Apache HttpClient 或者 Netflix Ribbon把请求发送到具体的后端服务器上
  • POST Filters(后置过滤器):当把请求路由到具体后端服务器后执行的过滤器;场景有添加标准http 响应头,收集一些统计数据(比如请求耗时等),写入请求结果到请求方等。
  • ERROR Filters(错误过滤器):当上面任何一个类型过滤器执行出错时候执行该过滤器

在这里插入图片描述
IO模型
servlet由servlet container进行生命周期管理。container启动时构造servlet对象并调用servlet init()进行初始化;container关闭时调用servlet destory()销毁servlet;container运行时接受请求,并为每个请求分配一个线程(一般从线程池中获取空闲线程)然后调用service()。

弊端:servlet是一个简单的网络IO模型,当请求进入servlet container时,servlet container就会为其绑定一个线程,在并发不高的场景下这种模型是适用的,但是一旦并发上升,线程数量就会上涨,而线程资源代价是昂贵的(上线文切换,内存消耗大)严重影响请求的处理时间。在一些简单的业务场景下,不希望为每个request分配一个线程,只需要1个或几个线程就能应对极大并发的请求,这种业务场景下servlet模型没有优势。

在这里插入图片描述

总结
zuul1.0时候当zuul接受到一个请求后会同步执行前置过滤器、路由过滤器、后置过滤器,等执行完毕后在同步把结果返回为调用方,调用方在整个过程中是阻塞的。其实SpringBoot集成的zuul就是自己实现了个前置过滤器做选择路由,然后自己实现了个路由过滤器根据前置过滤器选择的路由具体做路由转发

Zuul 2.0 服务架构新特性

Netty作为高性能异步网络通讯框架,在dubbo,rocketmq,sofa等知名开源框架中都有使用,如下图zuul2.0使用netty server作为网关监听服务器监听客户端发来的请求,然后把请求转发到前置过滤器(inbound filters)进行处理,处理完毕后在把请求使用netty client代理到具体的后端服务器进行处理,处理完毕后在把结果交给后者过滤器(outbound filters)进行处理,然后把处理结果通过nettyServer写回客户端。概括引入了netty

在这里插入图片描述
总结
在zuul1.0时候客户端发起的请求后需要同步等待zuul网关返回,zuul网关这边对每个请求会分派一个线程来进行处理,这会导致并发请求数量有限。而zuul2.0使用netty作为异步通讯,可以大大加大并发请求量。

虽然Zuul 2.0开始,使用了Netty,并且已经有了大规模Zuul 2.0集群部署的成熟案例,但是,Springcloud官方已经没有集成改版本的计划了。

思考

  1. 异步的好处在哪
  2. zuul该如何选择1.0版本还是2.0版本 #hidden(同步可以在线程变量中获取数据,异步实现不到)

2.2. gateway

Spring Cloud Gateway是Spring官方基于Spring5.0,Spring Boot2.0和Project Reactor等技术开发的网关,Spring Cloud Gateway旨在为微服务架构提供简单,有效且统一的API路由管理方式。Spring Cloud Gateway作为Spring Cloud 生态系统中的网关,目标是替代Netflix Zuul,其不仅提供统一的路由方式,并且还基于Filter链的方式提供了网关基本的功能,例如:安全,监控、埋点,限流等。

WebFlux

Webflux模式替换了旧的Servlet线程模型。用少量的线程处理request和response io操作,这些线程称为Loop线程,而业务交给响应式编程框架处理,响应式编程是非常灵活的,用户可以将业务中阻塞的操作提交到响应式框架的work线程中执行,而不阻塞的操作依然可以在Loop线程中进行处理,大大提高了Loop线程的利用率。官方结构图:
在这里插入图片描述
Webflux虽然可以兼容多个底层的通信框架,但是一般情况下,底层使用的还是Netty,毕竟,Netty是目前业界认可的最高性能的通信框架。而Webflux的Loop线程,正好就是著名的Reactor 模式IO处理模型的Reactor线程,如果使用的是高性能的通信框架Netty,这就是Netty的EventLoop线程。

Gateway请求流程图如下
在这里插入图片描述

cookie:

既然gateway是根据route来生成过滤链,那么有没有可能插入自己的过滤器呢,从而实现插拔式的功能

业务背景
部分路由不需要进行权限校验,为公共请求,这个时候如果验证功能写在全局过滤器里面,就会比较鸡肋

模仿源码 {@link AddRequestHeaderGatewayFilterFactory}实现
在这里插入图片描述

自定义权限过滤器的源码继承AbstractNameValueGatewayFilterFactory

/**
 * 自定义的过滤器实现,非全局 可在yml中配置使用
 * 模仿 {@link  AddRequestHeaderGatewayFilterFactory} 实现
 *
 * @author xyang
 * @version 1.0
 * @createDate 2019/11/07 17:34
 */
@Slf4j
public class JwtAuthFilter extends AbstractNameValueGatewayFilterFactory {
    
    @Autowired
    private SecurityService securityService;
    
    @Autowired
    private RequestTemplate requestTemplate;
    
    /**
     * 拦截器的filter方法,通过自定义 GatewayFilter
     * 使用权限控制
     *
     * @param config:
     * @Author xyang
     * @Date  2020/12/21 17:41
     */
    @Override
    public GatewayFilter apply(NameValueConfig config) {
        return new GatewayFilter() {
            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                ServerHttpRequest request = exchange.getRequest();
                // 获取token,校验jwt的合法性
                String jwt = WebFluxJwtUtil.obtainJwt(request);
                if (!WebFluxJwtUtil.validateJwtStart(jwt)){
                    // 没有token
                    return getVoidMono(exchange.getResponse(), Status.TOKEN_NO_EXIT.getCode(), Status.TOKEN_NO_EXIT.getMessage());
                }
                Ret<Status> authentication = securityService.authentication(jwt);
                if (authentication.getCode().equals(Status.SUCCESS.getCode())) {
                    //  请求继续执行
                    return chain.filter(exchange.mutate().request(request).build());
                }
                // 鉴权不通过
                return getVoidMono(exchange.getResponse(), authentication.getCode(), authentication.getMsg());
            }
            @Override
            public String toString() {
                return filterToStringCreator(JwtAuthFilter.this)
                        .append(config.getName(), config.getValue()).toString();
            }
        };
    }
    
    /**
     * 获取返回的Mono
     * @param serverHttpResponse:
     * @Author xyang
     * @Date  2020/12/23 10:56
     */
    private Mono<Void> getVoidMono(ServerHttpResponse serverHttpResponse, Integer code, String msg) {
        serverHttpResponse.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
        Ret<Status> ret = new Ret(code, msg, null);
        try {
          DataBuffer dataBuffer = serverHttpResponse.bufferFactory().wrap(new ObjectMapper().writeValueAsString(ret).getBytes());
          return serverHttpResponse.writeWith(Flux.just(dataBuffer));
        } catch (Exception ex){
            DataBuffer dataBuffer = serverHttpResponse.bufferFactory().wrap(JSON.toJSONBytes(ret));
            return serverHttpResponse.writeWith(Flux.just(dataBuffer));
        }
    }
}

注册自定义过滤器到gateway服务中

/**
 * 注入自定义的过滤器到容器中,提供 配置文件中配置使用
 * 模仿 {@link GatewayAutoConfiguration} 实现
 *
 * @author: xyang
 * @created: 2020-12-21 17:29:58
 */
@Configuration(proxyBeanMethods = false)
@AutoConfigureBefore({ HttpHandlerAutoConfiguration.class,
				WebFluxAutoConfiguration.class })
@AutoConfigureAfter({ GatewayLoadBalancerClientAutoConfiguration.class,
				GatewayClassPathWarningAutoConfiguration.class })
public class MyFilterAutoConfiguration {
	
	/**
	 * 把自己的过滤器注册到spring中,然后gateway会在此处 {@RouteDefinitionRouteLocator} 代码 100 行
	 * 获取到此filter,然后注册到全局中
	 *
	 * @Author xyang
	 * @Date  2020/12/21 17:46
	 */
	@Bean
	public JwtAuthFilter serverGatewayFilter() {
		return new JwtAuthFilter();
	}
}

GatewayAutoConfiguration
此类会获取spring中的predicates,也就是自定义的过滤器s
在这里插入图片描述
RouteDefinitionRouteLocator
初始化时,会在当前类生成路由的过滤器链
在这里插入图片描述

使用方法
在这里插入图片描述


关键的类:

1、RouteLocator 路由的转发

2、predicate 请求与路由进行匹配

在这里插入图片描述

3、filter 过滤与修改
3.1、GatewayFilter : 需要通过spring.cloud.routes.filters 配置在具体路由下,只作用在当前路由上或通过spring.cloud.default-filters配置在全局,作用在所有路由上。
在这里插入图片描述

3.2、GlobalFilter : 全局过滤器,不需要在配置文件中配置,作用在所有的路由上,最终通过GatewayFilterAdapter包装成GatewayFilterChain可识别的过滤器,它为请求业务以及路由的URI转换为真实业务服务的请求地址的核心过滤器,不需要配置,系统初始化时加载,并作用在每个路由上。

在这里插入图片描述
4、自定义过滤器,需要实现以下两个接口 :GatewayFilter, Ordered

5、限流过滤器

5.1、常见的限流算法:

  1. 计数器算法:简单来说,就是一分钟之内仅允许通过多少个请求。(缺点:突刺现象,无法解决某段时间并发高的问题)
    在这里插入图片描述
常见案例: 邮箱服务商,识图服务商,等限制用户高频访问的接口比较常见
滑动窗口:

限流的本质就是限制一个接口在某个维度上单位时间的响应次数。我们可以设置一个计数器对某一时间段内的请求进行计数,当请求量超过某个事先设定的阈值时则触发饱和策略,拒绝用户的请求。比如我们事先设定某个接口单一 IP 维度在 1 分钟内只能正常响应 100 次用户请求,那么如果范围内某个 IP 请求超过该阈值,就会拒绝后续请求。
上述方法存在的一个缺点是计数不够平滑,考虑一个 10 点开放抢购的场景,如果一个恶意用户如果在 09:59:30 ~ 09:59:59 之间请求了 100 次,然后等到 10 点整时计数器被清空,这个时候该用户在 10:00:00 ~ 10:00:30 之间又可以再次请求 100 次,实际上在 09:59:30 ~ 10:00:30 这一分钟内该恶意用户请求了 200 次,成功绕过了限流策略。

针对计数器算法存在的上述缺陷,一种典型的解决方法就是采用 滑动窗口策略,本质上就是多级计数。对于滑动时间窗口,我们可以把1ms的时间窗口划分成10个小窗口,或者想象窗口有10个时间插槽time slot, 每个time slot统计某个100ms的请求数量。每经过100ms,有一个新的time slot加入窗口,早于当前时间1s的time slot出窗口。窗口内最多维护10个time slot。

在这里插入图片描述

滑动窗口算法是固定窗口的一种改进,但从根本上并没有真正解决固定窗口算法的临界突发流量问题

  1. 漏桶算法:不管流量瞬间并发多高,都保持匀速消费request。(弊端:无法应对短时间的突发流量)

漏桶算法实际为一个容器请求队列,关键要素为 桶大小(队列大小),流出速率(出队速率)。即无论请求并发多高,如果桶内的队列满了,多余进来的请求都将被舍弃。由于桶的流出速率固定,所以可以保证限流后的请求并发数可以固定在一个范围内。
在这里插入图片描述

适用场景
漏桶算法是流量最均匀的限流实现方式,一般用于流量“整形”。例如保护数据库的限流,先把对数据库的访问加入到木桶中,worker再以db能够承受的qps从木桶中取出请求,去访问数据库。

存在的问题
木桶流入请求的速率是不固定的,但是流出的速率是恒定的。这样的话能保护系统资源不被打满,但是面对突发流量时会有大量请求失败,不适合电商抢购和微博出现热点事件等场景的限流。


  1. 令牌桶算法:从某种意义上讲,令牌桶算法是对漏桶算法的一种改进,桶算法能够限制请求调用的速率,而令牌桶算法能够在限制调用的平均速率的同时还允许一定程度的突发调用。在令牌桶算法中,存在一个桶,用来存放固定数量的令牌。算法中存在一种机制,以一定的速率往桶中放令牌。每次请求调用需要先获取令牌,只有拿到令牌,才有机会继续执行,否则选择选择等待可用的令牌、或者直接拒绝。放令牌这个动作是持续不断的进行,如果桶中令牌数达到上限,就丢弃令牌,所以就存在这种情况,桶中一直有大量的可用令牌,这时进来的请求就可以直接拿到令牌执行,比如设置qps为100,那么限流器初始化完成一秒后,桶中就已经有100个令牌了,这时服务还没完全启动好,等启动完成对外提供服务时,该限流器可以抵挡瞬时的100个请求。所以,只有桶中没有令牌时,请求才会进行等待,最后相当于以一定的速率执行。

在这里插入图片描述

参数设置 木桶的容量 - 考虑业务逻辑的资源消耗和机器能承载并发处理多少业务逻辑。 生成令牌的速度 -
太慢的话起不到“攒”令牌应对突发流量的效果。

适合电商抢购或者微博出现热点事件这种场景,因为在限流的同时可以应对一定的突发流量。如果采用漏桶那样的均匀速度处理请求的算法,在发生热点时间的时候,会造成大量的用户无法访问,对用户体验的损害比较大。

5.2、GateWay的实现:Spring Cloud Gateway官方就提供了RequestRateLimiterGatewayFilterFactory这个类,适用Redis和lua脚本实现了令牌桶的方式。

  1. 集成依赖
   <!--redis 用于实现gateway的限流-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
     <!--如果父项目中限定了版本的话,这里不需要再具体制定-->
    <version>2.1.3.RELEASE</version>   
</dependency>
  1. springboot入口类中注入KeyResolver,采用什么方式限流
@Slf4j
@EnableDiscoveryClient
@EnableCircuitBreaker
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class GatewayApplication {
    public static void main(String[] args) throws UnknownHostException {
        ConfigurableApplicationContext application = SpringApplication.run(GatewayApplication.class, args);

    }
	//注入bean
    @Bean
    public KeyResolver ipKeyResolver(){
        return new KeyResolver() {
            @Override
            public Mono<String> resolve(ServerWebExchange exchange) {
            	/**
            	* 限流条件:
            	* 1.用户ip地址(桶是私有)
				* 2.用户用户名(桶是私有)
				* 3.微服的路径(桶是共享的)
				*/
				//此处根据用户的ip做为条件限流
                return Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
            }
        };
    }

}
  1. application.yml文件中配置
    其实关键就是在filters中加入name,args的配置,可以对每个服务单独配置;
routes:
 - id: payment_routh #路由的ID,没有固定规则但要求唯一,建议配合服务名
#          uri: http://localhost:8001   #匹配后提供服务的路由地址
   uri: lb://cloud-payment-service #匹配后提供服务的路由地址
   predicates:
     - Path=/payment/get/**   #断言,路径相匹配的进行路由
   filters:
     - StripPrefix=1
     - name: RequestRateLimiter #请求数限流 名字不能随便写
       args:
         key-resolver: "#{@ipKeyResolver}"
         redis-rate-limiter.replenishRate: 1 #令牌桶每秒填充平均速率
         redis-rate-limiter.burstCapacity: 5 #令牌桶总容量

桶容量为5个,1秒钟加入一个,那么理论上用已经设置好的jemter请求参数,那就是10个请求应该有6个成功才对;

  1. jmeter测试

在这里插入图片描述
桶容量为5个,1秒钟加入一个,那么理论上用已经设置好的jemter请求参数,那就是10个请求应该有6个成功才对;

在这里插入图片描述

三、 业务推动技术

业务是什么?市场不是业务,运营不是业务,技术也不是业务,那业务到底是什么?维基百科的解释是“企业运用科学方法和生产工艺生产出可交付用户使用的产品与服务,并以此为企业带来利益的行为”。所以,业务应该是属于公司的,而不是属于某个部门的,运营和市场是业务方,而不是业务。
业务需要应该是王,而技术标准不是王。业务部门将有一系列广泛的战略目标。这些战略目标可能会与客户服务、效率和技术创新有关。

在这里插入图片描述

以业界为例,微软的产品一般到了V3.0才能用,1.0版、2.0版都不好用,但微软还是要发布。iPhone在2010年之前不好用,Android在2012年时也不好用,但是它们现在都很好用。同样Apple Watch 2现在不好用,我相信以后还是会好用的。整个行业都是这样,如果业务不认识到这一点,不了解技术的特征,不了解技术的工作流程,那自然就会对技术有误解,说不配合他们的工作。

业务规律对技术的要求。在起步阶段要新、要快,只开发核心功能MVP,然后快速迭代,快速验证商业逻辑;在发展阶段要有营销功能、粗放式运营功能,一定要有订单量,做技术才有价值;在成熟阶段要精细化运营、要大数据和分析功能、以及自动化功能。有了数据然后才需要分析,以自动化来节约成本和提高效率;在衰退阶段要转型、需要功能创新,减少系统维护。以上总结为四个字:销量、服务、管控、沉淀。即先以销量功能为主,然后做服务功能,接下来是管控功能,最后沉淀为基础业务服务,如以机+X的形式存在,机票作为基础业务,X作为创新点。


业务需要应该是王,而技术标准不是王。
  业务部门将有一系列广泛的战略目标。这些战略目标可能会与客户服务、效率和技术创新有关。只有在这个灵活的面向服务的流程与业务需求密切协调的时候才能满足这些目标。
  有太多的项目把重点放在了假设的、糟糕的或者虚构的业务需求方面。这种需求通常不是真正的机构需求、技术需求或者业务部门担心的需求。

腾讯拥有一个QQ,为什么还要开发出一款微信来?

在这里插入图片描述

国内有两款社交软件用户量最多,一款是微信,一款是QQ。而这两款社交软件,都是腾讯旗下的。很多80后和90后,都是同时拥有微信和QQ的。

快速的发展
从200人使用的小应用变成了亿级别的应用,过程中不断的代码重构,优化,以适应不同的流量级。

业务的沉淀
花里胡哨,不够简洁,业务验证臃肿的QQ空间,信息泄露。

一句话来说: 就是复杂的业务,难以扩展的代码,从而迫使腾讯结合趋势,开发了一款小型,轻便的通讯产品 : 微信

特斯拉放弃SAP后,仅四个月就开发了套ERP

汽车行业的众多优秀解决方案,甚至会不断的,渗透下沉到其他行业,比如编码的理念、配置驱动的研发、供应链、仓储管理、全生命周期的预测算法、工程变更的自动化应用、JIT、ANDON、动态成本控制等等。

按道理,Tesla直接使用汽车行业的最佳解决方案,应该是一个最经济有效的路径。
一开始,Tesla也是这么做的,主动牵手,成为了SAP客户。

Tesla于2012年6月22日推出的全电动车型Model S(参数|图片),为了更好的管理更大规模的生产,其CIO维贾扬带领的团队,也正在评估信息化系统(ERP)的构建方式?升级现有的SAP?还是另寻出路?正当评估着成本和周期的时候。

伊隆·马斯克找到了维贾扬,说:“不如我们自己建一套吧。”,当时ERP团队只有25个工程师。

时特斯拉的CTO Vijayan,使用了“低代码”平台,搭建了ERP的MVP版本,只用了4个月就完成了这个看似不可能完成的任务。

从上述的优秀应用产品中,能发现它们的几项共同点

  • 具有快速迭代的能立
  • 优先根据实际业务选择技术,当技术不满足业务时,再优化技术
  • 成本也是技术人应该控制的

总结

根据产品快速迭代,轻量级的特点,微服务,serverless 等轻型服务顺应而生,而网关是限流,权限,负载均衡,微服务直接的调节器,不可缺少。而选择一款合适的网关,也是至关重要。

深思:

  • 异步网关,gateway,zuul2.0 就是香的吗?zuul1.0的优势有哪些?
  • soa 是微服务吗? 它们的区别是什么? 这俩个架构可以兼容实施吗?
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值