Why service governance

As Internet browsing gets bigger and bigger. With the continuous expansion of application scale and the increase of application modules, the traditional MVC single architecture also becomes more and more bloated and difficult to maintain.

We must take measures to split the original application into multiple applications according to service characteristics. For example, a large e-commerce system may include user system, commodity system, order system, evaluation system and so on. We can separate them into separate applications. The characteristic of multi-application architecture is that applications are independent of each other and do not call each other.

Although multiple applications solve the problem of application bloat, they are independent from each other and some common services or codes cannot be reused.

A single application solution

For a large Internet system, there are usually multiple applications, and there are common services and call relationships between applications. In addition, there are other challenges for large Internet systems, such as how to cope with the rapid growth of users, how to manage rapid iterative product development by r&d teams, how to keep product upgrades more stable, and so on.

Therefore, in order to make services reusable and modules easier to expand and maintain, we hope that services and applications are separated, so that a service is maintained as an independent service instead of belonging to an application. The application itself is no longer a bloated stack of modules, but composed of modular service components.

As a service

The characteristics of

So what are the highlights of servitization?

  • Applications are divided into services by service
  • Each service can be deployed independently
  • Services can be shared by multiple applications
  • Services can communicate with each other
  • Architecturally, the system is clearer
  • Core modules are stable and upgraded on a service component basis, avoiding the risk of frequent release
  • Convenient development and management
  • Individual team maintenance, clear work, clear responsibilities
  • Business reuse, code reuse
  • It’s very easy to expand

The challenges of servitization

After the servitization of the system, the complexity of dependency relationship will increase, and the number of interactions between services will also increase. In FPM development mode. Unable to permanent memory brings us, every request will be loaded into the exit process from scratch, has increased a lot of useless overhead, database connection can’t reuse is not protected, because the FPM is process unit number also determines the number of concurrent processes of FPM, which is brought to us is the FPM development simple problems. That’s why the Internet platform Java is so popular right now, while.NET and PHP are not. Not to mention PHP is non-memory resident. There are many other issues that need to be addressed.

  • More and more services, complex configuration management
  • The dependencies between services are complex
  • Load balancing between services
  • Service Expansion
  • Service monitoring
  • Service degradation
  • Service authentication
  • Services go online and offline
  • Service documentation……

You can imagine the benefits of resident memory for example

  • Just start frame initialization and if we’re resident in memory we’re just going to start up and initialize the frame in memory and focus on processing the request

  • Connection multiplexing, which some engineers don’t understand very well, what if you don’t need a connection pool, and just send a connection for each request? This can result in too many connections to back-end resources. For some basic services, such as Redis, databases, connections are expensive.

So is there a good plan? The answer is yes, and a lot of people are using this framework, which is -Swoft. Swoft is an RPC framework with service governance capabilities. Swoft is the first PHP resident memory coroutine full-stack framework, based on the core concept of convention over configuration proposed by Spring Boot

Swoft provides a more elegant way to use RPC services like Dubbo, Swoft performance is very good with golang-like performance, below is my PC pressure test of Swoft performance.

The processing speed of AB pressure test is very amazing. In the I78 generation CPU and 16GB memory, 100,000 requests only take 5s, which is basically impossible to achieve under the FPM development mode. This also demonstrates Swoft’s high performance and stability,

Elegant service governance

Service registration and discovery

Microservice governance often involves registering started services to a third-party cluster, such as Consul/ETcd. This chapter uses the Swoft -Consul component in the Swoft framework as an example to implement service registration and discovery.

Implementation logic


       declare(strict_types=1);


namespace App\Common;


use ReflectionException;
use Swoft\Bean\Annotation\Mapping\Bean;
use Swoft\Bean\Annotation\Mapping\Inject;
use Swoft\Bean\Exception\ContainerException;
use Swoft\Consul\Agent;
use Swoft\Consul\Exception\ClientException;
use Swoft\Consul\Exception\ServerException;
use Swoft\Rpc\Client\Client;
use Swoft\Rpc\Client\Contract\ProviderInterface;

/**
 * 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; }}Copy the code

Service fusing

In distributed environment, especially in distributed system with microservice structure, it is very common for one software system to call another remote system. This remote call may be called by another process or another host across the network. The main difference between this remote call and the internal call of the process is that the remote call may fail or hang without any response until time out. Worse, if there are multiple callers calling the same suspended service, there is a high probability that a timeout wait for one service will quickly spread throughout the distributed system, causing a chain reaction that consumes a large amount of resources throughout the distributed system. Eventually, the system may crash.

The Circuit Breaker pattern is designed to prevent such cascading disasters in distributed systems.

The basic circuit breaker mode ensures that the Supplier does not call the protection when the circuit breaker is open, but additional measures are required to reset the circuit breaker after the Supplier resumes service. One possible solution is for the circuit breaker to periodically detect if the supplier’s service is restored and set the state to close when it is. The circuit breaker is in half-open state when it retries.

Using fuses is thought to be simple and powerful. Just use an @breaker annotation. Swoft fuses can be used in any scenario, such as service calls, and can be fuses degraded when requesting third parties


       declare(strict_types=1);


namespace App\Model\Logic;

use Exception;
use Swoft\Bean\Annotation\Mapping\Bean;
use Swoft\Breaker\Annotation\Mapping\Breaker;

/**
 * Class BreakerLogic
 *
 * @since 2.0
 *
 * @Bean() * /
class BreakerLogic
{
    / * * *@Breaker(fallback="loopFallback")
     *
     * @return string
     * @throws Exception
     */
    public function loop(a): string
    {
        // Do something
        throw new Exception('Breaker exception');
    }

    / * * *@return string
     * @throws Exception
     */
    public function loopFallback(a): string
    {
        // Do something}}Copy the code

Service current limiting

I can’t emphasize this enough, because it’s really important. Be sure to disconnect when the service is out of order. If there is no self-protection mechanism, no matter how many connections will be received. If the back-end can not handle it, the front-end traffic will certainly hang up when there is a lot of traffic.

Limiting traffic is used to limit the number of concurrent requests and requests for access to scarce resources, such as the second kill and the purchase of goods, so as to effectively shave the peak and smooth the flow curve. The purpose of traffic limiting is to limit the rate of concurrent access and requests, or to limit the rate of requests within a time window to protect the system. Once the rate reaches or exceeds the limit, the system can deny services or wait in a queue.

The bottom layer of Swoft traffic limiter adopts token bucket algorithm, and the bottom layer relies on Redis to realize distributed traffic limiter.

The Swoft limiter can limit not only the flow controller, but also any method in the bean, and can control the access rate of the method. Here is an example of how to use it


       declare(strict_types=1);

namespace App\Model\Logic;

use Swoft\Bean\Annotation\Mapping\Bean;
use Swoft\Limiter\Annotation\Mapping\RateLimiter;

/**
 * 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]; }}Copy the code

Key supports symfony/expression-language expressions. If the speed limit is limited, the limiterFallback method defined in fallback will be called

Configuration center

Before talking about configuration center, let’s talk about configuration files. We are not unfamiliar with them. They provide us with the ability to dynamically modify the application execution. To quote someone else:

Dynamic adjustment of flight attitude during system runtime!

I might call our job fixing parts on a fast-moving plane. We humans are always out of control and out of control. For our system, we always need to reserve some control lines, so that we can make adjustments when we need to control the direction of the system (such as gray control and current limiting adjustment), which is particularly important for the Internet industry to embrace changes.

For the standalone version, we call this configuration (file); For a distributed cluster system, we call it a configuration center (system);

What exactly is a distributed configuration center

With the development of business and the upgrade of micro-service architecture, the number of services and the configuration of programs (various micro-services, various server addresses and various parameters) are increasing day by day. The traditional configuration file and database can no longer meet the requirements of developers for configuration management:

  • Security: Configuration is stored in the code base along with the source code, which is easy to cause configuration leakage.
  • Timeliness: The modification takes effect only after the service is restarted.
  • Limitations: Cannot support dynamic adjustment, such as log switch and function switch.

Therefore, we need a configuration center to centrally manage configuration! Freeing business developers from complex and tedious configurations and focusing on the business code itself can significantly improve development and operation efficiency. At the same time, the uncoupling of configuration and release package will further improve the success rate of release, and provide strong support for the fine force control and emergency treatment of operation and maintenance.

There are already many open source solutions for distributed configuration centers on the web, such as:

Apollo is a distributed configuration center developed by the Framework department of Ctrip. It can centrally manage configurations in different environments and clusters, and push configurations to applications in real time after modification. It has standardized permissions and process governance features, and is suitable for micro-service configuration management scenarios.

This section uses Apollo as an example to pull configurations from the remote configuration center and safely restart services. If you are not familiar with Apollo, take a look at the Swoft extension Apollo component and read the official Apollo documentation.

This chapter uses Apollo in Swoft as an example. After Apollo configuration is changed, the service (HTTP-server/Rpc-server/WS-server) is restarted. Here is an agent example:


       declare(strict_types=1);


namespace App\Model\Logic;

use Swoft\Apollo\Config;
use Swoft\Apollo\Exception\ApolloException;
use Swoft\Bean\Annotation\Mapping\Bean;
use Swoft\Bean\Annotation\Mapping\Inject;

/**
 * Class ApolloLogic
 *
 * @since 2.0
 *
 * @Bean() * /
class ApolloLogic
{
    / * * *@Inject()
     *
     * @var Config
     */
    private $config;

    / * * *@throws ApolloException
     */
    public function pull(a): void
    {
        $data = $this->config->pull('application');
        
        // Print datavar_dump($data); }}Copy the code

The above is a simple Apollo configuration pull, Swoft-Apollo in addition to this method, but also provides more methods to use.

The official link

  • Github
  • Doc
  • swoft-cloud/community