Php-msf source code details, php-msf source code

Source: Internet
Author: User

Php-msf source code details, php-msf source code

Let's take a look at the specific source code: php-msf: https://github.com/pinguo/php-msf

The source code has been interpreted for a while. Summarize your experiences:

Capture the lifecycle and let the code run in your mind

Analysis Architecture, hierarchical border isolation of keywords

A good framework, clear the lifecycle and architecture, is basically familiar with the status, followed by filling in details and coding skills

Here are several important experiences:

Understand what this tool is good at and what it is suitable for. This information is also very easy to obtain. The tool documentation is usually marked out in a conspicuous manner. You can try to see each other through these features/features.

From the engineering point of view, this project is mainly distinguished from the above architecture. In addition to processing core business, that is, the above functions/features, engineering also involves security, testing, coding specifications, and language features. These are also part of business code that is rarely considered and rarely practiced.

We recommend that you use phpstorm, Baidu brain chart, Markdown notes, and the source of blog and php-msf to write blogs related to technical life, serve food directly.

Lifecycle & architecture

The official document has produced a very good figure: process the request flowchart. We recommend that you make similar diagrams in your spare time, which is helpful to your thinking.

Based on this figure, we will not go into details about the lifecycle and architecture. Here we will analyze some technical points in msf:

Coroutine related knowledge

Technical point Excerpt from msf

Coroutine

I will explain it in my way. If you need to know more, you can refer to the resources I recommend later.

Class vs object is a group of important concepts. class represents our abstraction of things. This abstraction capability will be used in the future. We hope that you can cultivate your awareness in this field to at least make it accessible. objects are instantiated classes and actually work. The coroutine we will discuss is such a real working role.

Where does coroutine come from, where does it go, and what does it do?

Think about these simple questions. Maybe you have a deeper understanding of the coroutine. Remember these keywords:

Generation. You need to have a place to generate a coroutine. You may not need to know the details, but you need to know when it happened.

Scheduling. There must be a lot of coroutines working together, so scheduling is required. How can we schedule it?

Destroyed. Will it be destroyed? When will it be destroyed?

Now let's take a look at the usage comparison of coroutine. Here, we should note that I have not compared the implementation of coroutine, because many times the actual requirements are as follows:

I don't care how to implement it. I chose the best one.

// Msf-one-time coroutine scheduling $ response = yield $ this-> getRedisPool ('tw ')-> get ('apicacheforabcoroutine '); // msf-concurrent coroutine call $ client1 = $ this-> getObject (Client: class, ['HTTP: // www.baidu.com/']); yield $ client1-> goDnsLookup (); $ client2 = $ this-> getObject (Client: class, ['HTTP: // www.qq.com/']); yield $ client2-> goDnsLookup (); $ result [] = yield $ client1-> goGet ('/'); $ result [] = yield $ client2-> goGet ('/');

The equation is roughly like this: Use coroutine = with yield, so you can figure out where yield needs to be added-where there is blocking IO, such as file IO, network I/O (redis, mysql, and http.

Of course, there is something worth attention.

The coroutine scheduling sequence may degrade to synchronous calling if you do not pay attention to it.

Call chain: yield must be added to the call chain using yield. For example, the following is the case:

Function a_test () {return yield $ this-> getRedisPool ('tw ')-> get ('apicacheforabcoroutine');} $ res = yield a_test (); // If yield is not added, the execution is synchronized.

Compare swoole2.0's coroutine solution:

$ Server = new Swoole \ Http \ Server ("127.0.0.1", 9502, SWOOLE_BASE); $ server-> set (['worker _ num' => 1,]); // In the asynchronous callback function of the coroutine server, $ server-> on ('request', function ($ Request, $ response) {$ tcpclient = new Swoole \ Coroutine \ Client (SWOOLE_SOCK_TCP); // you need to use the Coroutine Client $ tcpclient-> connect ('123. 0.0.1 ', 9501, 0.5) $ tcpclient-> send ("hello world \ n"); $ redis = new Swoole \ Coroutine \ Redis (); $ redis-> connect ('2017. 0.0.1 ', 6379); $ redis-> setDefer (); // mark the delayed package for concurrent calls $ redis-> get ('key '); $ mysql = new Swoole \ Coroutine \ MySQL (); $ mysql-> connect (['host' => '2017. 0.0.1 ', 'user' => 'user', 'Password' => 'pass', 'database' => 'test',]); $ mysql-> setDefer (); $ mysql-> query ('select sleep (1) '); $ httpclient = new Swoole \ Coroutine \ Http \ Client ('0. 0.0.0 ', 9599); $ httpclient-> setHeaders (['host' => "api.mp.qq.com"]); $ httpclient-> set (['timeout' => 1]); $ httpclient-> setDefer (); $ httpclient-> get ('/'); $ tcp_res = $ tcpclient-> recv (); $ redis_res = $ redis-> recv (); $ mysql_res = $ mysql-> recv (); $ http_res = $ httpclient-> recv (); $ response-> end ('test end') ;}); $ server-> start ();

Swoole2.0 coroutine solution has obvious advantages:

You don't need to add yield.

Concurrent calls do not need to pay attention to the yield sequence. Use defer () to delay packet collection.

However, there is no way to directly use coroutine = with a simple equation like yield. The above example must be used with swoole coroutine server + swoole coroutine client:

The server generates a coroutine when an asynchronous callback is triggered.

Client triggers coroutine Scheduling

Destroys the coroutine at the end of asynchronous callback execution

This leads to two problems:

What should I do not use the asynchronous callback of the swoole Coroutine server: Use Swoole \ Coroutine: create () to explicitly generate the Coroutine

What should I do if I need to use other coroutine clients: This is the goal of Swoole3, and Swoole2.0 can consider using coroutine tasks for disguise?

It seems that it is easier to use coroutine = and yield? I don't think so. I want to add some ideas for your consideration:

The yield method is used to implement the php coroutine scheduler based on the PHP generator +. If you want to use the scheduler without errors, such as the coroutine scheduling sequence above, you still need to figure out the implementation of this scheduler.

Swoole2.0's native method makes it easier to understand. You only need to know the timing of coroutine generation, scheduling, and destruction.

Is it very performance-consuming to frequently create and destroy coroutines in asynchronous callbacks such as Swoole2.0? -- No. Some memory operations are actually much smaller than process/object operations.

Technical point Excerpt from msf

Msf has many advantages in design and many codes are worth learning.

Request Context

This is a very important concept from fpm to swoole http server. fpm is a multi-process mode. Although $ _ POST and other variables are called Super global variables, these variables are isolated between different fpm processes. however, in the swoole http server, a worker process processes multiple requests asynchronously. A simple understanding is the following equation:

fpm worker : http request = 1 : 1swoole worker : http request = 1 : n

Therefore, we need a new method to isolate requests.

In programming languages, there is a professional term scope (scope). Usually scope/lifecycle is used, so the concept of lifecycle that I have been emphasizing is really important.

Swoole itself implements isolation:

$http = new swoole_http_server("127.0.0.1", 9501);$http->on('request', function ($request, $response) {  $response->end("

Msf also implements a layer of encapsulation on the Context to make the Context look as desired:

// You can almost use this method to complete any required logic $ this-> getContext ()-> xxxModule-> xxxModuleFunction ();

For details, see the src/Helpers/Context. php file.

Object pool

The object pool concept may be unfamiliar to everyone. It aims to reduce the frequent creation and destruction of objects to improve performance. msf has well encapsulated and is easy to use:

// GetObject (): // ** @ var DemoModel $ demoModel */$ demoModel = $ this-> getObject (DemoModel: class, [1, 2]);

The specific code of the Object Pool is under src/Base/Pool. php:

Dynamic Object creation using reflection at the underlying layer

Public function get ($ class,... $ args) {$ poolName = trim ($ class, '\'); if (! $ PoolName) {return null;} $ pool = $ this-> map [$ poolName]? Null; if ($ pool = null) {$ pool = $ this-> applyNewPool ($ poolName);} if ($ pool-> count ()) {$ obj = $ pool-> shift (); $ obj->__ isConstruct = false; return $ obj ;} else {// use reflection $ reflector = new \ ReflectionClass ($ poolName); $ obj = $ reflector ctor-> newInstanceWithoutConstructor (); $ obj->__ useCount = 0; $ obj->__ genTime = time (); $ obj->__ isConstruct = false; $ obj->__ DSLevel = Macro: DS_PUBLIC; unset ($ reflector ); return $ obj ;}}

Use SplStack to manage objects

Private function applyNewPool ($ poolName) {if (array_key_exists ($ poolName, $ this-> map) {throw new Exception ('the name is exists in pool map ');} $ this-> map [$ poolName] = new \ SplStack (); return $ this-> map [$ poolName];} // management object $ pool-> push ($ classInstance); $ obj = $ pool-> shift ();

Connection Pool & proxy

Connection Pool Pools

The concept of the connection pool will not be repeated. Let's look at the implementation in msf. The Code is under src/Pools/AsynPool. php:

public function __construct($config){  $this->callBacks = [];  $this->commands = new \SplQueue();  $this->pool   = new \SplQueue();  $this->config  = $config;}

The SplQueue used here is used to manage the connection and the command to be executed. You can compare it with the above and think about why one uses the SplStack and the other uses the SplQueue.

Proxy

Proxy is further encapsulated based on the connection pool. msf provides two encapsulation methods:

Master/slave master slave

Cluster

View the code in the sample App \ Controllers \ Redis:

Class Redis extends Controller {// Redis connection pool read/write example public function actionPoolSetGet () {yield $ this-> getRedisPool ('p1')-> set ('key1 ', 'val1'); $ val = yield $ this-> getRedisPool ('p1')-> get ('key1'); $ this-> outputJson ($ val );} // Redis proxy example (distributed) public function actionProxySetGet () {for ($ I = 0; $ I <= 100; $ I ++) {yield $ this-> getRedisProxy ('cluster')-> set ('proxy '. $ I, $ I) ;}$ val = yield $ this-> getRedisProxy ('cluster')-> get ('proxy22 '); $ this-> outputJson ($ val);} // example of using the Redis proxy (Master/Slave) public function actionMaserSlaveSetGet () {for ($ I = 0; $ I <= 100; $ I ++) {yield $ this-> getRedisProxy ('master _ slave ')-> set ('M '. $ I, $ I) ;}$ val = yield $ this-> getRedisProxy ('master _ slave ')-> get ('m66 '); $ this-> outputJson ($ val );}}

The proxy is further implemented based on the connection pool. The master-slave mode is used as an example:

Master-slave policy: Read the master database and write the slave Database
Proxy:

Determine whether to perform read or write operations, and select the appropriate database for execution.
Public Database

Msf implements the Public Library Practice and hopes that different functional components can be pluggable. This can be seen in the laravel framework and symfony framework, which are composed of packages added by the framework core. I highly recommend this kind of thinking. However, if you carefully read Baidu brain map-php-msf source code to interpret this figure, you will find the dependency between classes, tiering/boundary is not doing well. if you have read the source code of my previous blog-laravel or the source code of blog-yii, the comparison will be obvious.

However, this does not mean that the Code is not good. At least the Code with normal functions can be regarded as good code. in addition to functions, the sense of superiority is more about the yearning for a better life.

AOP

Php AOP Extension: http://pecl.php.net/package/aop

PHP-AOP extensions | rango: http://rango.swoole.com/archives/83

AOP, Aspect-Oriented Programming, Han boss's blog-PHP-AOP extension introduction | rango can look.

You do not need to understand a new thing. First, let's take a look at the role of this thing:

AOP: separates business code from business-independent code. scenarios include logging, Performance Statistics, security control, transaction processing, Exception Processing, and caching.
Here we reference the code in a programmer's DD-yong yongchao public account Article to let everyone feel:

Similarly, CRUD does not use AOP.

@ PostMapping ("/delete") public Map <String, Object> delete (long id, String lang) {Map <String, Object> data = new HashMap <String, object> (); boolean result = false; try {// language (different in Chinese and English) Locale local = "zh ". equalsIgnoreCase (lang )? Locale. CHINESE: Locale. ENGLISH; result = configService. delete (id, local); data. put ("code", 0);} catch (CheckException e) {// parameter verification error. This type of exception is a known exception and does not need to print the stack, the return code is-1 data. put ("code",-1); data. put ("msg", e. getMessage ();} catch (Exception e) {// other unknown exceptions, which must be used for Stack analysis. The return code is 99 log. error (e); data. put ("code", 99); data. put ("msg", e. toString ();} data. put ("result", result); return data ;}

Use AOP

@PostMapping("/delete")public ResultBean<Boolean> delete(long id) { return new ResultBean<Boolean>(configService.delete(id));}

The Code only uses one line and requires few features. Do you want to write such CRUD code?

Configuration File Management

First, clarify the pain points of Configuration Management:

Whether to support hot update, resident memory needs to be considered

Consider different environments: dev test production

Easy to use

Hot is actually the overall requirement of resident memory servers. Currently, common php solutions are inotify. refer to my previous blog-swoft source code.

Msf uses a third-party library to parse and process the configuration file. Here we will focus on the details of array_merge:

$ A = ['A' => ['a1' => 'a1',]; $ B = ['A' => ['b1 '=> 'b1',]; $ arr = array_merge ($ a, $ B); // note, array_merge () does not cyclically merge var_dump ($ arr); // The result array (1) {["a"] => array (1) {["b1"] => string (2) "b1 "}}

Msf Configuration:

$ Ids = $ this-> getConfig ()-> get ('params. mock_ids ', []); // compare laravel $ ids = cofnig ('params. mock_ids ', []);

It seems that laravel should be simpler. In fact, it uses composer autoload to load the function. This function encapsulates a layer of actual operations. As for whether to do this, it depends on your needs.

Conclusion

The most complex part of msf has a long inheritance in the service startup phase:

Child-> Server-> HttpServer-> MSFServer-> AppServer. If you are interested, you can challenge it.

Another difficulty is the implementation principle of MongoDbTask.

Msf also encapsulates many useful functions, such as RPC, message queue, and restful, which can be explored by yourself based on the document.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.