随着互联网浏览变得越来越大。传统的MVC单一架构随着应用规模和应用模块的不断增加,整个应用变得越来越臃肿,越来越难维护。
我们必须采取按应用拆分的措施,也就是根据业务特点将原来的应用拆分成多个应用。例如,一个大型的电子商务系统可能包括用户系统、商品系统、订单系统、评价系统等,我们可以将它们分离成单独的应用程序。多应用架构的特点是应用相互独立,互不调用。
多应用虽然解决了应用臃肿的问题,但应用之间是相互独立的,一些常用的服务或代码无法复用。
单一应用解决方案
对于一个大型的互联网系统,一般有多个应用程序,应用程序之间往往有共同的服务,应用程序之间也存在调用关系。此外,大型互联网系统还有其他一些挑战,比如如何应对用户的快速增长,如何管理研发团队快速迭代产品开发,如何保持产品升级更稳定等等。
所以为了让业务很好的复用,模块更容易扩展和维护,我们希望业务和应用分开,某个业务不再属于一个应用,而是作为一个独立的服务来维护。应用程序本身不再是臃肿的模块堆栈,而是模块化服务组件的组合。
服务
特征
那么面向服务的方法有哪些亮点呢?
应用程序按业务拆分为服务
每个服务都可以独立部署
服务可以被多个应用程序共享
服务之间的通信
系统结构更清晰
核心模块稳定,服务组件单元升级,规避频繁发布风险
易于开发和管理
独立团队维护,工作清晰,职责明确
业务重用,代码重用
很容易扩展
服务化面临的挑战
系统服务后,增加了依赖的复杂度,也增加了服务之间的交互次数。在fpm的开发模式下。由于无法驻留在内存中,每个请求都必须从头开始加载。退出进程,增加了很多无用的开销,数据库连接无法重用或保护。由于fpm是以进程为单位的,所以fpm进程数也决定了并发数,这也是fpm开发的简单性给我们带来的。问题。那么为什么现在互联网平台上Java比较流行,.NET和PHP在这方面做得不好。更不用说 PHP 不是内存驻留的。除此之外,还有许多其他问题需要解决。
那么有没有好的方案呢?答案是肯定的,它是-Swoft。Swoft 是一个带有服务治理的 RPC 框架。Swoft 是第一个 PHP 常驻内存协程的全栈框架,一个基于高性能协程的 PHP 世界的 Boot
Swoft 提供了一种更优雅的方式来使用类似于 Dubbo 的 RPC 服务。Swoft的表现非常好,也有类似的表现。以下是 Swoft 性能的压力测试。
ab压力测试的处理速度非常惊人。在i78代CPU中,16GB内存下10000个请求在fpm开发模式下只需要5s就可以实现。这也足以证明 Swoft` 的高性能和稳定性,
优雅的服务治理
服务注册和发现
在微服务治理过程中,往往会涉及到将启动的服务注册到第三方集群,如/etcd等。以使用Swoft框架中的swoft-组件实现服务注册和发现为例。
实现逻辑
<?php declare(strict_types=1);
namespace AppCommon;
use ReflectionException;
use SwoftBeanAnnotationMappingBean;
use SwoftBeanAnnotationMappingInject;
use SwoftBeanExceptionContainerException;
use SwoftConsulAgent;
use SwoftConsulExceptionClientException;
use SwoftConsulExceptionServerException;
use SwoftRpcClientClient;
use SwoftRpcClientContractProviderInterface;
/**
* Class RpcProvider
*
* @since 2.0
*
* @Bean()
*/
class RpcProvider implements ProviderInterface
{
/**
* @Inject()
*
* @var Agent
*/
private $agent;
/**
* @param Client $client
*
* @return array
* @throws ReflectionException
* @throws ContainerException
* @throws ClientException
* @throws ServerException
* @example
* [
* 'host:port',
* 'host:port',
* 'host:port',
* ]
*/
public function getList(Client $client): array
{
// Get health service from consul
$services = $this->agent->services();
$services = [
];
return $services;
}
}
服务保险丝
在分布式环境中,尤其是在具有微服务结构的分布式系统中,一个软件系统调用另一个远程系统是很常见的。这个远程调用的被调用者可能是另一个进程,也可能是网络上的另一个主机。这个远程调用和进程的内部调用最大的不同就是远程调用可能会失败,或者挂起并且没有响应,直到超时。更糟糕的是,如果有多个调用者调用同一个暂停的服务,那么很可能一个服务的超时会迅速蔓延到整个分布式系统,造成连锁反应,消耗整个服务。分布式系统有很多资源。它最终可能导致系统瘫痪。
断路器 ( ) 模式旨在防止分布式系统中由这种级联连锁反应引起的灾难。
基本断路器模式保证在断路器处于打开状态时不会调用保护,但我们还需要额外的措施来在服务恢复后重置断路器。一种可能的方式是,断路器会定期检测服务是否恢复,一旦恢复,就将状态设置为关闭。重试时断路器处于半开状态。
断路器的使用简单而强大。只需使用 @ 注释。Swoft的熔断器可以在任何场景下使用,比如调用服务的时候,请求第三方的时候,可以熔断降级。
<?php declare(strict_types=1);
namespace AppModelLogic;
use Exception;
use SwoftBeanAnnotationMappingBean;
use SwoftBreakerAnnotationMappingBreaker;
/**
* Class BreakerLogic
*
* @since 2.0
*
* @Bean()
*/
class BreakerLogic
{
/**
* @Breaker(fallback="loopFallback")
*
* @return string
* @throws Exception
*/
public function loop(): string
{
// Do something
throw new Exception('Breaker exception');
}
/**
* @return string
* @throws Exception
*/
public function loopFallback(): string
{
// Do something
}
}
服务电流限制
对限流、熔断、降级的强调怎么强调都不过分,因为它确实非常重要。当服务失败时,它必须被炸毁。限流是保护自己的最大武器。如果没有自我保护机制,无论有多少连接,它都会收到。如果后端处理不了,前端流量大的时候肯定会挂掉。
当前的节流是在访问稀缺资源时限制并发数和请求数,例如秒杀和抢购产品,从而有效切峰和平滑流量曲线。限流的目的是限制并发访问和并发请求的速率,或者限制一个时间窗口内的请求速率以保护系统。一旦达到或超过速率限制,服务可能会被拒绝,或排队等待。
Swoft限流器底层采用令牌桶算法,底层依靠Redis实现分布式限流。
Swoft限速器不仅可以限制当前控制器,还可以限制任意bean中的方法,并且可以控制方法的访问速率。下面详细解释一下使用下面的例子
<?php declare(strict_types=1);
namespace AppModelLogic;
use SwoftBeanAnnotationMappingBean;
use SwoftLimiterAnnotationMappingRateLimiter;
/**
* Class LimiterLogic
*
* @since 2.0
*
* @Bean()
*/
class LimiterLogic
{
/**
* @RequestMapping()
* @RateLimiter(rate=20, fallback="limiterFallback")
*
* @param Request $request
*
* @return array
*/
public function requestLimiter2(Request $request): array
{
$uri = $request->getUriPath();
return ['requestLimiter2', $uri];
}
/**
* @param Request $request
*
* @return array
*/
public function limiterFallback(Request $request): array
{
$uri = $request->getUriPath();
return ['limiterFallback', $uri];
}
}
这里的key支持/-表达式,如果速度有限,会调用中定义的方法
配置中心
在说配置中心之前,先说一下配置文件。我们对它并不陌生。它为我们提供了动态修改程序运行的能力。引用别人的话:
系统运行时动态调整飞行姿态!
我可以称我们的工作是在快速飞行的飞机上修理零件。我们人类一直无法控制和预测一切。对于我们的系统来说,当我们需要控制系统的方向(如灰度控制、限流调整)时,我们总是需要预留一些控制线来进行调整,这对于拥抱变化的互联网行业来说尤其重要。
对于单机版,我们称之为配置(文件);对于分布式集群系统,我们称之为配置中心(系统);
分布式配置中心到底是什么?
随着业务的发展和微服务架构的升级,服务的数量和程序的配置越来越多(各种微服务,各种服务器地址,各种参数),不再是传统的配置文件方式和数据库方式足以发展。配置管理人员要求:
安全性:配置随源代码存储在代码库中,容易造成配置泄露;
及时性:修改配置需要重启服务才能生效;
限制:不支持动态调整:如日志切换、功能切换;
因此,我们需要一个配置中心来统一管理配置!将业务开发者从复杂繁琐的配置中解放出来,只需要专注于业务代码本身,就能显着提升开发和运维效率。同时,配置和发布包的解耦进一步提高了发布的成功率,为运维的细粒度控制和应急处理提供了强有力的支持。
关于分布式配置中心,网上已经有很多开源的解决方案,比如:
是携程框架部门开发的分布式配置中心。它可以集中管理不同环境和应用集群的配置。配置修改后,可以实时推送到应用端。具有标准化的权限、流程治理等特性,适用于微服务配置。管理场景。
例如,从远程配置中心拉取配置并安全重启服务。如果不熟悉,可以先看一下 Swoft 扩展组件,阅读官方文档。
以 Swoft 为例,更改配置时重启服务(http-/rpc-/ws-)。下面是一个代理的例子:
<?php declare(strict_types=1);
namespace AppModelLogic;
use SwoftApolloConfig;
use SwoftApolloExceptionApolloException;
use SwoftBeanAnnotationMappingBean;
use SwoftBeanAnnotationMappingInject;
/**
* Class ApolloLogic
*
* @since 2.0
*
* @Bean()
*/
class ApolloLogic
{
/**
* @Inject()
*
* @var Config
*/
private $config;
/**
* @throws ApolloException
*/
public function pull(): void
{
$data = $this->config->pull('application');
// Print data
var_dump($data);
}
}
暂无评论内容