RPC simple microservice architecture based on hyperf

Time:2020-12-6
This demo has been uploaded to GitHub:
Link: hyperf RPC demo

Why RPC? Not http

1. In short, RPC does not have so many HTTP request and response body fields, such as:content-typeuser-agentaccept-languagecontent-encodingexpiresAnd so on. Often these fields account for 70% of the message content. If the number of requests is too frequent, you can imagine how much the performance and network overhead will be.

2. In the internal server communication, we can completely reduce the number of handshakes

  • With http2.0, http2.0 can send data multiple times on a connection. Compared with the current HTTP1.1 mode, it is still non blocking
  • Use RPC Protocol Based on TCP to transmit data on long connection

Based on the above, httpv1.1 server to server communication between microservices is not the best solution. This is why many PHP frameworks based on php-fpm are not suitable for microservices, because each request of php-fpm will generate a new woker process. If every worker runs to establish an HTTP1.1 connection with microservices, it is meaningless

Why consult?

What is consult? Why service discovery is needed? Just look at the picture

RPC simple microservice architecture based on hyperf

I have deployed a set of HTTP service (service consumer) interface in Server1, but it also relies on the service (service provider) of server2. Server1 does not need to know the address of server2, but only needs to know the service provider center of consult, which will help me register all services

In reality, for example, team a of a large company is doing the core functions of HTTP business, and team B has done a lot of service wheels. Team a can’t always go to team B every time they develop. Team B asks, “what’s your address? What is the port? What’s the name of the service? Tell me to call. If you want to call 100 services, isn’t team a busy with configuring IP and ports every time?

1、 Build consult in server 1

1. Download consult for Linux. After decompressing, it will be an executable file, which can be directly MV to / usr / bin / consult

2. Create a new consult folder, and create a data folder and etc folder in it. The data folder is used to store the data files of the consult, and etc is used to store the configuration files

3. Switch to the etc folder and create a new one web.json The contents of the document are as follows:

{
    "service": {
        //The ID of the service must be unique
        "id": "CalculatorService",
        //Here, write the service name, which is also the ID name, which is not unique
        "name": "CalculatorService",
        //To register a service, fill in the IP address of the server on which the service is located. Here, I fill in the IP of server2, because server2 provides the service to Server1 to call
        "address": "server2.ip.server2.ip",
        //Write casually
        "tags": [
            "webapi"
        ],
        //As above, the service also has a port. Fill in the port provided by the server, and fill in the port of server2 here
        "port": 9502
    }
}

4. Return to the consult directory and start consult, where – config dir specifies the configuration directory and – Data dir specifies the directory where the data is stored

consul agent -dev -ui -config-dir=./etc -data-dir=./data -client=0.0.0.0

Client = 0.0.0.0.0 it should be noted that the Internet is generally 127.0.0.1. If it is written as 127.0.0.1, it can also run, but it is not possible to access the UI interface of the consult in the Internet, so it is changed to 0.0.0.0

5. Enter IP: 8500 in the browser and you will see that the consult installation is successful

2、 Install and set up the hyperf service provider on server 2

1. Create a new RPC folder in the app directory. First create a calculatorserviceinterface interface file named calculate atorServiceInterface.php

<?php

namespace App\Rpc;

interface CalculatorServiceInterface
{
    public function add(int $a, int $b): int;
}

2. Based on this interface, add a calculatorservice of implementation mode in the directory, and the file name is: CalculatorService.php

<?php


namespace App\Rpc;

use Hyperf\RpcServer\Annotation\RpcService;

/**
 *Note that if you want to manage services through the service center, you need to add the publishto attribute in the annotation
 * @RpcService(name="CalculatorService", protocol="jsonrpc-http", server="jsonrpc-http" ,publishTo="consul")
 */
class CalculatorService implements CalculatorServiceInterface
{
    public function add(int $a, int $b) : int
    {
        return $a +$b;
    }
}

Here, the annotation method is used to provide the service. Name is the service name, and the protocol specifies that the JSON RPC HTTP protocol is used. Here, the publishto option is added to specify a service registry, because the consult has been set up before

3. Open config / autoload/ server.php , under the servers array, add an array:

[
    'name' => 'jsonrpc-http',
    'type' => Server::SERVER_HTTP,
    'host' => '0.0.0.0',
    'port' => 9502,
    'sock_type' => SWOOLE_SOCK_TCP,
    'callbacks' => [
       SwooleEvent::ON_REQUEST => [\Hyperf\JsonRpc\HttpServer::class, 'onRequest'],
    ],
],

In this way, hyperf will publish and run the services in the code as port 9502. The port here is actually the same as the above consult configuration file web.json So that the service 9502 can be discovered by consult

3、 Install and set up the hyperf service consumer on server 1

1. Here I create a new project to represent the consumer consumer service model. I also create a new RPC folder in the app directory. First, create a calculatorserviceinterface interface file named calculate atorServiceInterface.php

<?php

namespace App\Rpc;

interface CalculatorServiceInterface
{
    public function add(int $a, int $b): int;
}

2. Open app / controllers/ IndexController.php

<?php
namespace App\Controller;

use App\Rpc\CalculatorServiceInterface;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Annotation\AutoController;

/**
 * Class IndexController
 * @package App\Controller
 * @AutoController()
 */
class IndexController extends AbstractController
{
    /**
     *// here, we inject an interface class and call the add method of the interface directly, but there is no add in this project 
Method implementation, the real add method has been implemented in the service provider, hyperf will help us find the corresponding service and use it
     * @Inject()
     * @var CalculatorServiceInterface
     */
    private $calculatorService;

    public function index()
    {
        return $this->calculatorService->add(1,2);
    }
}

2. Create a new one under config / autoload services.php

<?php
return [
    'consumers' => [
        [
            //The name must be the same as the name attribute of the service provider
            'name' => 'CalculatorService',
            //Service interface name, optional. The default value is equal to the value configured by name. If name is defined as an interface class directly, you can ignore this line of configuration. If name is a string, you need to configure service to correspond to the interface class
            'service' => \App\Rpc\CalculatorServiceInterface::class,


            //Which service center does the consumer want to get the node information from? If it is not configured, it will not get the node information from the service center
            'registry' => [
                'protocol' => 'consul',
                //The address here means that the IP address of the server where the consult is set up will be filled in
                'address' => 'http://127.0.0.1:8500',
            ],
        ]
    ],
];

In this way, when the request comes in, the indexcontroller will inject the service, and the hyperf will tell the service that it should go services.php To find the service

3. Configure / autoload/ server.php Change port to 9503, and access the index controller through 9503 later. This is just a demonstration. In reality, you can change it to the port you want to access

    'servers' => [
        [
            'name' => 'http',
            'type' => Server::SERVER_HTTP,
            'host' => '0.0.0.0',
            'port' => 9503,
            'sock_type' => SWOOLE_SOCK_TCP,
            'callbacks' => [
                SwooleEvent::ON_REQUEST => [Hyperf\HttpServer\Server::class, 'onRequest'],
            ],
        ],
    ],

4、 Run

1. Restart consult. If it has been started before, kill the PID of – 9 consult first

consul agent -dev -ui -config-dir=./etc -data-dir=./data -client=0.0.0.0

2. Switch to the server 2’s superf provider and start

php bin/hyperf.php start

3. Switch to server 1’s superf consumer and start

php bin/hyperf.php start

4. Open the HTTP 8500 port of Server1 in the browser and view the consult interface. You can find the provider of hyperf under server2

RPC simple microservice architecture based on hyperf

5. Browse to servier1’s services

RPC simple microservice architecture based on hyperf

You can see that the 9503 service under Server1 is normal. It will visit the consult-8500 center under Server1, and then the consult-8500 center will access the 9502 service under server2, and then return it to 9503 of Server1

So here we have completed the whole simple micro service system. Sorry for the bad writing~

Recommended Today

Regular expression sharing for checking primes

This regular expression is shown as follows: Regular expressions for checking prime numbers or not To use this positive regular expression, you need to convert the natural number into multiple 1 strings. For example, 2 should be written as “11”, 3 should be written as “111”, 17 should be written as “11111111111”. This kind of […]