What is Swoft?
Swoft is a PHP microservices coroutine framework based on the Swoole extension. Like Go, Swoft has a built-in coroutine web server and a common coroutine client and is resident in memory, independent of traditional PHP-FPM. There are similar Go language operations, similar to the Spring Cloud framework flexible annotations, powerful global dependency injection container, comprehensive service governance, flexible and powerful AOP, standard PSR specification implementation and so on.
Through three years of accumulation and direction exploration, Swoft has made Swoft the Spring Cloud in the PHP world, which is the best choice for PHP's high-performance framework and microservices management.
Update
Remove
- Remove
request->json()
method(c9e8f04)
Enhancement
- Add interface dependency injection(6169f84)
- Add
getFile
to obtain information after file upload and save(fe7e3a6) - Add
restart()
to restart service(2ffec37) - Add call 1.x RPC service support(30d73c3)
- Add AOP class name matching supports regular expressions(bc5e479)
- Add RPC Server /Http server Middleware namespace
use
error prompt(b1cec04) - Add validator exclusion attribute field with
unfields
(b1bf44f) - Add auto write timestamp(dc58011)
- Add model action event(dc58011)
- Add database migration script(26bb464)
- Add entity automatically interact with json and arrays(dc58011)
- Add model batch update method with
batchUpdateByIds
(dc58011)
Fixed:
- Fix cookies some problems when setting up, add some related methods with withCookie(b05afbb01)
- Fix no capture processing error when the console uses the coroutine mode to run the command.(8a5418bf)
- Fix restart websocket server command does not stop the old server problem first(db2d935)
- Fix task return value is
null
(a69347c) - Fix RPC Server only class middleware can't be used(204bc7f)
- Fix RPC Server return value is
null
(4d091be) - Fix Logger and CLog log level cannot be overwritten and invalid(8eb8aba)
- Fix attributes in the model do not support custom expressions(dc58011)
Update:
- Validator optimization, support for custom validation rules(d959a4f)
- Rename the error handling management class
ErrorHanlders
toErrorManager
(f3a8f04b) - The exception handling of the console component is changed to the unified processing style provided by the error component. (4f47204)
- Console component allows to set the disable command group(c5a0269)
- In the default error handling, the error capture level is allowed to be set. The default level is
E_ALL | E_STRICT
(afff9029) - Optimization When the ws server is started, the http processing function is enabled at the same time, and the information panel adds prompts.(83a81170)
- Optimize Start the ws server and add the rpc server to start. The information panel does not display the rpc server information.(3d1d0d848)
Extra:
- Document add support search by google
- New apollo Component
- New consul Component
- New breaker Component
- New limter component
Elegant service governance
Swoft officially recommends that developers use service mesh patterns, such as the Istio/Envoy framework, to separate business and service governance, but Swoft also provides a set of microservices components for small and medium-sized businesses to quickly build microservices.
Service registration and discovery
For service registration and discovery, the swoft-consul component provided by Swoft is required, if other third parties are similar.
Registration and cancellation services
Listen for the SwooleEvent::START
event, register the service
/**
* Class RegisterServiceListener
*
* @since 2.0
*
* @Listener(event=SwooleEvent::START)
*/
class RegisterServiceListener implements EventHandlerInterface
{
/**
* @Inject()
*
* @var Agent
*/
private $agent;
/**
* @param EventInterface $event
*/
public function handle(EventInterface $event): void
{
/* @var HttpServer $httpServer */
$httpServer = $event->getTarget();
$service = [
// ....
];
$scheduler = Swoole\Coroutine\Scheduler();
$scheduler->add(function () use ($service) {
// Register
$this->agent->registerService($service);
CLog::info('Swoft http register service success by consul!');
});
$scheduler->start();
}
}
Listen for the SwooleEvent::SHUTDOWN
event, cancel the service
/**
* Class DeregisterServiceListener
*
* @since 2.0
*
* @Listener(SwooleEvent::SHUTDOWN)
*/
class DeregisterServiceListener implements EventHandlerInterface
{
/**
* @Inject()
*
* @var Agent
*/
private $agent;
/**
* @param EventInterface $event
*/
public function handle(EventInterface $event): void
{
/* @var HttpServer $httpServer */
$httpServer = $event->getTarget();
$scheduler = Swoole\Coroutine\Scheduler();
$scheduler->add(function () use ($httpServer) {
$this->agent->deregisterService('swoft');
});
$scheduler->start();
}
}
Service discovery
Defining a service provider
/**
* Class RpcProvider
*
* @since 2.0
*
* @Bean()
*/
class RpcProvider implements ProviderInterface
{
/**
* @Inject()
*
* @var Agent
*/
private $agent;
/**
* @param Client $client
*
* @return array
* @example
* [
* 'host:port'
* ]
*/
public function getList(Client $client): array
{
// Get health service from consul
$services = $this->agent->services();
$services = [
];
return $services;
}
}
Configuration service provider
return [
'user' => [
'class' => ServiceClient::class,
'provider' => bean(RpcProvider::class)
// ...
]
];
Service breaker
Swoft uses the @Breaker
annotation to achieve a blow, which can be blown on any method.
/**
* Class BreakerLogic
*
* @since 2.0
*
* @Bean()
*/
class BreakerLogic
{
/**
* @Breaker(fallback="funcFallback")
*
* @return string
* @throws Exception
*/
public function func(): string
{
// Do something
throw new Exception('Breaker exception');
}
/**
* @return string
*/
public function funcFallback(): string
{
return 'funcFallback';
}
}
Service limit
Swoft uses the @RateLimiter
annotation to implement service throttling, which can be throttled on any method, not just the controller, and KEY also supports symfony/expression-language expression language.
/**
* Class LimiterController
*
* @since 2.0
*
* @Controller(prefix="limiter")
*/
class LimiterController
{
/**
* @RequestMapping()
* @RateLimiter(key="request.getUriPath()", fallback="limiterFallback")
*
* @param Request $request
*
* @return array
*/
public function requestLimiter(Request $request): array
{
$uri = $request->getUriPath();
return ['requestLimiter', $uri];
}
/**
* @param Request $request
*
* @return array
*/
public function limiterFallback(Request $request): array
{
$uri = $request->getUriPath();
return ['limiterFallback', $uri];
}
}
Configuration center
The configuration center needs to use the Swoft-apollo component provided by Swoft officially, if other third parties are similar.
Declare Agent
/**
* Class AgentCommand
*
* @since 2.0
*
* @Command("agent")
*/
class AgentCommand
{
/**
* @Inject()
*
* @var Config
*/
private $config;
/**
* @CommandMapping(name="index")
*/
public function index(): void
{
$namespaces = [
'application'
];
while (true) {
try {
$this->config->listen($namespaces, [$this, 'updateConfigFile']);
} catch (Throwable $e) {
CLog::error('Config agent fail(%s %s %d)!', $e->getMessage(), $e->getFile(), $e->getLine());
}
}
}
/**
* @param array $data
*
* @throws ContainerException
* @throws ReflectionException
*/
public function updateConfigFile(array $data): void
{
foreach ($data as $namespace => $namespaceData) {
$configFile = sprintf('@config/%s.php', $namespace);
$configKVs = $namespaceData['configurations'] ?? '';
$content = '<?php return ' . var_export($configKVs, true) . ';';
Co::writeFile(alias($configFile), $content, FILE_NO_DEFAULT_CONTEXT);
CLog::info('Apollo update success!');
/** @var HttpServer $server */
$server = bean('httpServer');
$server->restart();
}
}
}
Start Agent
The Agent only needs to run before the service (Http/RPC/Websocket) is started.
php bin/swoft agent:index
Resource
- GitHub: https://github.com/swoft-cloud/swoft
- Website:https://en.swoft.org
- Document:https://en.swoft.org/docs
- Discuss:swoft-cloud/community
Top comments (0)