<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: stelin</title>
    <description>The latest articles on Forem by stelin (@stelin).</description>
    <link>https://forem.com/stelin</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F191757%2Fef19c76a-449e-4485-8c83-fc41069ce845.jpeg</url>
      <title>Forem: stelin</title>
      <link>https://forem.com/stelin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/stelin"/>
    <language>en</language>
    <item>
      <title>Best distributed task scheduling framework — Openjob 1.0.7 released</title>
      <dc:creator>stelin</dc:creator>
      <pubDate>Mon, 11 Sep 2023 09:07:39 +0000</pubDate>
      <link>https://forem.com/stelin/best-distributed-task-scheduling-framework-openjob-107-released-43b5</link>
      <guid>https://forem.com/stelin/best-distributed-task-scheduling-framework-openjob-107-released-43b5</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://github.com/open-job/openjob"&gt;Openjob&lt;/a&gt; is a new  distributed task scheduling framework based on Akka architecture. Supports multiple cronjob, delay task, workflow, lightweight distributed computing, unlimited horizontal scaling, with high scalability and fault tolerance. Also has complete management, powerful alarm monitoring, and support multiple languages&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;High reliability

&lt;ul&gt;
&lt;li&gt;Distributed with stateless design, using the Master/Worker architecture, supports multiple databases (MySQL/PostgreSQL/Oracle)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;High performance

&lt;ul&gt;
&lt;li&gt;System uses a consistency sharding algorithm, lock-free design, task scheduling is accurate down to the second, supporting lightweight distributed computing and unlimited horizontal scaling&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Cronjob

&lt;ul&gt;
&lt;li&gt;Supports distributed cronjob, fixed rate tasks, high-performance second tasks, and onetime tasks&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Distributed computing

&lt;ul&gt;
&lt;li&gt;Supports multiple distributed programming models such as standalone, broadcast, Map, MapReduce, and sharding, easy to complete distributed computing for big data&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Delay task

&lt;ul&gt;
&lt;li&gt;High performance delay task based on Redis , support multi-level storage, and provides rich statistics and reports&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Workflow

&lt;ul&gt;
&lt;li&gt;Supports workflow scheduling engine, visual DAG design, and easy to complete complex task scheduling&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Permission management

&lt;ul&gt;
&lt;li&gt;User management, supports menu, button, and data permission settings, flexible management of user permissions&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Alarm monitoring

&lt;ul&gt;
&lt;li&gt;Overall monitoring metrics, rich and alarm in time, easy to locate and resolve online problem&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Multiple languages

&lt;ul&gt;
&lt;li&gt;Support multiple languages such as Java, Go, PHP, and Python, as well as build with frameworks such as Spring Boot, Gin, and Swoft
If you are looking for a high-performance distributed task scheduling framework that supports cronjob, delay task, lightweight computing, workflow, and supports multiple programming languages, then &lt;a href="https://github.com/open-job/openjob"&gt;Openjob&lt;/a&gt; is definitely the way to go.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Released
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/open-job/openjob"&gt;Openjob&lt;/a&gt; 1.0.7 newly supports H2/TiDB database and adds second delay task, fixed rate task, broadcast task, sharding task, and Map Reduce lightweight computing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Second Delay
&lt;/h3&gt;

&lt;p&gt;Second delay support scheduling at interval of 1 to 60 seconds. After each task execution is completed, scheduling will be triggered again at second intervals.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;High reliability: Second delay have high reliability characteristics. If a machine goes down, it can be re-run on another machine.&lt;/li&gt;
&lt;li&gt;Rich task types: Second delay belong to the cron type and can be applied to all task types and execution types.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5qAkLe3e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9duia2trhdqgy5pud2no.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5qAkLe3e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9duia2trhdqgy5pud2no.png" alt="Image description" width="800" height="454"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Fixed Rate
&lt;/h3&gt;

&lt;p&gt;Crontab must be divisible by 60, if task executed every 50 minutes, Crontab cannot support it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lr9rCLeB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0w9qxb1z0nt3wf5kh0rj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lr9rCLeB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0w9qxb1z0nt3wf5kh0rj.png" alt="Image description" width="800" height="424"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Map Reduce
&lt;/h3&gt;

&lt;p&gt;MapReduce is a lightweight distributed batch task. Implemented by the MapProcessor or MapReduceProcessor. Compared with big data batch task (such as Hadoop, Spark, etc.), MapReduce does not need to import data into the big data platform, and has no additional storage and computing costs. It can realize second data processing and the advantages of low cost, fast speed and programming.&lt;/p&gt;

&lt;h5&gt;
  
  
  Example
&lt;/h5&gt;

&lt;p&gt;Define executor by annotation as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
 * @author stelin swoft@qq.com
 * @since 1.0.7
 */&lt;/span&gt;
&lt;span class="nd"&gt;@Component&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"mapReduceTestProcessor"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MapReduceTestProcessor&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;MapReduceProcessor&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;Logger&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LoggerFactory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getLogger&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"openjob"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;TWO_NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"TASK_TWO"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;THREE_NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"TASK_THREE"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;ProcessResult&lt;/span&gt; &lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JobContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isRoot&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MapChildTaskTest&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;tasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MapChildTaskTest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;

            &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Map Reduce root task mapList={}"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;TWO_NAME&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isTask&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;TWO_NAME&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;MapChildTaskTest&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;MapChildTaskTest&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getTask&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
            &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MapChildTaskTest&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;tasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;()*&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MapChildTaskTest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;

            &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Map Reduce task two mapList={}"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;THREE_NAME&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isTask&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;THREE_NAME&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;MapChildTaskTest&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;MapChildTaskTest&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getTask&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
            &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Map Reduce task three mapTask={}"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ProcessResult&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;valueOf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ProcessResult&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;ProcessResult&lt;/span&gt; &lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JobContext&lt;/span&gt; &lt;span class="n"&gt;jobContext&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;resultList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jobContext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getTaskResultList&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;TaskResult:&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;getResult&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;collect&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Collectors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toList&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Map Reduce resultList={}"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;resultList&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ProcessResult&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Data&lt;/span&gt;
    &lt;span class="nd"&gt;@AllArgsConstructor&lt;/span&gt;
    &lt;span class="nd"&gt;@NoArgsConstructor&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MapChildTaskTest&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Integer&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lVVRR1kc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n9qh54v3a1xuy382vxdm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lVVRR1kc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n9qh54v3a1xuy382vxdm.png" alt="Image description" width="800" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Sharding
&lt;/h3&gt;

&lt;p&gt;Sharding model includes static sharding and dynamic sharding:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Static sharding: The main scenario is to process a fixed number of sharding. For example, there are 256 databases in sub-databases, which requires many worker to be processed in a distributed.&lt;/li&gt;
&lt;li&gt;Dynamic sharding: The main scenario is distributed processing of unknown data. For example, a large table is constantly changing and requires distributed batch running.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Feature
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Compatible with elastic-job’s static sharding.&lt;/li&gt;
&lt;li&gt;Supports languages: Java, PHP, Python, Shell, and Go.&lt;/li&gt;
&lt;li&gt;High availability: When the worker that executes a sharding task becomes abnormal, it will be dynamically assigned to other normal worker to execute the task.&lt;/li&gt;
&lt;li&gt;Flow control: You can set the number of concurrent subtasks for a single worker. For example, if there are 100 sharding and a total of 3 worker, up to 5 sharding can be controlled to execute concurrently, and the others are waiting in the queue.&lt;/li&gt;
&lt;li&gt;Retry on failure: Automatically retry when subtask execution fails.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Example
&lt;/h5&gt;

&lt;p&gt;Define executor by annotation as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
 * @author stelin swoft@qq.com
 * @since 1.0.7
 */&lt;/span&gt;
&lt;span class="nd"&gt;@Component&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ShardingAnnotationProcessor&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;Logger&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LoggerFactory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getLogger&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"openjob"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="nd"&gt;@Openjob&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"annotationShardingProcessor"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;ProcessResult&lt;/span&gt; &lt;span class="nf"&gt;shardingProcessor&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JobContext&lt;/span&gt; &lt;span class="n"&gt;jobContext&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Sharding annotation processor execute success! shardingId={} shardingNum={} shardingParams={}"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;jobContext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getShardingId&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;jobContext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getShardingNum&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;jobContext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getShardingParam&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"jobContext={}"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;jobContext&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ProcessResult&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2ODNnw7L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yxk87jukr319qr5g88s5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2ODNnw7L--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yxk87jukr319qr5g88s5.png" alt="Image description" width="800" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Broadcast
&lt;/h3&gt;

&lt;p&gt;Broadcast task instance will be broadcast to all workers to the application for execution. Task will be completed when all workers have completed execution. If any worker execute fail, the task will fail.&lt;/p&gt;

&lt;h5&gt;
  
  
  Application scenarios&lt;a href="http://localhost:3000/docs/developer-guide/distributed-model/broadcast#application-scenarios%20%22Direct%20link%20to%20Application%20scenarios%22"&gt;​&lt;/a&gt;
&lt;/h5&gt;

&lt;p&gt;&lt;strong&gt;Batch operation&lt;/strong&gt;&lt;a href="http://localhost:3000/docs/developer-guide/distributed-model/broadcast#batch-operation%20%22Direct%20link%20to%20Batch%20operation%22"&gt;​&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Broadcast to all workers to run a script.&lt;/li&gt;
&lt;li&gt;Broadcast to all workers to cleaning data regularly.&lt;/li&gt;
&lt;li&gt;Dynamically start a service on each worker&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Data aggregation&lt;/strong&gt;&lt;a href="http://localhost:3000/docs/developer-guide/distributed-model/broadcast#data-aggregation%20%22Direct%20link%20to%20Data%20aggregation%22"&gt;​&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Initialize using JavaProcessor-&amp;gt;preProcess&lt;/li&gt;
&lt;li&gt;When each worker executes the process, it returns the result according to the business.&lt;/li&gt;
&lt;li&gt;Execute postProcess to obtain the execution results of all workers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Feature&lt;a href="http://localhost:3000/docs/developer-guide/distributed-model/broadcast#feature%20%22Direct%20link%20to%20Feature%22"&gt;​&lt;/a&gt;
&lt;/h5&gt;

&lt;p&gt;There are many types of broadcast tasks, such as script or Java Processor. If Java processor, it can supports preProcess and postProcess advanced features.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;preProcess will be executed before each worker execute process, and will only be executed once.&lt;/li&gt;
&lt;li&gt;process is the actual task execution.&lt;/li&gt;
&lt;li&gt;postProcess will be executed once after the process execution on each worker is completed and successfully executed, and the results can be returned as data transmission.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;Define executor by annotation as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
 * @author stelin swoft@qq.com
 * @since 1.0.7
 */&lt;/span&gt;
&lt;span class="nd"&gt;@Component&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"broadcastPostProcessor"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BroadcastProcessor&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;JavaProcessor&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;Logger&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LoggerFactory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getLogger&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"openjob"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;preProcess&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JobContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Broadcast pre process!"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;ProcessResult&lt;/span&gt; &lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JobContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Broadcast process!"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ProcessResult&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"{\"data\":\"result data\"}"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;ProcessResult&lt;/span&gt; &lt;span class="nf"&gt;postProcess&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;JobContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Broadcast post process taskList={}"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getTaskResultList&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getTaskResultList&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ProcessResult&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--boSn6OiQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c2le4w918znmp8237dyc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--boSn6OiQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c2le4w918znmp8237dyc.png" alt="Image description" width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  More
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Official website: &lt;a href="https://openjob.io/"&gt;https://openjob.io&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Github: &lt;a href="https://github.com/open-job/openjob"&gt;https://github.com/open-job/openjob&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Live demo: &lt;a href="https://demo.openjob.io/"&gt;https://demo.openjob.io&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;openjob&lt;/li&gt;
&lt;li&gt;openjob.io&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>java</category>
      <category>php</category>
      <category>programming</category>
    </item>
    <item>
      <title>Openjob: best distributed task scheduling framework</title>
      <dc:creator>stelin</dc:creator>
      <pubDate>Sun, 18 Jun 2023 14:28:00 +0000</pubDate>
      <link>https://forem.com/stelin/openjob-best-distributed-task-scheduling-framework-32mc</link>
      <guid>https://forem.com/stelin/openjob-best-distributed-task-scheduling-framework-32mc</guid>
      <description>&lt;h3&gt;
  
  
  What is Openjob?
&lt;/h3&gt;

&lt;p&gt;Openjob is a new  distributed task scheduling framework based on Akka. Supports a variety of cronjob, delayed jobs, and workflow. Uses a consistency sharding algorithm and supports unlimited horizontal scaling.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hE6M5WZr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/87v75yh2x5wr9ioa3fp0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hE6M5WZr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/87v75yh2x5wr9ioa3fp0.png" alt="dashboard" width="800" height="445"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Feature
&lt;/h3&gt;

&lt;p&gt;Openjob not only supports basic cronjob, but also provides delayed jobs, distributed computing, and workflow&lt;/p&gt;

&lt;h4&gt;
  
  
  Cronjob
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cronjob，&lt;/strong&gt;support Unix Crontab expression&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Second，&lt;/strong&gt;execution cycle less than 60 seconds&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fixed rate，&lt;/strong&gt;execute tasks at a fixed frequency with minute unit&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xLImQP1y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9aslskg77ncluvi0jqrv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xLImQP1y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9aslskg77ncluvi0jqrv.png" alt="cronjob" width="800" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  Delay Task
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Distributed, high-performance delay task  based on Redis, and providing rich reports and statistics&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Distributed Computing
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Standalone，&lt;/strong&gt; execute on a worker client&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Broadcast，&lt;/strong&gt; execute on all worker clients&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Map，&lt;/strong&gt;a map function can distribute big data to multiple machines for execution, like Hadoop map&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;MapReduce，&lt;/strong&gt; MapReduce is an extension of the Map.After all map sub-tasks are completed, the Reduce method is executed, which can process the results and data of the task execution in the Reduce method.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Sharding，&lt;/strong&gt; like Elastic-Job model, configure sharding numbers on the management, which can be scheduled to different client by sharding, and supports multiple languages.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1BApY4gf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jpajucksidhjdnwmimwb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1BApY4gf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jpajucksidhjdnwmimwb.png" alt="delay" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  Processor
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Processor&lt;/strong&gt;, execute by function or class(support Java/Golang/PH)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HTTP&lt;/strong&gt;, http request, used to periodically request an HTTP&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shell&lt;/strong&gt;,shell script&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Visual operations
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dashboard&lt;/strong&gt;，rich task statistics and reports&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Task history&lt;/strong&gt;，task execution history records&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Task log&lt;/strong&gt;，complete task log, and suppport storage (H2/Mysql/Elasticsearch).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Task running stack&lt;/strong&gt;，detailed recording of task execution stack information&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6bQiDlix--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lv6chhpot3nlsfkbd8u0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6bQiDlix--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lv6chhpot3nlsfkbd8u0.png" alt="log" width="800" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  Alarms and permissions
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Provides task event monitoring alarms,  detailed alarm histories, and support notifications with WeChat, Feishu, and webhook triggers. &lt;/li&gt;
&lt;li&gt;Designed with namespace, support button-level access  and easy to manage complex project.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Multiple languages
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Java&lt;/strong&gt; java and its frameworks, with native support.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Go&lt;/strong&gt; golang support use &lt;code&gt;go mod&lt;/code&gt; install&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PHP&lt;/strong&gt; PHP support use Golang agent to execute task by shell mode 。Swoole frameworks support composer install.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Python&lt;/strong&gt; python support use Golang agent to execute task by shell mode&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Use cases
&lt;/h3&gt;

&lt;p&gt;Openjob is well-suited for business scenarios that have task schedule and delay task. such as every day to clean data and report generation. It is also suitable for lightweight computing, and Map/MapReduce can process big data computing. For complex task flows or workflow, it can design workflow with UI&lt;/p&gt;

&lt;h2&gt;
  
  
  Open source
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Item&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Quartz&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Elastic-Job&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;XXL-JOB&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Openjob&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Cronjob&lt;/td&gt;
&lt;td&gt;Cron&lt;/td&gt;
&lt;td&gt;Cron&lt;/td&gt;
&lt;td&gt;Cron&lt;/td&gt;
&lt;td&gt;* Cronjob&lt;br&gt;* second&lt;br&gt;* Onetime&lt;br&gt;* Fixed rate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Delay task&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Distributed, high-performance delay task  based on Redis&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Workflow&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Workflow design with UI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Distributed Computing&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Sharding&lt;/td&gt;
&lt;td&gt;Sharding&lt;/td&gt;
&lt;td&gt;* Broadcast&lt;br&gt;* Map/MapReduce&lt;br&gt;* Sharding&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multiple languages&lt;/td&gt;
&lt;td&gt;Java&lt;/td&gt;
&lt;td&gt;* Java&lt;br&gt;* Shell&lt;/td&gt;
&lt;td&gt;* Java&lt;br&gt;* Shell&lt;/td&gt;
&lt;td&gt;* Java&lt;br&gt;* Go(Gin、beego)&lt;br&gt;* PHP(Swoft)&lt;br&gt;* Python(Agent)&lt;br&gt;* Shell&lt;br&gt;* HTTP&lt;br&gt;* Kettle&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Visualization&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Weak&lt;/td&gt;
&lt;td&gt;* Task history&lt;br&gt;* Task log（Not support storage）&lt;br&gt;* Dashboard&lt;/td&gt;
&lt;td&gt;* Task history&lt;br&gt;&lt;br&gt;* Task log（support H2/Mysql/Elasticsearch）&lt;br&gt;* Dashboard&lt;br&gt;* Full permissions&lt;br&gt;* Task log stack&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Manageable&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;enable、disable task&lt;/td&gt;
&lt;td&gt;* enable、disable task&lt;br&gt;* execute once&lt;br&gt;* stop&lt;/td&gt;
&lt;td&gt;* enable、disable task&lt;br&gt;* execute once&lt;br&gt;* kill&lt;br&gt;* stop&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Alarms&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;email&lt;/td&gt;
&lt;td&gt;email&lt;/td&gt;
&lt;td&gt;* custom event&lt;br&gt;* email&lt;br&gt;* webhook&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Performance&lt;/td&gt;
&lt;td&gt;Every task scheduling try to acquire a lock through the database, causes a high pressure on the database&lt;/td&gt;
&lt;td&gt;ZooKeeper  is performance bottleneck&lt;/td&gt;
&lt;td&gt;Task scheduling is only by master, causes a high pressure on master&lt;/td&gt;
&lt;td&gt;Uses sharding algorithm, each node can be scheduled without lock, supports unlimited horizontal scaling, and supports big task scheduling&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  More
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Official website: &lt;a href="https://openjob.io/"&gt;https://openjob.io&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Github: &lt;a href="https://github.com/open-job/openjob"&gt;https://github.com/open-job/openjob&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Live demo: &lt;a href="https://demo.openjob.io/"&gt;https://demo.openjob.io&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>java</category>
      <category>php</category>
      <category>go</category>
      <category>python</category>
    </item>
    <item>
      <title>PHP microservices framework — Swoft 2.0.5 published</title>
      <dc:creator>stelin</dc:creator>
      <pubDate>Thu, 08 Aug 2019 13:16:28 +0000</pubDate>
      <link>https://forem.com/stelin/php-microservices-framework-swoft-2-0-5-published-83k</link>
      <guid>https://forem.com/stelin/php-microservices-framework-swoft-2-0-5-published-83k</guid>
      <description>&lt;h2&gt;
  
  
  What is Swoft?
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Efficient seconds crontab
&lt;/h2&gt;

&lt;p&gt;The following simple lines of code define a timed task that is executed every second, which can completely replace the system crontab.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;?php declare(strict_types=1);

namespace App\Crontab;

use Swoft\Crontab\Annotaion\Mapping\Cron;
use Swoft\Crontab\Annotaion\Mapping\Scheduled;

/**
 * Class CronTask
 *
 * @since 2.0
 *
 * @Scheduled()
 */
class CronTask
{
    /**
     * @Cron("* * * * * *")
     */
    public function secondTask()
    {
        printf("second task run: %s ", date('Y-m-d H:i:s', time()));
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The crontab starts with the service and will see the following display:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhabrastorage.org%2Fwebt%2Fta%2Fag%2F1h%2Ftaag1h3rpqrxtv8nqgkhvt0q6ti.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhabrastorage.org%2Fwebt%2Fta%2Fag%2F1h%2Ftaag1h3rpqrxtv8nqgkhvt0q6ti.jpeg" alt="-w1249"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Exception management
&lt;/h2&gt;

&lt;p&gt;During the development process, if the error message is a string of characters, it is not convenient for the business to solve the problem. If the component is used, all error messages will be displayed as follows:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhabrastorage.org%2Fwebt%2Frs%2F6c%2Fqy%2Frs6cqyiok1gkruxsvajjamjqxvm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fhabrastorage.org%2Fwebt%2Frs%2F6c%2Fqy%2Frs6cqyiok1gkruxsvajjamjqxvm.png" alt="whoops"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Update
&lt;/h2&gt;

&lt;p&gt;Fixed：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fixing early interrupt request logic may result in incorrect formatting of the corresponding Content-Type &lt;a href="https://github.com/swoft-cloud/swoft-component/pull/493/commits/f03139886a471a0424d236061e8cb30d90b32a89" rel="noopener noreferrer"&gt;f031398&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Fixed the use of sgo to create child coroutines, at the end did not clean up the mapping with the top coroutine &lt;a href="https://github.com/swoft-cloud/swoft-component/pull/493/commits/de11ae5bc63833b80ca491132d156d51b95f6c8d" rel="noopener noreferrer"&gt;de11ae5b&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Fix Xml format parsing method &lt;a href="https://github.com/swoft-cloud/swoft-component/pull/495/commits/24d0038dc644fccf238d9642f049ceb961dd22b3" rel="noopener noreferrer"&gt;24d0038&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Fix class proxy Unique string problem &lt;a href="https://github.com/swoft-cloud/swoft-component/pull/495/commits/444ddeb51e0741dda06e8f548f2579cf534bdf30" rel="noopener noreferrer"&gt;444ddeb&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Fixed &lt;code&gt;context()-&amp;gt;get()&lt;/code&gt; problem and discard &lt;code&gt;Context::mustGet()&lt;/code&gt; method &lt;a href="https://github.com/swoft-cloud/swoft-component/pull/496/commits/6acc1b55163a18edc95de6cdb899398a9a7d0f2e" rel="noopener noreferrer"&gt;6acc1b5&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Fixed interface injection, class name access error &lt;a href="https://github.com/swoft-cloud/swoft-component/pull/496/commits/2d9a31fe1855054055daa6e6e73aeaddfa280900" rel="noopener noreferrer"&gt;2d9a31f&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Repair model uses the &lt;code&gt;paginate&lt;/code&gt; method, the result set has no mapping field &lt;a href="https://github.com/swoft-cloud/swoft-component/commit/3027287a58bfa66b3c87b8d2d03fddbfc6c2c754" rel="noopener noreferrer"&gt;3027287&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Fixed websocket server error when there are multiple workers and actively closes non-current worker connections &lt;a href="https://github.com/swoft-cloud/swoft-component/pull/500/commits/7666969f731dce68d395f45749260731eead7bda" rel="noopener noreferrer"&gt;7666969&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Update:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The default worker num setting is obtained by the &lt;code&gt;swoole_cpu_num&lt;/code&gt; function &lt;a href="https://github.com/swoft-cloud/swoft-component/pull/493/commits/553f6500678b258080b84cffeab0fe2d5bf65550" rel="noopener noreferrer"&gt;553f6500&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;The validator is adjusted to, the default is not required, the user opens &lt;a href="https://github.com/swoft-cloud/swoft-component/pull/496/commits/e5b258db35683e50f4abeba22a2c6fa82dbc7ceb" rel="noopener noreferrer"&gt;e5b258d&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;No longer throws &lt;code&gt;containerException&lt;/code&gt; inside the swowt to the user-used layer &lt;a href="https://github.com/swoft-cloud/swoft-component/pull/498/commits/1e74893bf6e05fe954334e527e8b76eca2cef6e9" rel="noopener noreferrer"&gt;1e74893&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;console output Add interactive methods such as &lt;code&gt;confirm&lt;/code&gt; &lt;code&gt;select&lt;/code&gt; &lt;a href="https://github.com/swoft-cloud/swoft-component/pull/498/commits/0181138af6f1bc1dc0f3f1025b23d9a6354d122a" rel="noopener noreferrer"&gt;0181138a&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Enhancement：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The console command option sets &lt;code&gt;CommandOption&lt;/code&gt;, which now allows options to be described as multiple lines of information &lt;a href="https://github.com/swoft-cloud/swoft-component/pull/493/commits/e591498363dac1888f503ab18766e89542e33665" rel="noopener noreferrer"&gt;e5914983&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;All messaging methods for websocket server, support for incoming &lt;code&gt;opcode&lt;/code&gt; parameter &lt;a href="https://github.com/swoft-cloud/swoft-component/pull/493/commits/dc164ffe97d507e505ac8cd1b50a421a27ae5859" rel="noopener noreferrer"&gt;dc164ffe9&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;The websocket module allows setting the default &lt;code&gt;opcode&lt;/code&gt; of the current module for automatic processing of return data settings &lt;code&gt;opcode&lt;/code&gt; &lt;a href="https://github.com/swoft-cloud/swoft-component/pull/493/commits/9e3e9672ed83579e6135ed47ae0c30ef335d8659" rel="noopener noreferrer"&gt;9e3e9672&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Enhanced websocket related classes, now the message processing method allows to inject more data object types &lt;code&gt;Request&lt;/code&gt; &lt;code&gt;Response&lt;/code&gt; &lt;a href="https://github.com/swoft-cloud/swoft-component/pull/493/commits/3d6c60b4812535c48d51c57476f801529f66655f" rel="noopener noreferrer"&gt;3d6c60b4&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;When the worker exits, the websocket server will automatically close all connections &lt;a href="https://github.com/swoft-cloud/swoft-component/pull/498/commits/5ea10ecc4bcf767b374dad9652dd57a4fcfc8fc5" rel="noopener noreferrer"&gt;5ea10ecc&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Add Timer timer package &lt;a href="https://github.com/swoft-cloud/swoft-component/pull/495/commits/eb92ee6a7d5e7f2a47e30920a83ed192626b42e3" rel="noopener noreferrer"&gt;eb92ee6&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Add Coroutine Method Package &lt;a href="https://github.com/swoft-cloud/swoft-component/pull/495/commits/d8c2b8848d492fc4b389df6edee595ef8f0e39c5" rel="noopener noreferrer"&gt;d8c2b88&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Resource
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/swoft-cloud/swoft" rel="noopener noreferrer"&gt;https://github.com/swoft-cloud/swoft&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>php</category>
    </item>
    <item>
      <title>How to use PHP to implement microservices?</title>
      <dc:creator>stelin</dc:creator>
      <pubDate>Mon, 22 Jul 2019 03:53:06 +0000</pubDate>
      <link>https://forem.com/stelin/how-to-use-php-to-implement-microservices-4kjm</link>
      <guid>https://forem.com/stelin/how-to-use-php-to-implement-microservices-4kjm</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fswoft-cloud%2Fblog%2Fmaster%2Fimage%2Fmico.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fswoft-cloud%2Fblog%2Fmaster%2Fimage%2Fmico.jpg" alt="Swoft"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  How to use PHP to implement microservices?
&lt;/h1&gt;

&lt;h3&gt;
  
  
  Why do you say service governance?
&lt;/h3&gt;

&lt;p&gt;   With the increasing popularity of Internet browsing, the traditional MVC single architecture has become more and more bloated and more difficult to maintain as the scale of applications continues to expand.&lt;br&gt;
   &lt;br&gt;
   We must take measures to split the application, which is to split the original application into multiple applications according to business characteristics. For example, a large e-commerce system may include user systems, commodity systems, order systems, evaluation systems, etc., and we can separate them into separate applications. The multi-application architecture is characterized by independent applications and not calling each other.&lt;br&gt;
  &lt;br&gt;
  Although multiple applications solve the bloated application problem, the applications are independent of each other, and some common services or codes cannot be reused.&lt;br&gt;
  &lt;/p&gt;
&lt;h3&gt;
  
  
  Single application solution
&lt;/h3&gt;

&lt;p&gt;   For a large Internet system, there are usually multiple applications, and there are often common services between applications, and there are call relationships between applications. In addition, there are other challenges for large-scale Internet systems, such as how to deal with rapidly growing users, how to manage R&amp;amp;D teams to quickly iterate product development, how to keep product upgrades more stable, and so on.&lt;br&gt;
 &lt;br&gt;
   Therefore, in order to make the service be well reused, the module is easier to expand and maintain. We want the service to be separated from the application. A service is no longer an application, but is maintained as a separate service. The application itself is no longer a bloated module stack, but a modular service component.&lt;/p&gt;
&lt;h2&gt;
  
  
  Service
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Features
&lt;/h3&gt;

&lt;p&gt;So what is the feature of using "services"?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Application split into services by business&lt;/li&gt;
&lt;li&gt;Individual services can be deployed independently&lt;/li&gt;
&lt;li&gt;Service can be shared by multiple apps&lt;/li&gt;
&lt;li&gt;Communication between services&lt;/li&gt;
&lt;li&gt;The system is more clear on the architecture&lt;/li&gt;
&lt;li&gt;Core modules are stable and upgraded in units of service components, avoiding the risk of frequent releases&lt;/li&gt;
&lt;li&gt;Easy development and management&lt;/li&gt;
&lt;li&gt;Individual team maintenance, clear work, clear responsibilities&lt;/li&gt;
&lt;li&gt;Service reuse, code reuse&lt;/li&gt;
&lt;li&gt;Very easy to expand&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  The challenge of service
&lt;/h3&gt;

&lt;p&gt;After the system is serviced, the dependency is complicated, and the number of interactions between the service and the service is increased. In the development mode of &lt;code&gt;fpm&lt;/code&gt;, because the resident memory cannot be brought to us, every request must be from zero. Starting to load to the exit process, adding a lot of useless overhead, the database connection can not be reused and can not be protected, because &lt;code&gt;fpm&lt;/code&gt; is the process-based &lt;code&gt;fpm&lt;/code&gt; process number also determines the number of concurrent, this is also Fpm development is simple to bring us problems. So why is the Internet platform &lt;code&gt;Java&lt;/code&gt; more popular now, &lt;code&gt;.NET&lt;/code&gt; and &lt;code&gt;PHP&lt;/code&gt; will not work in this regard. Needless to say &lt;code&gt;PHP non-memory resident&lt;/code&gt;. In addition, there are many other issues that need to be addressed.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More and more services, complex configuration management&lt;/li&gt;
&lt;li&gt;Complex service dependencies&lt;/li&gt;
&lt;li&gt;Load balancing between services&lt;/li&gt;
&lt;li&gt;Service expansion&lt;/li&gt;
&lt;li&gt;Service monitoring&lt;/li&gt;
&lt;li&gt;Service downgrade&lt;/li&gt;
&lt;li&gt;Service authentication&lt;/li&gt;
&lt;li&gt;Service online and offline&lt;/li&gt;
&lt;li&gt;Service documentation
......&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can imagine the benefits that resident memory brings to us.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;only start frame initialization&lt;/strong&gt; If resident memory we just initialize the memory in the memory at startup, concentrate on processing the request&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Connection multiplexing&lt;/strong&gt;, some engineers can not specifically understand, if you do not need to connect to the pool, how about making a connection to a request? This will result in too many backend resource connections. For some basic services, such as Redis, databases, connections are an expensive drain.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So is there a good plan? The answer is yes, and many people are using this framework, it is - &lt;code&gt;Swoft&lt;/code&gt;. &lt;code&gt;Swoft&lt;/code&gt; is a &lt;a href="https://en.swoft.org/docs/2.x/zh-CN/rpc-server/index.html" rel="noopener noreferrer"&gt;RPC&lt;/a&gt; framework with the &lt;code&gt;Service Governance&lt;/code&gt; feature. &lt;code&gt;Swoft&lt;/code&gt; is the first PHP resident memory coroutine full stack framework, based on the core concept of the &lt;code&gt;Spring Boot&lt;/code&gt; convention is greater than the configuration&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Swoft&lt;/code&gt; provides a more elegant way to use &lt;code&gt;RPC&lt;/code&gt; services like &lt;code&gt;Dubbo&lt;/code&gt;, &lt;code&gt;Swoft&lt;/code&gt; performance is great with similar &lt;code&gt;Golang&lt;/code&gt; performance, here is my &lt;code&gt;PC&lt;/code&gt; vs. &lt;code&gt;Swoft&lt;/code&gt; performance. Happening.&lt;br&gt;
 &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fswoft-cloud%2Fblog%2Fmaster%2Fimage%2FabTesting.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fswoft-cloud%2Fblog%2Fmaster%2Fimage%2FabTesting.png" alt="Swoft"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ab&lt;/code&gt; stress test processing speed is very amazing, in the &lt;code&gt;i78 generation&lt;/code&gt; CPU, &lt;code&gt;16GB&lt;/code&gt; memory &lt;code&gt;100000&lt;/code&gt; million requests only use &lt;code&gt;5s&lt;/code&gt; time in the &lt;code&gt;fpm&lt;/code&gt; development mode is basically impossible to achieve. Sufficient to demonstrate the high performance and stability of &lt;code&gt;Swoft&lt;/code&gt;,&lt;/p&gt;
&lt;h2&gt;
  
  
  Elegant service governance
&lt;/h2&gt;
&lt;h3&gt;
  
  
  &lt;a href="https://en.swoft.org/docs/2.x/en/ms/govern/register-discovery.html" rel="noopener noreferrer"&gt;Service Registration and Discovery&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;In the microservices governance process, registration of services initiated to third-party clusters, such as consul / etcd, is often involved. This chapter uses the swoft-consul component in the Swoft framework to implement service registration and discovery.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fswoft-cloud%2Fblog%2Fmaster%2Fimage%2FregisterProvider.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fswoft-cloud%2Fblog%2Fmaster%2Fimage%2FregisterProvider.png" alt="Swoft"&gt;&lt;/a&gt;&lt;br&gt;
Implementation logic&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt; &lt;span class="k"&gt;declare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strict_types&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Common&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;ReflectionException&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Swoft\Bean\Annotation\Mapping\Bean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Swoft\Bean\Annotation\Mapping\Inject&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Swoft\Bean\Exception\ContainerException&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Swoft\Consul\Agent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Swoft\Consul\Exception\ClientException&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Swoft\Consul\Exception\ServerException&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Swoft\Rpc\Client\Client&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Swoft\Rpc\Client\Contract\ProviderInterface&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cd"&gt;/**
 * Class RpcProvider
 *
 * @since 2.0
 *        
 * @Bean()
 */&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RpcProvider&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;ProviderInterface&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * @Inject()
     *
     * @var Agent
     */&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$agent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * @param Client $client
     *
     * @return array
     * @throws ReflectionException
     * @throws ContainerException
     * @throws ClientException
     * @throws ServerException
     * @example
     * [
     *     'host:port',
     *     'host:port',
     *     'host:port',
     * ]
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Client&lt;/span&gt; &lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;array&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Get health service from consul&lt;/span&gt;
        &lt;span class="nv"&gt;$services&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;services&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="nv"&gt;$services&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;

        &lt;span class="p"&gt;];&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$services&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;a href="https://en.swoft.org/docs/2.x/en/ms/govern/breaker.html" rel="noopener noreferrer"&gt;Service Blow&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;In a distributed environment, especially a distributed system of microservice architectures, it is very common for one software system to call another remote system. The callee of such a remote call may be another process, or another host across the network. The biggest difference between this remote call and the internal call of the process is that the remote call may fail or hang. No response until timeout. Worse, if there are multiple callers calling the same suspended service, it is very likely that a service's timeout waits quickly spread to the entire distributed system, causing a chain reaction that consumes the entire A large amount of resources in distributed systems. Eventually it can lead to system paralysis.&lt;/p&gt;

&lt;p&gt;The Circuit Breaker mode is designed to prevent disasters caused by such waterfall-like chain reactions in distributed systems.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fswoft-cloud%2Fswoft-doc%2F2.x%2Fzh-CN%2Fms%2Fgovern%2F..%2F..%2Fimage%2Fms%2Fbreaker_ext.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fswoft-cloud%2Fswoft-doc%2F2.x%2Fzh-CN%2Fms%2Fgovern%2F..%2F..%2Fimage%2Fms%2Fbreaker_ext.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the basic circuit breaker mode, the protection supplier is not called when the circuit breaker is in the open state, but we also need additional measures to reset the circuit breaker after the supplier resumes service. One possible solution is that the circuit breaker periodically detects whether the service of the supplier is restored. Once restored, the status is set to close. The state when the circuit breaker is retried is a half-open state.&lt;/p&gt;

&lt;p&gt;The use of the fuse is simple and powerful. It can be annotated with a &lt;code&gt;@Breaker&lt;/code&gt;. The fuse of the &lt;code&gt;Swoft&lt;/code&gt; can be used in any scenario, such as when the service is called. It can be blown when requesting a third party. Downgrade&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt; &lt;span class="k"&gt;declare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strict_types&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Model\Logic&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Swoft\Bean\Annotation\Mapping\Bean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Swoft\Breaker\Annotation\Mapping\Breaker&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cd"&gt;/**
 * Class BreakerLogic
 *
 * @since 2.0
 *
 * @Bean()
 */&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BreakerLogic&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * @Breaker(fallback="loopFallback")
     *
     * @return string
     * @throws Exception
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Do something&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Breaker exception'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * @return string
     * @throws Exception
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;loopFallback&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Do something&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;a href="https://en.swoft.org/docs/2.x/en/ms/govern/limiter.html" rel="noopener noreferrer"&gt;Service Restriction&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Restriction, Fuse, Degradation&lt;/strong&gt; This emphasis cannot be overstated because it is really important. When the service is not working, it must be blown. Current limiting is a tool to protect itself. If there is no self-protection mechanism, no matter how many connections are received, if the back-end processing is not enough, the front-end traffic will definitely hang when it is very large.&lt;/p&gt;

&lt;p&gt;The current limit is to limit the number of concurrent and requested when accessing scarce resources, such as spikes and snapped goods, so as to effectively cut the peak and smooth the flow curve. The purpose of current limiting is to limit the rate of concurrent access and concurrent requests, or to request a speed limit within a time window to protect the system. Once the rate limit is reached or exceeded, the service can be denied, or queued.&lt;/p&gt;

&lt;p&gt;The bottom layer of the &lt;code&gt;Swoft&lt;/code&gt; current limiter uses the token bucket algorithm, and the underlying layer relies on &lt;code&gt;Redis&lt;/code&gt; to implement distributed current limiting.&lt;/p&gt;

&lt;p&gt;The Swoft speed limiter not only limits the flow controller, it also limits the methods in any bean and controls the access rate of the method. Here is a detailed explanation of the following examples.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt; &lt;span class="k"&gt;declare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strict_types&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Model\Logic&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Swoft\Bean\Annotation\Mapping\Bean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Swoft\Limiter\Annotation\Mapping\RateLimiter&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cd"&gt;/**
 * Class LimiterLogic
 *
 * @since 2.0
 *
 * @Bean()
 */&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LimiterLogic&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * @RequestMapping()
     * @RateLimiter(rate=20, fallback="limiterFallback")
     *
     * @param Request $request
     *
     * @return array
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;requestLimiter2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Request&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;array&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getUriPath&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'requestLimiter2'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * @param Request $request
     *
     * @return array
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;limiterFallback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Request&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;array&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getUriPath&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'limiterFallback'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Key This supports the &lt;code&gt;symfony/expression-language&lt;/code&gt; expression. If the speed limit is called, the &lt;code&gt;limiterFallback&lt;/code&gt; method defined in &lt;code&gt;fallback&lt;/code&gt; will be called.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://en.swoft.org/docs/2.x/en/ms/govern/config.html" rel="noopener noreferrer"&gt;Configuration Center&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Before we talk about the configuration center, let's talk about the configuration file. We are no stranger to it. It provides us with the ability to dynamically modify the program. A quote from someone else is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Dynamic adjustment of the flight attitude of the system runtime!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I can call our work to repair parts on fast-flying airplanes. We humans are always unable to control and predict everything. For our system, we always need to reserve some control lines to make adjustments when we need them, to control the system direction (such as gray control, current limit adjustment), which is especially important for the Internet industry that embraces change.&lt;/p&gt;

&lt;p&gt;For the stand-alone version, we call it the configuration (file); for the distributed cluster system, we call it the configuration center (system);&lt;/p&gt;

&lt;h4&gt;
  
  
  What exactly is a distributed configuration center?
&lt;/h4&gt;

&lt;p&gt;With the development of the business and the upgrade of the micro-service architecture, the number of services and the configuration of programs are increasing (various micro-services, various server addresses, various parameters), and the traditional configuration file method and database method cannot meet the development. Personnel requirements for configuration management:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Security: The configuration follows the source code stored in the code base, which is easy to cause configuration leaks;&lt;/li&gt;
&lt;li&gt;Timeliness: Modify the configuration and restart the service to take effect.&lt;/li&gt;
&lt;li&gt;Limitations: Dynamic adjustments cannot be supported: for example, log switches, function switches;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Therefore, we need to configure the center to manage the configuration! Freeing business developers from complex and cumbersome configurations, they only need to focus on the business code itself, which can significantly improve development and operational efficiency. At the same time, the configuration and release of the package will further enhance the success rate of the release, and provide strong support for the fine control and emergency handling of operation and maintenance.&lt;/p&gt;

&lt;p&gt; About distributed configuration centers, there are many open source solutions on the web, such as:&lt;/p&gt;

&lt;p&gt;Apollo is a distributed configuration center developed by Ctrip's framework department. It can centrally manage the configuration of different environments and different clusters of applications. It can be pushed to the application end in real time after configuration modification. It has the features of standardized authority and process management, and is suitable for microservices. Configure management scenarios.&lt;/p&gt;

&lt;p&gt;This chapter uses &lt;code&gt;Apollo&lt;/code&gt; as an example to pull configuration and secure restart services from the remote configuration center. If you are unfamiliar with &lt;code&gt;Apollo&lt;/code&gt;, you can first look at the &lt;code&gt;Swoft&lt;/code&gt; extension &lt;a href="https://en.swoft.org/docs/2.x/en/extra/apollo.html" rel="noopener noreferrer"&gt;&lt;code&gt;Apollo&lt;/code&gt;&lt;/a&gt; component and read &lt;code&gt;Apollo&lt;/code&gt; Official documentation.&lt;/p&gt;

&lt;p&gt;This chapter uses &lt;code&gt;Apollo&lt;/code&gt; in &lt;code&gt;Swoft&lt;/code&gt; as an example. When the &lt;code&gt;Apollo&lt;/code&gt; configuration changes, restart the service (http-server / rpc-server/ ws-server). The following is an example of an agent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt; &lt;span class="k"&gt;declare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strict_types&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Model\Logic&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Swoft\Apollo\Config&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Swoft\Apollo\Exception\ApolloException&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Swoft\Bean\Annotation\Mapping\Bean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Swoft\Bean\Annotation\Mapping\Inject&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="cd"&gt;/**
 * Class ApolloLogic
 *
 * @since 2.0
 *
 * @Bean()
 */&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ApolloLogic&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * @Inject()
     *
     * @var Config
     */&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$config&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * @throws ApolloException
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;pull&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;pull&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'application'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Print data&lt;/span&gt;
        &lt;span class="nb"&gt;var_dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above is a simple Apollo configuration pull, in addition to this method, &lt;a href="https://en.swoft.org/docs/2.x/en/extra/apollo.html" rel="noopener noreferrer"&gt;&lt;code&gt;Swoft-Apollo&lt;/code&gt;&lt;/a&gt; provides more ways to use.&lt;/p&gt;

&lt;h2&gt;
  
  
  Official link
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/swoft-cloud/swoft" rel="noopener noreferrer"&gt;Github&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.swoft.org/docs" rel="noopener noreferrer"&gt;Document&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gitter.im/swoft-cloud/community" rel="noopener noreferrer"&gt;Swoft-cloud/community&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>php</category>
    </item>
    <item>
      <title>Swoft 2.0.3 major update, launching elegant microservices governance</title>
      <dc:creator>stelin</dc:creator>
      <pubDate>Tue, 09 Jul 2019 03:56:28 +0000</pubDate>
      <link>https://forem.com/stelin/swoft-2-0-3-major-update-launching-elegant-microservices-governance-3hfk</link>
      <guid>https://forem.com/stelin/swoft-2-0-3-major-update-launching-elegant-microservices-governance-3hfk</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mrzIAZ7m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/bw76hz9cgelzhsk96hh5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mrzIAZ7m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/bw76hz9cgelzhsk96hh5.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Swoft?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/swoft-cloud/swoft"&gt;Swoft&lt;/a&gt; is a PHP microservices coroutine framework based on the &lt;a href="https://github.com/swoole/swoole-src"&gt;Swoole&lt;/a&gt; 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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Update
&lt;/h2&gt;

&lt;p&gt;Remove&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Remove &lt;code&gt;request-&amp;gt;json()&lt;/code&gt; method(&lt;a href="https://github.com/swoft-cloud/swoft-component/pull/455/commits/c9e8f048217670fd975e70d4eee1d8d3b2fccd7e"&gt;c9e8f04&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Enhancement&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add interface dependency injection(&lt;a href="https://github.com/swoft-cloud/swoft-component/pull/442/commits/6169f84ffd32622c4d3bb21f6ab3c69ef04746e2"&gt;6169f84&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;getFile&lt;/code&gt; to obtain information after file upload and save(&lt;a href="https://github.com/swoft-cloud/swoft-component/commit/fe7e3a69f215a92af83c5837d32b72a5c181383a"&gt;fe7e3a6&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;restart()&lt;/code&gt; to restart service(&lt;a href="https://github.com/swoft-cloud/swoft-component/pull/453/commits/2ffec37568618cc49c038f96a901cbb339769623"&gt;2ffec37&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Add call 1.x RPC service support(&lt;a href="https://github.com/swoft-cloud/swoft-component/pull/455/commits/30d73c3bcef6294d5985ce5af316e7aa6e86c0e5"&gt;30d73c3&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Add AOP class name matching supports regular expressions(&lt;a href="https://github.com/swoft-cloud/swoft-component/pull/455/commits/bc5e47951d1426e6944b934e6c8eb5db5657f8a4"&gt;bc5e479&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Add RPC Server /Http server Middleware namespace &lt;code&gt;use&lt;/code&gt; error prompt(&lt;a href="https://github.com/swoft-cloud/swoft-component/pull/455/commits/b1cec041ea402fe1c837d6755eff6efbfcef3681"&gt;b1cec04&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Add validator exclusion attribute field with&lt;code&gt;unfields&lt;/code&gt;(&lt;a href="https://github.com/swoft-cloud/swoft-component/pull/459/commits/b1bf44f62ae096674f2c413e9630964782b14d3f"&gt;b1bf44f&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Add auto write timestamp(&lt;a href="https://github.com/swoft-cloud/swoft-component/pull/457/commits/dc58011cfa90996e6e319365fc738c1cd386f08d"&gt;dc58011&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Add model action event(&lt;a href="https://github.com/swoft-cloud/swoft-component/pull/457/commits/dc58011cfa90996e6e319365fc738c1cd386f08d"&gt;dc58011&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Add database migration script(&lt;a href="https://github.com/swoft-cloud/swoft-ext/commit/26bb464ba61e43b6bbae9ba191a8e69525ad7dc5"&gt;26bb464&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Add entity automatically interact with json and arrays(&lt;a href="https://github.com/swoft-cloud/swoft-component/pull/457/commits/dc58011cfa90996e6e319365fc738c1cd386f08d"&gt;dc58011&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Add model batch update method with&lt;code&gt;batchUpdateByIds&lt;/code&gt;(&lt;a href="https://github.com/swoft-cloud/swoft-component/pull/457/commits/dc58011cfa90996e6e319365fc738c1cd386f08d"&gt;dc58011&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fixed：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fix cookies some problems when setting up, add some related methods with withCookie(&lt;a href="https://github.com/swoft-cloud/swoft-component/pull/443/commits/b05afbb011457d217bb3a40c6a3639c28b0eef18"&gt;b05afbb01&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Fix no capture processing error when the console uses the coroutine mode to run the command.(&lt;a href="https://github.com/swoft-cloud/swoft-component/pull/443/commits/8a5418bf25a4d4797d99281bf7db8881b7ca43ed"&gt;8a5418bf&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Fix restart websocket server command does not stop the old server problem first(&lt;a href="https://github.com/swoft-cloud/swoft-component/pull/443/commits/db2d935542c715bbe1ed4b3ed822b2d946317b6f"&gt;db2d935&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Fix task return value is &lt;code&gt;null&lt;/code&gt;(&lt;a href="https://github.com/swoft-cloud/swoft-component/pull/455/commits/a69347c8ce486102e23bb82d70cfef63573a94eb"&gt;a69347c&lt;/a&gt;) &lt;/li&gt;
&lt;li&gt;Fix RPC Server only class middleware can't be used(&lt;a href="https://github.com/swoft-cloud/swoft-component/pull/455/commits/204bc7f4f23a26f75534ac808e2f9eb05a0118a2"&gt;204bc7f&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Fix RPC Server return value is &lt;code&gt;null&lt;/code&gt;(&lt;a href="https://github.com/swoft-cloud/swoft-component/pull/455/commits/4d091bef0ece773bcd382a750de01eef830f2949"&gt;4d091be&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Fix Logger and CLog log level cannot be overwritten and invalid(&lt;a href="https://github.com/swoft-cloud/swoft-component/pull/459/commits/8eb8aba2313a45191318b52a3698135d92cb3e71"&gt;8eb8aba&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Fix attributes in the model do not support custom expressions(&lt;a href="https://github.com/swoft-cloud/swoft-component/pull/457/commits/dc58011cfa90996e6e319365fc738c1cd386f08d"&gt;dc58011&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Update:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Validator optimization, support for custom validation rules(&lt;a href="https://github.com/swoft-cloud/swoft-component/pull/442/commits/d959a4f5facfc24070fbde547f0557213e5184ee"&gt;d959a4f&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Rename the error handling management class &lt;code&gt;ErrorHanlders&lt;/code&gt; to &lt;code&gt;ErrorManager&lt;/code&gt; (&lt;a href="https://github.com/swoft-cloud/swoft-component/pull/443/commits/f3a8f04ba6d83874b772a419fe29e5449b3dcea9"&gt;f3a8f04b&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;The exception handling of the console component is changed to the unified processing style provided by the error component. (&lt;a href="https://github.com/swoft-cloud/swoft-component/pull/443/commits/4f472045e3d80165145907331386f46a2912b2e3"&gt;4f47204&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Console component allows to set the disable command group(&lt;a href="https://github.com/swoft-cloud/swoft-component/pull/454/commits/c5a0269f26ae6b9739401393a48fd3fd91280bbb"&gt;c5a0269&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;In the default error handling, the error capture level is allowed to be set. The default level is &lt;code&gt;E_ALL | E_STRICT&lt;/code&gt; (&lt;a href="https://github.com/swoft-cloud/swoft-component/pull/443/commits/afff90296d80085acd30b951441774049d0ca2e7"&gt;afff9029&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Optimization When the ws server is started, the http processing function is enabled at the same time, and the information panel adds prompts.(&lt;a href="https://github.com/swoft-cloud/swoft-component/pull/456/commits/83a8117047036da5687fa6dc5236301716dfd59f"&gt;83a81170&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Optimize Start the ws server and add the rpc server to start. The information panel does not display the rpc server information.(&lt;a href="https://github.com/swoft-cloud/swoft-component/pull/454/commits/3d1d0d848a8f5ca31a09feb5ee860079f7c018e4"&gt;3d1d0d848&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Extra:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Document add support search by google&lt;/li&gt;
&lt;li&gt;New apollo Component&lt;/li&gt;
&lt;li&gt;New consul Component&lt;/li&gt;
&lt;li&gt;New breaker Component&lt;/li&gt;
&lt;li&gt;New limter component&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Elegant service governance
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://en.swoft.org/docs/2.x/en/ms/govern/register-discovery.html"&gt;Service registration and discovery&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.swoft.org/docs/2.x/en/ms/govern/breaker.html"&gt;Service breaker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.swoft.org/docs/2.x/en/ms/govern/limiter.html"&gt;Service limiter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.swoft.org/docs/2.x/en/ms/govern/config.html"&gt;Configuration center&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Service registration and discovery
&lt;/h3&gt;

&lt;p&gt;For service registration and discovery, the &lt;a href="https://en.swoft.org/docs/2.x/en/extra/consul.html"&gt;swoft-consul&lt;/a&gt; component provided by Swoft is required, if other third parties are similar.&lt;/p&gt;

&lt;h4&gt;
  
  
  Registration and cancellation services
&lt;/h4&gt;

&lt;p&gt;Listen for the &lt;code&gt;SwooleEvent::START&lt;/code&gt; event, register the service&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cd"&gt;/**
 * Class RegisterServiceListener
 *
 * @since 2.0
 *
 * @Listener(event=SwooleEvent::START)
 */&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RegisterServiceListener&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;EventHandlerInterface&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * @Inject()
     *
     * @var Agent
     */&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$agent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * @param EventInterface $event
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;EventInterface&lt;/span&gt; &lt;span class="nv"&gt;$event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="cm"&gt;/* @var HttpServer $httpServer */&lt;/span&gt;
        &lt;span class="nv"&gt;$httpServer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$event&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;getTarget&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="nv"&gt;$service&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="c1"&gt;// ....&lt;/span&gt;
        &lt;span class="p"&gt;];&lt;/span&gt;

        &lt;span class="nv"&gt;$scheduler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Swoole\Coroutine\Scheduler&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nv"&gt;$scheduler&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;use&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$service&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Register&lt;/span&gt;
            &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;agent&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;registerService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$service&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nx"&gt;CLog&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Swoft http register service success by consul!'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="nv"&gt;$scheduler&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Listen for the &lt;code&gt;SwooleEvent::SHUTDOWN&lt;/code&gt; event, cancel the service&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cd"&gt;/**
 * Class DeregisterServiceListener
 *
 * @since 2.0
 *
 * @Listener(SwooleEvent::SHUTDOWN)
 */&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DeregisterServiceListener&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;EventHandlerInterface&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * @Inject()
     *
     * @var Agent
     */&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$agent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * @param EventInterface $event
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;EventInterface&lt;/span&gt; &lt;span class="nv"&gt;$event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="cm"&gt;/* @var HttpServer $httpServer */&lt;/span&gt;
        &lt;span class="nv"&gt;$httpServer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$event&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;getTarget&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="nv"&gt;$scheduler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Swoole\Coroutine\Scheduler&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nv"&gt;$scheduler&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;use&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$httpServer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;agent&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;deregisterService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'swoft'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="nv"&gt;$scheduler&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;    
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  Service discovery
&lt;/h4&gt;

&lt;p&gt;Defining a service provider&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cd"&gt;/**
 * Class RpcProvider
 *
 * @since 2.0
 *        
 * @Bean()
 */&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RpcProvider&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;ProviderInterface&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * @Inject()
     *
     * @var Agent
     */&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$agent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * @param Client $client
     *
     * @return array
     * @example
     * [
     *     'host:port'
     * ]
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Client&lt;/span&gt; &lt;span class="nv"&gt;$client&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Get health service from consul&lt;/span&gt;
        &lt;span class="nv"&gt;$services&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;agent&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="nv"&gt;$services&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;

        &lt;span class="p"&gt;];&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$services&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Configuration service provider&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'user'&lt;/span&gt;           &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="s1"&gt;'class'&lt;/span&gt;   &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;ServiceClient&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s1"&gt;'provider'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;bean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;RpcProvider&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Service breaker
&lt;/h3&gt;

&lt;p&gt;Swoft uses the &lt;code&gt;@Breaker&lt;/code&gt; annotation to achieve a blow, which can be blown on any method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cd"&gt;/**
 * Class BreakerLogic
 *
 * @since 2.0
 *
 * @Bean()
 */&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BreakerLogic&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * @Breaker(fallback="funcFallback")
     *
     * @return string
     * @throws Exception
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Do something&lt;/span&gt;

        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Breaker exception'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * @return string
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;funcFallback&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s1"&gt;'funcFallback'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Service limit
&lt;/h3&gt;

&lt;p&gt;Swoft uses the &lt;code&gt;@RateLimiter&lt;/code&gt; annotation to implement service throttling, which can be throttled on any method, not just the controller, and KEY also supports &lt;a href="https://symfony.com/doc/current/components/expression_language/syntax.html#component-expression-objects"&gt;symfony/expression-language&lt;/a&gt; expression language.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cd"&gt;/**
 * Class LimiterController
 *
 * @since 2.0
 *
 * @Controller(prefix="limiter")
 */&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LimiterController&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * @RequestMapping()
     * @RateLimiter(key="request.getUriPath()", fallback="limiterFallback")
     *
     * @param Request $request
     *
     * @return array
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;requestLimiter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Request&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;getUriPath&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'requestLimiter'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * @param Request $request
     *
     * @return array
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;limiterFallback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Request&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;getUriPath&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'limiterFallback'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Configuration center
&lt;/h3&gt;

&lt;p&gt;The configuration center needs to use the &lt;a href="https://en.swoft.org/docs/2.x/en/extra/apollo.html"&gt;Swoft-apollo&lt;/a&gt; component provided by Swoft officially, if other third parties are similar.&lt;/p&gt;

&lt;h4&gt;
  
  
  Declare Agent
&lt;/h4&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cd"&gt;/**
 * Class AgentCommand
 *
 * @since 2.0
 *
 * @Command("agent")
 */&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AgentCommand&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * @Inject()
     *
     * @var Config
     */&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$config&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * @CommandMapping(name="index")
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$namespaces&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'application'&lt;/span&gt;
        &lt;span class="p"&gt;];&lt;/span&gt;

        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$namespaces&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'updateConfigFile'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Throwable&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;CLog&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Config agent fail(%s %s %d)!'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;getMessage&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;getFile&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;getLine&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * @param array $data
     *
     * @throws ContainerException
     * @throws ReflectionException
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;updateConfigFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$namespace&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$namespaceData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$configFile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'@config/%s.php'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$namespace&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="nv"&gt;$configKVs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$namespaceData&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'configurations'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nv"&gt;$content&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;?php return '&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nb"&gt;var_export&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$configKVs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;';'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nx"&gt;Co&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;writeFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$configFile&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nv"&gt;$content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;FILE_NO_DEFAULT_CONTEXT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="nx"&gt;CLog&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Apollo update success！'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="cd"&gt;/** @var HttpServer $server */&lt;/span&gt;
            &lt;span class="nv"&gt;$server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;bean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'httpServer'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nv"&gt;$server&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  Start Agent
&lt;/h4&gt;

&lt;p&gt;The Agent only needs to run before the service (Http/RPC/Websocket) is started.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php bin/swoft agent:index
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Resource
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/swoft-cloud/swoft"&gt;https://github.com/swoft-cloud/swoft&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Website：&lt;a href="https://en.swoft.org"&gt;https://en.swoft.org&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Document：&lt;a href="https://en.swoft.org/docs"&gt;https://en.swoft.org/docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Discuss：&lt;a href="https://gitter.im/swoft-cloud/community"&gt;swoft-cloud/community&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>php</category>
      <category>java</category>
      <category>go</category>
    </item>
  </channel>
</rss>
