http://git-wip-us.apache.org/repos/asf/incubator-servicecomb-website/blob/08e1b43f/content/docs/linuxcon-workshop-demo/index.html
----------------------------------------------------------------------
diff --git a/content/docs/linuxcon-workshop-demo/index.html
b/content/docs/linuxcon-workshop-demo/index.html
new file mode 100644
index 0000000..3db6f47
--- /dev/null
+++ b/content/docs/linuxcon-workshop-demo/index.html
@@ -0,0 +1,1525 @@
+<!doctype html>
+<!--
+ Minimal Mistakes Jekyll Theme 4.4.1 by Michael Rose
+ Copyright 2017 Michael Rose - mademistakes.com | @mmistakes
+ Free for personal and commercial use under the MIT license
+ https://github.com/mmistakes/minimal-mistakes/blob/master/LICENSE.txt
+-->
+<html lang="en" class="no-js">
+ <head>
+ <meta charset="utf-8">
+
+<!-- begin SEO -->
+
+
+
+
+
+
+
+
+
+<title>Linux Con Workshop Demo - Apache incubator ServiceComb</title>
+
+
+
+
+<meta name="description" content="A step by step guide on how to use
ServiceComb to develop a complete project">
+
+
+
+
+<meta name="author" content="Sean Yin">
+
+<meta property="og:locale" content="en">
+<meta property="og:site_name" content="Apache incubator ServiceComb">
+<meta property="og:title" content="Linux Con Workshop Demo">
+
+
+ <link rel="canonical"
href="http://github.com/pages/ServiceComb/servicesomb.github.io/docs/linuxcon-workshop-demo/">
+ <meta property="og:url"
content="http://github.com/pages/ServiceComb/servicesomb.github.io/docs/linuxcon-workshop-demo/">
+
+
+
+ <meta property="og:description" content="A step by step guide on how to use
ServiceComb to develop a complete project">
+
+
+
+ <meta name="twitter:site" content="@ServiceComb">
+ <meta name="twitter:title" content="Linux Con Workshop Demo">
+ <meta name="twitter:description" content="A step by step guide on how to use
ServiceComb to develop a complete project">
+ <meta name="twitter:url" content="">
+
+
+ <meta name="twitter:card" content="summary">
+
+
+
+
+ <meta name="twitter:creator" content="@seanyinx">
+
+
+
+
+
+
+
+
+
+
+
+
+ <meta property="og:type" content="article">
+ <meta property="article:published_time" content="2017-06-15T00:00:00+08:00">
+
+
+
+
+
+
+
+
+ <script type="application/ld+json">
+ {
+ "@context" : "http://schema.org",
+ "@type" : "Person",
+ "name" : "Apache incubator ServiceComb",
+ "url" : "http://github.com/pages/ServiceComb/servicesomb.github.io",
+ "sameAs" : null
+ }
+ </script>
+
+
+
+ <meta name="google-site-verification"
content="HvJjNd7vvJ-yjSTHlBiIWEYxp_Hrz-PYEY5Idz9LRcA" />
+
+
+
+
+<!-- end SEO -->
+
+
+<link href="/feed.xml" type="application/atom+xml" rel="alternate"
title="Apache incubator ServiceComb Feed">
+
+<!-- http://t.co/dKP3o1e -->
+<meta name="HandheldFriendly" content="True">
+<meta name="MobileOptimized" content="320">
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+
+<script>
+ document.documentElement.className =
document.documentElement.className.replace(/\bno-js\b/g, '') + ' js ';
+</script>
+<script
src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/1.7.1/clipboard.min.js"></script>
+<script src="/assets/js/prism.js"></script>
+
+<script type="text/javascript" async
+
src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-MML-AM_CHTML">
+</script>
+
+<link rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css"
integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M"
crossorigin="anonymous">
+
+<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"
integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
crossorigin="anonymous"></script>
+<script
src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js"
integrity="sha384-b/U6ypiBEHpOf/4+1nzFpr53nxSS+GLCkfwBdFNTxtclqqenISfwAzpKaMNFNmj4"
crossorigin="anonymous"></script>
+<script
src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/js/bootstrap.min.js"
integrity="sha384-h0AbiXch4ZDo7tp9hKZ4TsHbi047NrKGLO3SEJAg45jXxnGIfYzk4Si90RDIqNm1"
crossorigin="anonymous"></script>
+<!-- For all browsers -->
+<link rel="stylesheet" href="/assets/css/main.css">
+<link rel="stylesheet" href="/assets/css/prism.css">
+
+<!--[if lte IE 9]>
+ <style>
+ /* old IE unsupported flexbox fixes */
+ .greedy-nav .site-title {
+ padding-right: 3em;
+ }
+ .greedy-nav button {
+ position: absolute;
+ top: 0;
+ right: 0;
+ height: 100%;
+ }
+ </style>
+<![endif]-->
+
+<meta http-equiv="cleartype" content="on">
+
+ <!-- start custom head snippets -->
+
+<!-- insert favicons. use http://realfavicongenerator.net/ -->
+<link
href="https://fonts.cat.net/css?family=Roboto:400,500,700|Source+Code+Pro"
rel="stylesheet">
+<script src="/assets/js/custom.js"></script>
+<!-- end custom head snippets -->
+
+ </head>
+
+ <body class="layout--single">
+
+ <!--[if lt IE 9]>
+<div class="notice--danger align-center" style="margin: 0;">You are using an
<strong>outdated</strong> browser. Please <a
href="http://browsehappy.com/">upgrade your browser</a> to improve your
experience.</div>
+<![endif]-->
+ <div class="masthead">
+ <div class="masthead__inner-wrap">
+ <div class="masthead__menu">
+ <nav id="site-nav" class="greedy-nav">
+
+ <a class="site-title active" href="/"><img
src="//assets/images/ServiceComb-logo-1.png"></a>
+
+ <ul class="visible-links">
+
+
+ <li class="masthead__menu-item">
+
+
+
+ <a href="/docs/quick-start/">Quick Start</a>
+
+ </li>
+
+
+ <li class="masthead__menu-item">
+
+
+
+ <a href="/users/">Users</a>
+
+ </li>
+
+
+ <li class="masthead__menu-item">
+
+
+
+ <a href="/developers/">Developers</a>
+
+ </li>
+
+
+ <li class="masthead__menu-item">
+
+
+
+ <a href="/year-archive/">Blogs</a>
+
+ </li>
+
+
+ <li class="masthead__menu-item">
+
+
+
+ <a href="/faqs/">FAQ</a>
+
+ </li>
+
+ </ul>
+ <button><div class="navicon"></div></button>
+ <ul class="hidden-links hidden"></ul>
+ <div class="nav-lang">
+
+
+ <a href=/cn/docs/linuxcon-workshop-demo/>ä¸æ</a>
+
+ </div>
+ </nav>
+ </div>
+ </div>
+</div>
+
+
+
+
+
+
+<div id="main" role="main">
+
+ <div class="sidebar sticky">
+
+ <div class="back-to-home">Home > <a href="/">ServiceComb</a></div>
+
+
+
+<div itemscope itemtype="http://schema.org/Person">
+
+
+
+ <div class="author__content">
+ <h3 class="author__name" itemprop="name">Sean Yin</h3>
+
+ <p class="author__bio" itemprop="description">
+
+ Nothing but speed is indestructible
+
+ </p>
+
+ </div>
+
+ <div class="author__urls-wrapper">
+ <button class="btn btn--inverse">Follow</button>
+ <ul class="author__urls social-icons">
+
+
+
+ <li>
+ <a href="http://seanyinx.github.io" itemprop="url">
+ <i class="fa fa-fw fa-chain" aria-hidden="true"></i> Website
+ </a>
+ </li>
+
+
+
+ <li>
+ <a href="mailto:seany...@gmail.com">
+ <meta itemprop="email" content="seany...@gmail.com" />
+ <i class="fa fa-fw fa-envelope-square" aria-hidden="true"></i>
Email
+ </a>
+ </li>
+
+
+
+
+
+ <li>
+ <a href="https://twitter.com/seanyinx" itemprop="sameAs">
+ <i class="fa fa-fw fa-twitter-square" aria-hidden="true"></i>
Twitter
+ </a>
+ </li>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <!--
+ <li>
+ <a href="http://link-to-whatever-social-network.com/user/"
itemprop="sameAs">
+ <i class="fa fa-fw" aria-hidden="true"></i> Custom Social Profile Link
+ </a>
+ </li>
+-->
+ </ul>
+ </div>
+</div>
+
+
+ </div>
+
+
+
+ <article class="page" itemscope itemtype="http://schema.org/CreativeWork">
+ <meta itemprop="headline" content="Linux Con Workshop Demo">
+ <meta itemprop="description" content="A step by step guide on how to use
ServiceComb to develop a complete project">
+ <meta itemprop="datePublished" content="June 15, 2017">
+ <meta itemprop="dateModified" content="June 15, 2017">
+
+ <div class="page__inner-wrap">
+
+
+ <header>
+ <h1 class="page__title" itemprop="headline">Linux Con Workshop Demo
+</h1>
+
+ <p class="page__meta"><i class="fa fa-clock-o"
aria-hidden="true"></i>
+
+
+
+
+ 6 minute read
+
+</p>
+
+ </header>
+
+
+
+ <section class="page__content" itemprop="text">
+ <p>为äºè¯»è
è½æ´å®¹æäºè§£ServiceCombå¾®æå¡æ¡æ¶çåè½ä»¥åå¦ä½ç¨å
¶å¿«éå¼åå¾®æå¡ï¼æ以æä¾å¤§å®¶è³çè½è¯¦çä¾åï¼éä½å¦ä¹
æ²çº¿çåæ¶ï¼å¢å 趣å³æ§ï¼å æ·±ç解ã</p>
+
+<p>æ¬æä¸å设æ们æç«äºä¸å®¶ç§ç å
¬å¸ï¼å¤çå¤æçæ°å¦è¿ç®ï¼ä»¥åå°ç«¯çç©ç§æç
究ï¼å¹¶ä¸ºç¨æ·æä¾å¦ä¸æå¡ï¼</p>
+
+<ul>
+ <li>
+ <p>é»éåå²æ°å计ç®</p>
+ </li>
+ <li>
+ <p>èèç¹æ®è§å¾ (计ç®æ¯åªéè/éèçç¥å
æ°é)</p>
+ </li>
+</ul>
+
+<p>ä½æ¯æ们å¦ä½å°å
¬å¸çè¿äºå¼ºå¤§è¿ç®è½åæä¾ç»æ们çæ¶è´¹è
å¢ï¼</p>
+
+<p>é¦å
æ们éè¿è®¤è¯æå¡ä¿éå
¬å¸ç计ç®èµæºæ²¡æ被滥ç¨ï¼
åæ¶æ们对å¤æä¾Restæå¡è®©ç¨æ·æ¥è¿è¡è®¿é®ã
ä¸é¢çè§é¢å±ç¤ºå
·ä½çæå¡éªè¯è°ç¨çæ
åµã</p>
+
+<!-- Courtesy of embedresponsively.com //-->
+<div class="responsive-video-container">
+
+ <iframe src="https://player.youku.com/embed/XMjg1NzQ3NzUzNg" frameborder="0"
allowfullscreen=""></iframe>
+
+</div>
+
+<aside class="sidebar__right">
+<nav class="toc">
+ <!-- <header><h4 class="nav__title"><i class="fa fa-file-text"></i> On
This Page</h4></header> -->
+<ul class="toc__menu" id="markdown-toc">
+ <li><a href="#ä¸å¡åºæ¯"
id="markdown-toc-ä¸å¡åºæ¯">ä¸å¡åºæ¯</a></li>
+ <li><a href="#å
¬å¸ç»æ-ç³»ç»æ¶æ" id="markdown-toc-å
¬å¸ç»æ-ç³»ç»æ¶æ">å
¬å¸ç»æ (ç³»ç»æ¶æ)</a></li>
+ <li><a href="#æå·¥-worker" id="markdown-toc-æå·¥-worker">æå·¥
(Worker)</a> <ul>
+ <li><a href="#é»éåå²è¿ç®æå¡"
id="markdown-toc-é»éåå²è¿ç®æå¡">é»éåå²è¿ç®æå¡</a></li>
+ <li><a href="#æå·¥æå¡ç«¯ç¹"
id="markdown-toc-æå·¥æå¡ç«¯ç¹">æå·¥æå¡ç«¯ç¹</a></li>
+ </ul>
+ </li>
+ <li><a href="#å示æ -bulletin-board" id="markdown-toc-å示æ
-bulletin-board">å示æ (Bulletin Board)</a></li>
+ <li><a href="#å
»è人-beekeeper" id="markdown-toc-å
»è人-beekeeper">å
»è人 (Beekeeper)</a> <ul>
+ <li><a href="#èèç¹æ®è§å¾ç 究æå¡"
id="markdown-toc-èèç¹æ®è§å¾ç 究æå¡">èèç¹æ®è§å¾ç
究æå¡</a></li>
+ <li><a href="#å
»è人æå¡ç«¯ç¹" id="markdown-toc-å
»è人æå¡ç«¯ç¹">å
»è人æå¡ç«¯ç¹</a></li>
+ </ul>
+ </li>
+ <li><a href="#é¨å«-doorman" id="markdown-toc-é¨å«-doorman">é¨å«
(Doorman)</a> <ul>
+ <li><a href="#é¨å«è®¤è¯æå¡"
id="markdown-toc-é¨å«è®¤è¯æå¡">é¨å«è®¤è¯æå¡</a></li>
+ <li><a href="#é¨å«è®¤è¯æå¡ç«¯ç¹"
id="markdown-toc-é¨å«è®¤è¯æå¡ç«¯ç¹">é¨å«è®¤è¯æå¡ç«¯ç¹</a></li>
+ </ul>
+ </li>
+ <li><a href="#ç»ç-manager" id="markdown-toc-ç»ç-manager">ç»ç
(Manager)</a> <ul>
+ <li><a href="#ç¨æ·è®¤è¯æå¡"
id="markdown-toc-ç¨æ·è®¤è¯æå¡">ç¨æ·è®¤è¯æå¡</a></li>
+ <li><a href="#请æ±è¿æ»¤"
id="markdown-toc-请æ±è¿æ»¤">请æ±è¿æ»¤</a></li>
+ </ul>
+ </li>
+ <li><a href="#项ç®å½æ¡£-project-archive"
id="markdown-toc-项ç®å½æ¡£-project-archive">项ç®å½æ¡£ (Project
Archive)</a></li>
+ <li><a href="#人åèµæº-human-resource"
id="markdown-toc-人åèµæº-human-resource">人åèµæº (Human
Resource)</a></li>
+ <li><a href="#æ»ç»" id="markdown-toc-æ»ç»">æ»ç»</a></li>
+</ul>
+
+ </nav>
+</aside>
+
+<h2 id="ä¸å¡åºæ¯">ä¸å¡åºæ¯</h2>
+<p>让æ们å
对ä¸å¡åºæ¯è¿è¡æ»ç»åæ</p>
+
+<ol>
+ <li>
+ <p>为äºå
¬å¸æç»åå±ï¼æ们éè¦å¯¹ç¨æ·æ¶è´¹çè¿ç®è½åæ¶è´¹ï¼æ以æ们èç¨äº<strong>é¨å«</strong>认è¯ç¨æ·ï¼é¿å
ä¸æ³ååæ··å
¥</p>
+ </li>
+ <li>
+
<p>为äºæä¾è¶³å¤çé»éåå²æ°éè¿ç®è½åï¼æ们éè¦éä½£ç¸åºç<strong>æå·¥</strong></p>
+ </li>
+ <li>
+ <p>为äºæç»ç 究èèç¹æ®è§å¾ï¼å
¬å¸å»ºç«äºèªå·±çèåºï¼éè¦ç¸åºç<strong>å
»è人</strong>è¿è¡ç®¡çç 究</p>
+ </li>
+ <li>
+ <p>为äºå¹³è¡¡<strong>æå·¥</strong>ã<strong>å
»è人</strong>ãå<strong>é¨å«</strong>çå·¥ä½éåæ¶é´ï¼æ们建ç«äº<strong>å示æ
</strong>æºå¶ï¼è®©å½åæé²æç人ååå¸èªå·±çèç³»æ¹å¼ï¼ä»¥ä¾¿æ们è½åæ¶èç³»æè½å¹é
ç人å以æå¡å°æ¥çç¨æ·</p>
+ </li>
+ <li>
+ <p>å
为è¿ç®è½åææ¬é«æï¼æ们å°è¿ç®é¡¹ç®è¿è¡äº<strong>å½æ¡£</strong>ï¼ä»¥ä¾¿æªæ¥æç¸å请æ±æ¶ï¼æ们è½ç´æ¥æ¥è¯¢<strong>项ç®å½æ¡£</strong>ï¼èçå
¬å¸è¿ç®ææ¬</p>
+ </li>
+ <li>
+
<p>é¢å¯¹ä¸è¿°å¤æçåºæ¯ï¼æ们åèç¨äº<strong>é¨é¨ç»ç</strong>æ¥ç®¡çå
¬å¸æåå设æ½</p>
+ </li>
+ <li>
+ <p>æåï¼å½å
¬å¸æ¥ç壮大ï¼ç¨æ·æ°éæ´æ¶¨æ¶ï¼æ们è¿éè¦æèæ´å¤<strong>æå·¥</strong>ã<strong>å
»è人</strong>ãå<strong>é¨å«</strong>ï¼æ以å¢å
äº<strong>人åèµæº</strong>é¨é¨</p>
+ </li>
+</ol>
+
+<h2 id="å
¬å¸ç»æ-ç³»ç»æ¶æ">å
¬å¸ç»æ (ç³»ç»æ¶æ)</h2>
+<p>å°ç°å¨ä¸å¡åºæ¯å·²ç»æ¯è¾æ¸
æ°ï¼æ们æä¸è¿°èå¡é¨é¨å设æ½ç»æå
¬å¸ç»ç»ç»æå¾ã
+<img src="/assets/images/workshop-company-structure.png" alt="company
structure" class="align-center" /></p>
+
+<p>ç°å¨å
¬å¸ç»ç»ç»æå·²ç»å®æ´ï¼è®©æ们çææ建ç¸åºé¨é¨ã</p>
+
+<h2 id="æå·¥-worker">æå·¥ (Worker)</h2>
+<p>å 为æå·¥æ为ç®åï¼å¯¹å
¶ä»é¨é¨äººåä¾èµæå°ï¼æ们é¦å
æ建è¿ä¸ªé¨é¨ã</p>
+
+<h3 id="é»éåå²è¿ç®æå¡">é»éåå²è¿ç®æå¡</h3>
+<p>æå·¥ç主è¦å·¥ä½æ¶æä¾é»éåå²æ°å计ç®æå¡ï¼å½ç¨æ·éè¦ç¥é第n个é»éåå²æ°æ¶ï¼æ工以æå¿«çé度计ç®åºæ°å¼å¹¶è¿åç»ç¨æ·ã
+æ们å¯ä»¥æè¿ä¸ªå·¥ä½ç®å为å¦ä¸æ°å¦æ¹ç¨:</p>
+
+<div class="highlighter-rouge"><pre class="highlight"><code>value = fibo(n)
+</code></pre>
+</div>
+
+<p>å¨ææ¶ä¸èèæ§è½çæ
åµä¸ï¼æ们å¯ä»¥è¿
éå®ç°é»éåå²æ°åç计ç®ã</p>
+<div class="language-java highlighter-rouge"><pre
class="highlight"><code><span class="kd">interface</span> <span
class="nc">FibonacciService</span> <span class="o">{</span>
+ <span class="kt">long</span> <span class="nf">term</span><span
class="o">(</span><span class="kt">int</span> <span class="n">n</span><span
class="o">);</span>
+<span class="o">}</span>
+
+<span class="nd">@Service</span>
+<span class="kd">class</span> <span class="nc">FibonacciServiceImpl</span>
<span class="kd">implements</span> <span class="n">FibonacciService</span>
<span class="o">{</span>
+ <span class="nd">@Override</span>
+ <span class="kd">public</span> <span class="kt">long</span> <span
class="nf">term</span><span class="o">(</span><span class="kt">int</span> <span
class="n">n</span><span class="o">)</span> <span class="o">{</span>
+ <span class="k">if</span> <span class="o">(</span><span class="n">n</span>
<span class="o">==</span> <span class="mi">0</span><span class="o">)</span>
<span class="o">{</span>
+ <span class="k">return</span> <span class="mi">0</span><span
class="o">;</span>
+ <span class="o">}</span> <span class="k">else</span> <span
class="k">if</span> <span class="o">(</span><span class="n">n</span> <span
class="o">==</span> <span class="mi">1</span><span class="o">)</span> <span
class="o">{</span>
+ <span class="k">return</span> <span class="mi">1</span><span
class="o">;</span>
+ <span class="o">}</span>
+
+ <span class="k">return</span> <span class="nf">term</span><span
class="o">(</span><span class="n">n</span> <span class="o">-</span> <span
class="mi">1</span><span class="o">)</span> <span class="o">+</span> <span
class="n">term</span><span class="o">(</span><span class="n">n</span> <span
class="o">-</span> <span class="mi">2</span><span class="o">);</span>
+ <span class="o">}</span>
+<span class="o">}</span>
+</code></pre>
+</div>
+
+<h3 id="æå·¥æå¡ç«¯ç¹">æå·¥æå¡ç«¯ç¹</h3>
+<p>é»éåå²æ°éè¿ç®å·²ç»å®ç°ï¼ç°å¨æ们éè¦å°æå¡æä¾ç»ç¨æ·ï¼é¦å
æ们å®ä¹ç«¯ç¹æ¥å£ï¼</p>
+
+<div class="language-java highlighter-rouge"><pre
class="highlight"><code><span class="kd">public</span> <span
class="kd">interface</span> <span class="nc">FibonacciEndpoint</span> <span
class="o">{</span>
+ <span class="kt">long</span> <span class="nf">term</span><span
class="o">(</span><span class="kt">int</span> <span class="n">n</span><span
class="o">);</span>
+<span class="o">}</span>
+</code></pre>
+</div>
+
+<p>å¼å
¥ <code class="highlighter-rouge">ServiceComb</code> ä¾èµï¼</p>
+
+<div class="language-xml highlighter-rouge"><pre class="highlight"><code>
<span class="nt"><dependency></span>
+ <span class="nt"><groupId></span>io.servicecomb<span
class="nt"></groupId></span>
+ <span
class="nt"><artifactId></span>spring-boot-starter-provider<span
class="nt"></artifactId></span>
+ <span class="nt"></dependency></span>
+
+</code></pre>
+</div>
+
+<p>æ¥ä¸æ¥æ们åæ¶æ´é²é»éåå²è¿ç®æå¡ç<strong>Restful</strong>å<strong>RPC</strong>端ç¹ï¼</p>
+
+<div class="language-java highlighter-rouge"><pre
class="highlight"><code><span class="nd">@RestSchema</span><span
class="o">(</span><span class="n">schemaId</span> <span class="o">=</span>
<span class="s">"fibonacciRestEndpoint"</span><span class="o">)</span>
+<span class="nd">@RequestMapping</span><span class="o">(</span><span
class="s">"/fibonacci"</span><span class="o">)</span>
+<span class="nd">@Controller</span>
+<span class="kd">public</span> <span class="kd">class</span> <span
class="nc">FibonacciRestEndpoint</span> <span class="kd">implements</span>
<span class="n">FibonacciEndpoint</span> <span class="o">{</span>
+
+ <span class="kd">private</span> <span class="kd">final</span> <span
class="n">FibonacciService</span> <span class="n">fibonacciService</span><span
class="o">;</span>
+
+ <span class="nd">@Autowired</span>
+ <span class="n">FibonacciRestEndpoint</span><span class="o">(</span><span
class="n">FibonacciService</span> <span class="n">fibonacciService</span><span
class="o">)</span> <span class="o">{</span>
+ <span class="k">this</span><span class="o">.</span><span
class="na">fibonacciService</span> <span class="o">=</span> <span
class="n">fibonacciService</span><span class="o">;</span>
+ <span class="o">}</span>
+
+ <span class="nd">@Override</span>
+ <span class="nd">@RequestMapping</span><span class="o">(</span><span
class="n">value</span> <span class="o">=</span> <span
class="s">"/term"</span><span class="o">,</span> <span class="n">method</span>
<span class="o">=</span> <span class="n">RequestMethod</span><span
class="o">.</span><span class="na">GET</span><span class="o">)</span>
+ <span class="nd">@ResponseBody</span>
+ <span class="kd">public</span> <span class="kt">long</span> <span
class="nf">term</span><span class="o">(</span><span class="kt">int</span> <span
class="n">n</span><span class="o">)</span> <span class="o">{</span>
+ <span class="k">return</span> <span class="n">fibonacciService</span><span
class="o">.</span><span class="na">term</span><span class="o">(</span><span
class="n">n</span><span class="o">);</span>
+ <span class="o">}</span>
+<span class="o">}</span>
+</code></pre>
+</div>
+
+<div class="language-java highlighter-rouge"><pre
class="highlight"><code><span class="nd">@RpcSchema</span><span
class="o">(</span><span class="n">schemaId</span> <span class="o">=</span>
<span class="s">"fibonacciRpcEndpoint"</span><span class="o">)</span>
+<span class="kd">public</span> <span class="kd">class</span> <span
class="nc">FibonacciRpcEndpoint</span> <span class="kd">implements</span> <span
class="n">FibonacciEndpoint</span> <span class="o">{</span>
+
+ <span class="kd">private</span> <span class="kd">final</span> <span
class="n">FibonacciService</span> <span class="n">fibonacciService</span><span
class="o">;</span>
+
+ <span class="nd">@Autowired</span>
+ <span class="kd">public</span> <span
class="nf">FibonacciRpcEndpoint</span><span class="o">(</span><span
class="n">FibonacciService</span> <span class="n">fibonacciService</span><span
class="o">)</span> <span class="o">{</span>
+ <span class="k">this</span><span class="o">.</span><span
class="na">fibonacciService</span> <span class="o">=</span> <span
class="n">fibonacciService</span><span class="o">;</span>
+ <span class="o">}</span>
+
+ <span class="nd">@Override</span>
+ <span class="kd">public</span> <span class="kt">long</span> <span
class="nf">term</span><span class="o">(</span><span class="kt">int</span> <span
class="n">n</span><span class="o">)</span> <span class="o">{</span>
+ <span class="k">return</span> <span class="n">fibonacciService</span><span
class="o">.</span><span class="na">term</span><span class="o">(</span><span
class="n">n</span><span class="o">);</span>
+ <span class="o">}</span>
+<span class="o">}</span>
+</code></pre>
+</div>
+
+<p>è¿éç¨ <code class="highlighter-rouge">@RestSchema</code> å <code
class="highlighter-rouge">@RpcSchema</code> 注é两个端ç¹åï¼<code
class="highlighter-rouge">ServiceComb</code>
ä¼èªå¨çæ对åºçæå¡ç«¯ç¹å¥çº¦ï¼æ ¹æ®å¦ä¸
+<code class="highlighter-rouge">microsevice.yaml</code> é
置端ç¹ç«¯å£ï¼å¹¶å°å¥çº¦åæå¡ä¸èµ·æ³¨åå°<a
href="https://github.com/ServiceComb/service-center">Service Center</a>ï¼</p>
+
+<div class="language-yaml highlighter-rouge"><pre
class="highlight"><code><span class="c1"># all interconnected microservices
must belong to an application wth the same ID</span>
+<span class="s">APPLICATION_ID</span><span class="pi">:</span> <span
class="s">company</span>
+<span class="s">service_description</span><span class="pi">:</span>
+<span class="c1"># name of the declaring microservice</span>
+ <span class="s">name</span><span class="pi">:</span> <span
class="s">worker</span>
+ <span class="s">version</span><span class="pi">:</span> <span
class="s">0.0.1</span>
+<span class="c1"># service center address</span>
+<span class="s">cse</span><span class="pi">:</span>
+ <span class="s">service</span><span class="pi">:</span>
+ <span class="s">registry</span><span class="pi">:</span>
+ <span class="s">address</span><span class="pi">:</span> <span
class="s">http://sc.servicecomb.io:30100</span>
+ <span class="s">highway</span><span class="pi">:</span>
+ <span class="s">address</span><span class="pi">:</span> <span
class="s">0.0.0.0:7070</span>
+ <span class="s">rest</span><span class="pi">:</span>
+ <span class="s">address</span><span class="pi">:</span> <span
class="s">0.0.0.0:8080</span>
+</code></pre>
+</div>
+
+<p>æåï¼æä¾æå·¥æå¡åºç¨å¯å¨å
¥å£ï¼å¹¶å ä¸ <code
class="highlighter-rouge">@EnableServiceComb</code> 注éå¯ç¨ <code
class="highlighter-rouge">ServiceComb</code> ï¼</p>
+
+<div class="language-java highlighter-rouge"><pre
class="highlight"><code><span class="nd">@SpringBootApplication</span>
+<span class="nd">@EnableServiceComb</span>
+<span class="kd">public</span> <span class="kd">class</span> <span
class="nc">WorkerApplication</span> <span class="o">{</span>
+
+ <span class="kd">public</span> <span class="kd">static</span> <span
class="kt">void</span> <span class="nf">main</span><span
class="o">(</span><span class="n">String</span><span class="o">[]</span> <span
class="n">args</span><span class="o">)</span> <span class="o">{</span>
+ <span class="n">SpringApplication</span><span class="o">.</span><span
class="na">run</span><span class="o">(</span><span
class="n">WorkerApplication</span><span class="o">.</span><span
class="na">class</span><span class="o">,</span> <span
class="n">args</span><span class="o">);</span>
+ <span class="o">}</span>
+<span class="o">}</span>
+</code></pre>
+</div>
+
+<h2 id="å示æ -bulletin-board">å示æ (Bulletin Board)</h2>
+<p><strong>å示æ
</strong>æä¾ä¸º<strong>é¨å«</strong>ã<strong>æå·¥</strong>å<strong>å
»è人</strong>注åèç³»æ¹å¼ç设æ½ï¼åæ¶<strong>ç»ç</strong>å<strong>å
»è人</strong>å¯éè¿æ¤è®¾æ½æ¥è¯¢æ³¨åæ¹çèç³»æ¹å¼ï¼ä»¥æ¹ä¾¿å¹é
è½åçæä¾åæ¶è´¹ã</p>
+
+<p><code class="highlighter-rouge">Service Center</code>
æä¾å¥çº¦åæå¡æ³¨åãåç°åè½ï¼èä¸æ
¡éªæå¡æä¾æ¹åæ¶è´¹æ¹çå¥çº¦æ¯å¦å¹é
ï¼æ们å¯ä»¥<a
href="https://github.com/ServiceComb/service-center/releases">ä¸è½½</a>ç¼è¯å¥½ççæ¬ç´æ¥è¿è¡ã</p>
+
+<h2 id="å
»è人-beekeeper">å
»è人 (Beekeeper)</h2>
+<p><strong>å
»è人</strong>ç 究èèç¹æ®è§å¾ï¼è®¡ç®æ¯åªèè
(éè/éè) çç¥å
æ°éãå
为èèç¹æ®è§å¾åé»éåå²æ°åç¸å
³ï¼æ以<strong>å
»è人</strong>åæ¶æ¶è´¹<strong>æå·¥</strong>æä¾ç计ç®æå¡ã</p>
+
+<p><a href="http://www.dave-cushman.net/bee/fibonacci.html">ç
究</a>表æï¼éè(Drone)ç±æªåç²¾åµåµåèçï¼åªææ¯äº²ï¼èéè(Queen)ç±åç²¾åµåµåèçï¼æ¢ææ¯åæç¶ã</p>
+
+<p class="figure-caption"><img src="/assets/images/fibonaccitree.gif"
alt="fibonacci tree" />
+Credit: <a href="http://www.dave-cushman.net"">Dave Cushmanâs
website</a></p>
+
+<p>åèä¸å¾ï¼èèçæä¸ä»£ç¥å
æ°é符åé»éåå²æ°åç模åï¼ç±æ¤æ们å¯ä»¥å¾å¿«å®ç°æå¡åè½ã</p>
+
+<h3 id="èèç¹æ®è§å¾ç 究æå¡">èèç¹æ®è§å¾ç 究æå¡</h3>
+<p>é¦å
æ们å®ä¹é»éæ°åè¿ç®æ¥å£ï¼</p>
+
+<div class="language-java highlighter-rouge"><pre
class="highlight"><code><span class="kd">public</span> <span
class="kd">interface</span> <span class="nc">FibonacciCalculator</span> <span
class="o">{</span>
+
+ <span class="kt">long</span> <span class="nf">term</span><span
class="o">(</span><span class="kt">int</span> <span class="n">n</span><span
class="o">);</span>
+<span class="o">}</span>
+</code></pre>
+</div>
+
+<p>æ¥ä¸æ¥å®ä¹å¹¶å®ç°èèç¹æ®è§å¾ç 究æå¡:</p>
+<div class="language-java highlighter-rouge"><pre
class="highlight"><code><span class="kd">interface</span> <span
class="nc">BeekeeperService</span> <span class="o">{</span>
+ <span class="kt">long</span> <span class="nf">ancestorsOfDroneAt</span><span
class="o">(</span><span class="kt">int</span> <span
class="n">generation</span><span class="o">);</span>
+
+ <span class="kt">long</span> <span class="nf">ancestorsOfQueenAt</span><span
class="o">(</span><span class="kt">int</span> <span
class="n">generation</span><span class="o">);</span>
+<span class="o">}</span>
+
+<span class="kd">class</span> <span class="nc">BeekeeperServiceImpl</span>
<span class="kd">implements</span> <span class="n">BeekeeperService</span>
<span class="o">{</span>
+
+ <span class="kd">private</span> <span class="kd">final</span> <span
class="n">FibonacciCalculator</span> <span
class="n">fibonacciCalculator</span><span class="o">;</span>
+
+ <span class="n">BeekeeperServiceImpl</span><span class="o">(</span><span
class="n">FibonacciCalculator</span> <span
class="n">fibonacciCalculator</span><span class="o">)</span> <span
class="o">{</span>
+ <span class="k">this</span><span class="o">.</span><span
class="na">fibonacciCalculator</span> <span class="o">=</span> <span
class="n">fibonacciCalculator</span><span class="o">;</span>
+ <span class="o">}</span>
+
+ <span class="nd">@Override</span>
+ <span class="kd">public</span> <span class="kt">long</span> <span
class="nf">ancestorsOfDroneAt</span><span class="o">(</span><span
class="kt">int</span> <span class="n">generation</span><span class="o">)</span>
<span class="o">{</span>
+ <span class="k">if</span> <span class="o">(</span><span
class="n">generation</span> <span class="o"><=</span> <span
class="mi">0</span><span class="o">)</span> <span class="o">{</span>
+ <span class="k">return</span> <span class="mi">0</span><span
class="o">;</span>
+ <span class="o">}</span>
+ <span class="k">return</span> <span
class="n">fibonacciCalculator</span><span class="o">.</span><span
class="na">term</span><span class="o">(</span><span class="n">generation</span>
<span class="o">+</span> <span class="mi">1</span><span class="o">);</span>
+ <span class="o">}</span>
+
+ <span class="nd">@Override</span>
+ <span class="kd">public</span> <span class="kt">long</span> <span
class="nf">ancestorsOfQueenAt</span><span class="o">(</span><span
class="kt">int</span> <span class="n">generation</span><span class="o">)</span>
<span class="o">{</span>
+ <span class="k">if</span> <span class="o">(</span><span
class="n">generation</span> <span class="o"><=</span> <span
class="mi">0</span><span class="o">)</span> <span class="o">{</span>
+ <span class="k">return</span> <span class="mi">0</span><span
class="o">;</span>
+ <span class="o">}</span>
+ <span class="k">return</span> <span
class="n">fibonacciCalculator</span><span class="o">.</span><span
class="na">term</span><span class="o">(</span><span class="n">generation</span>
<span class="o">+</span> <span class="mi">2</span><span class="o">);</span>
+ <span class="o">}</span>
+<span class="o">}</span>
+</code></pre>
+</div>
+
+<p>è¿éæ们ç¨å°ä¹åå®ä¹ç <code
class="highlighter-rouge">FibonacciCalculator</code>
æ¥å£ï¼å¹¶å¸æéè¿è¿ä¸ªæ¥å£è¿ç¨è°ç¨<strong>æå·¥</strong>æå¡ç«¯ç¹ã<code
class="highlighter-rouge">@RpcReference</code>
+注éè½å¸®å©æ们èªå¨ä»<a
href="https://github.com/ServiceComb/service-center">Service Center</a>ä¸è·å
+<code class="highlighter-rouge">microserviceName = "worker", schemaId =
"fibonacciRpcEndpoint"</code> ï¼ å³æå¡å为 <code
class="highlighter-rouge">worker</code> å·²ç»schema ID为
+<code class="highlighter-rouge">fibonacciRpcEndpoint</code>ç端ç¹ï¼</p>
+
+<div class="language-java highlighter-rouge"><pre
class="highlight"><code><span class="nd">@Configuration</span>
+<span class="kd">class</span> <span class="nc">BeekeeperConfig</span> <span
class="o">{</span>
+
+ <span class="nd">@RpcReference</span><span class="o">(</span><span
class="n">microserviceName</span> <span class="o">=</span> <span
class="s">"worker"</span><span class="o">,</span> <span
class="n">schemaId</span> <span class="o">=</span> <span
class="s">"fibonacciRpcEndpoint"</span><span class="o">)</span>
+ <span class="kd">private</span> <span class="n">FibonacciCalculator</span>
<span class="n">fibonacciCalculator</span><span class="o">;</span>
+
+ <span class="nd">@Bean</span>
+ <span class="n">BeekeeperService</span> <span
class="nf">beekeeperService</span><span class="o">()</span> <span
class="o">{</span>
+ <span class="k">return</span> <span class="k">new</span> <span
class="nf">BeekeeperServiceImpl</span><span class="o">(</span><span
class="n">fibonacciCalculator</span><span class="o">);</span>
+ <span class="o">}</span>
+<span class="o">}</span>
+</code></pre>
+</div>
+
+<p>æ们å¨<strong>æå·¥</strong>ä¸èå·²å®ä¹å¥½å¯¹åºçæå¡ååschema
ID端ç¹ï¼éè¿ä¸é¢çé
ç½®ï¼<code
class="highlighter-rouge">ServiceComb</code>
ä¼èªå¨å°è¿ç¨<strong>æå·¥</strong>æå¡
+å®ä¾å <code class="highlighter-rouge">FibonacciCalculator</code>
ç»å®å¨ä¸èµ·ã</p>
+
+<h3 id="å
»è人æå¡ç«¯ç¹">å
»è人æå¡ç«¯ç¹</h3>
+<p>ä¸ä¸ä¸è<strong>æå·¥</strong>æå¡ç¸ä¼¼ï¼æ们å¨è¿éä¹éè¦æä¾å
»è人æå¡ç«¯ç¹ï¼è®©ç¨æ·å¯ä»¥è¿è¡è°ç¨ï¼</p>
+
+<div class="language-java highlighter-rouge"><pre
class="highlight"><code><span class="nd">@RestSchema</span><span
class="o">(</span><span class="n">schemaId</span> <span class="o">=</span>
<span class="s">"beekeeperRestEndpoint"</span><span class="o">)</span>
+<span class="nd">@RequestMapping</span><span class="o">(</span><span
class="s">"/rest"</span><span class="o">)</span>
+<span class="nd">@Controller</span>
+<span class="kd">public</span> <span class="kd">class</span> <span
class="nc">BeekeeperController</span> <span class="o">{</span>
+
+ <span class="kd">private</span> <span class="kd">static</span> <span
class="kd">final</span> <span class="n">Logger</span> <span
class="n">logger</span> <span class="o">=</span> <span
class="n">LoggerFactory</span><span class="o">.</span><span
class="na">getLogger</span><span class="o">(</span><span
class="n">BeekeeperController</span><span class="o">.</span><span
class="na">class</span><span class="o">);</span>
+
+ <span class="kd">private</span> <span class="kd">final</span> <span
class="n">BeekeeperService</span> <span class="n">beekeeperService</span><span
class="o">;</span>
+
+ <span class="nd">@Autowired</span>
+ <span class="n">BeekeeperController</span><span class="o">(</span><span
class="n">BeekeeperService</span> <span class="n">beekeeperService</span><span
class="o">)</span> <span class="o">{</span>
+ <span class="k">this</span><span class="o">.</span><span
class="na">beekeeperService</span> <span class="o">=</span> <span
class="n">beekeeperService</span><span class="o">;</span>
+ <span class="o">}</span>
+
+ <span class="nd">@RequestMapping</span><span class="o">(</span><span
class="n">value</span> <span class="o">=</span> <span
class="s">"/drone/ancestors/{generation}"</span><span class="o">,</span> <span
class="n">method</span> <span class="o">=</span> <span
class="n">GET</span><span class="o">,</span> <span class="n">produces</span>
<span class="o">=</span> <span
class="n">APPLICATION_JSON_UTF8_VALUE</span><span class="o">)</span>
+ <span class="nd">@ResponseBody</span>
+ <span class="kd">public</span> <span class="n">Ancestor</span> <span
class="nf">ancestorsOfDrone</span><span class="o">(</span><span
class="nd">@PathVariable</span> <span class="kt">int</span> <span
class="n">generation</span><span class="o">)</span> <span class="o">{</span>
+ <span class="n">logger</span><span class="o">.</span><span
class="na">info</span><span class="o">(</span>
+ <span class="s">"Received request to find the number of ancestors of
drone at generation {}"</span><span class="o">,</span>
+ <span class="n">generation</span><span class="o">);</span>
+
+ <span class="k">return</span> <span class="k">new</span> <span
class="nf">Ancestor</span><span class="o">(</span><span
class="n">beekeeperService</span><span class="o">.</span><span
class="na">ancestorsOfDroneAt</span><span class="o">(</span><span
class="n">generation</span><span class="o">));</span>
+ <span class="o">}</span>
+
+ <span class="nd">@RequestMapping</span><span class="o">(</span><span
class="n">value</span> <span class="o">=</span> <span
class="s">"/queen/ancestors/{generation}"</span><span class="o">,</span> <span
class="n">method</span> <span class="o">=</span> <span
class="n">GET</span><span class="o">,</span> <span class="n">produces</span>
<span class="o">=</span> <span
class="n">APPLICATION_JSON_UTF8_VALUE</span><span class="o">)</span>
+ <span class="nd">@ResponseBody</span>
+ <span class="kd">public</span> <span class="n">Ancestor</span> <span
class="nf">ancestorsOfQueen</span><span class="o">(</span><span
class="nd">@PathVariable</span> <span class="kt">int</span> <span
class="n">generation</span><span class="o">)</span> <span class="o">{</span>
+ <span class="n">logger</span><span class="o">.</span><span
class="na">info</span><span class="o">(</span>
+ <span class="s">"Received request to find the number of ancestors of
queen at generation {}"</span><span class="o">,</span>
+ <span class="n">generation</span><span class="o">);</span>
+
+ <span class="k">return</span> <span class="k">new</span> <span
class="nf">Ancestor</span><span class="o">(</span><span
class="n">beekeeperService</span><span class="o">.</span><span
class="na">ancestorsOfQueenAt</span><span class="o">(</span><span
class="n">generation</span><span class="o">));</span>
+ <span class="o">}</span>
+<span class="o">}</span>
+
+<span class="kd">class</span> <span class="nc">Ancestor</span> <span
class="o">{</span>
+ <span class="kd">private</span> <span class="kt">long</span> <span
class="n">ancestors</span><span class="o">;</span>
+
+ <span class="n">Ancestor</span><span class="o">()</span> <span
class="o">{</span>
+ <span class="o">}</span>
+
+ <span class="n">Ancestor</span><span class="o">(</span><span
class="kt">long</span> <span class="n">ancestors</span><span class="o">)</span>
<span class="o">{</span>
+ <span class="k">this</span><span class="o">.</span><span
class="na">ancestors</span> <span class="o">=</span> <span
class="n">ancestors</span><span class="o">;</span>
+ <span class="o">}</span>
+
+ <span class="kd">public</span> <span class="kt">long</span> <span
class="nf">getAncestors</span><span class="o">()</span> <span class="o">{</span>
+ <span class="k">return</span> <span class="n">ancestors</span><span
class="o">;</span>
+ <span class="o">}</span>
+<span class="o">}</span>
+</code></pre>
+</div>
+
+<p>å 为<strong>å
»è人</strong>éè¦æ¶è´¹<strong>æå·¥</strong>æä¾çæå¡ï¼æ以å
¶
<code class="highlighter-rouge">microservice.yaml</code> é
ç½®ç¨æä¸åï¼</p>
+
+<div class="language-yaml highlighter-rouge"><pre
class="highlight"><code><span class="c1"># all interconnected microservices
must belong to an application wth the same ID</span>
+<span class="s">APPLICATION_ID</span><span class="pi">:</span> <span
class="s">company</span>
+<span class="s">service_description</span><span class="pi">:</span>
+<span class="c1"># name of the declaring microservice</span>
+ <span class="s">name</span><span class="pi">:</span> <span
class="s">beekeeper</span>
+ <span class="s">version</span><span class="pi">:</span> <span
class="s">0.0.1</span>
+<span class="s">cse</span><span class="pi">:</span>
+ <span class="s">service</span><span class="pi">:</span>
+ <span class="s">registry</span><span class="pi">:</span>
+ <span class="s">address</span><span class="pi">:</span> <span
class="s">http://sc.servicecomb.io:30100</span>
+ <span class="s">rest</span><span class="pi">:</span>
+ <span class="s">address</span><span class="pi">:</span> <span
class="s">0.0.0.0:8090</span>
+ <span class="s">handler</span><span class="pi">:</span>
+ <span class="s">chain</span><span class="pi">:</span>
+ <span class="s">Consumer</span><span class="pi">:</span>
+ <span class="s">default</span><span class="pi">:</span> <span
class="s">bizkeeper-consumer,loadbalance</span>
+ <span class="s">references</span><span class="pi">:</span>
+<span class="c1"># this one below must refer to the microservice name it
communicates with</span>
+ <span class="s">worker</span><span class="pi">:</span>
+ <span class="s">version-rule</span><span class="pi">:</span> <span
class="s">0.0.1</span>
+</code></pre>
+</div>
+
+<p>è¿éæ们éè¦å®ä¹ <code
class="highlighter-rouge">cse.references.worker.version-rule</code> ï¼è®©é
ç½®å称ä¸æå<strong>æå·¥</strong>æå¡å <code
class="highlighter-rouge">worker</code> ï¼å¹¶å¹é
å
¶çæ¬å·ã</p>
+
+<p>æåå®ä¹å
»è人æå¡åºç¨å
¥å£ï¼</p>
+
+<div class="language-java highlighter-rouge"><pre
class="highlight"><code><span class="nd">@SpringBootApplication</span>
+<span class="nd">@EnableServiceComb</span>
+<span class="kd">public</span> <span class="kd">class</span> <span
class="nc">BeekeeperApplication</span> <span class="o">{</span>
+
+ <span class="kd">public</span> <span class="kd">static</span> <span
class="kt">void</span> <span class="nf">main</span><span
class="o">(</span><span class="n">String</span><span class="o">[]</span> <span
class="n">args</span><span class="o">)</span> <span class="o">{</span>
+ <span class="n">SpringApplication</span><span class="o">.</span><span
class="na">run</span><span class="o">(</span><span
class="n">BeekeeperApplication</span><span class="o">.</span><span
class="na">class</span><span class="o">,</span> <span
class="n">args</span><span class="o">);</span>
+ <span class="o">}</span>
+<span class="o">}</span>
+</code></pre>
+</div>
+
+<h2 id="é¨å«-doorman">é¨å« (Doorman)</h2>
+<p><strong>é¨å«</strong>为å
¬å¸æä¾å®å
¨ä¿éï¼å±è½éåæ³ç¨æ·ï¼é²æ¢å
¶éªåå
è´¹æå¡ï¼çè³ä¼¤å®³<strong>æå·¥</strong>å<strong>å
»è人</strong>ã</p>
+
+<h3 id="é¨å«è®¤è¯æå¡">é¨å«è®¤è¯æå¡</h3>
+<p>认è¯åè½æ们éç¨<a href="https://jwt.io/introduction/">JSON Web
Token (JWT)</a>çæºå¶ï¼å
·ä½å®ç°è¶
åºäºè¿ç¯æç« çèå´ï¼
+ç»è大家å¯ä»¥æ¥çgithubä¸<a
href="https://github.com/ServiceComb/LinuxCon-Beijing-WorkShop">workshop</a>ç
<code class="highlighter-rouge">doorman</code> 模å代ç ã</p>
+
+<p>认è¯æå¡çæ¥å£å¦ä¸ï¼<code
class="highlighter-rouge">authenticate</code> æ¹æ³æ ¹æ®ç¨æ·ååå¯ç
æ¥è¯¢ç¡®è®¤ç¨æ·åå¨ï¼å¹¶è¿å对åºJWT tokenãç¨æ·ç»å½åçæ¯æ¬¡
+请æ±é½éè¦å¸¦ä¸è¿åçJWT tokenï¼è <code
class="highlighter-rouge">validate</code> æ¹æ³å°éªè¯token以确认å
¶ææã</p>
+
+<div class="language-java highlighter-rouge"><pre
class="highlight"><code><span class="kd">public</span> <span
class="kd">interface</span> <span class="nc">AuthenticationService</span> <span
class="o">{</span>
+ <span class="n">String</span> <span class="nf">authenticate</span><span
class="o">(</span><span class="n">String</span> <span
class="n">username</span><span class="o">,</span> <span class="n">String</span>
<span class="n">password</span><span class="o">);</span>
+
+ <span class="n">String</span> <span class="nf">validate</span><span
class="o">(</span><span class="n">String</span> <span
class="n">token</span><span class="o">);</span>
+<span class="o">}</span>
+</code></pre>
+</div>
+
+<h3 id="é¨å«è®¤è¯æå¡ç«¯ç¹">é¨å«è®¤è¯æå¡ç«¯ç¹</h3>
+
+<p>ä¸å两èçRestæå¡ç«¯ç¹ç¸ä¼¼ï¼æ们å ä¸ <code
class="highlighter-rouge">@RestSchema</code> 注éï¼ä»¥ä¾¿ <code
class="highlighter-rouge">ServiceComb</code> èªå¨é
置端ç¹ãçæå¥çº¦å¹¶æ³¨åæå¡ã</p>
+
+<div class="language-java highlighter-rouge"><pre
class="highlight"><code><span class="nd">@RestSchema</span><span
class="o">(</span><span class="n">schemaId</span> <span class="o">=</span>
<span class="s">"authenticationRestEndpoint"</span><span class="o">)</span>
+<span class="nd">@Controller</span>
+<span class="nd">@RequestMapping</span><span class="o">(</span><span
class="s">"/rest"</span><span class="o">)</span>
+<span class="kd">public</span> <span class="kd">class</span> <span
class="nc">AuthenticationController</span> <span class="o">{</span>
+
+ <span class="kd">private</span> <span class="kd">static</span> <span
class="kd">final</span> <span class="n">Logger</span> <span
class="n">logger</span> <span class="o">=</span> <span
class="n">LoggerFactory</span><span class="o">.</span><span
class="na">getLogger</span><span class="o">(</span><span
class="n">AuthenticationController</span><span class="o">.</span><span
class="na">class</span><span class="o">);</span>
+
+ <span class="kd">static</span> <span class="kd">final</span> <span
class="n">String</span> <span class="n">USERNAME</span> <span
class="o">=</span> <span class="s">"username"</span><span class="o">;</span>
+ <span class="kd">static</span> <span class="kd">final</span> <span
class="n">String</span> <span class="n">PASSWORD</span> <span
class="o">=</span> <span class="s">"password"</span><span class="o">;</span>
+ <span class="kd">static</span> <span class="kd">final</span> <span
class="n">String</span> <span class="n">TOKEN</span> <span class="o">=</span>
<span class="s">"token"</span><span class="o">;</span>
+
+ <span class="kd">private</span> <span class="kd">final</span> <span
class="n">AuthenticationService</span> <span
class="n">authenticationService</span><span class="o">;</span>
+
+ <span class="nd">@Autowired</span>
+ <span class="n">AuthenticationController</span><span class="o">(</span><span
class="n">AuthenticationService</span> <span
class="n">authenticationService</span><span class="o">)</span> <span
class="o">{</span>
+ <span class="k">this</span><span class="o">.</span><span
class="na">authenticationService</span> <span class="o">=</span> <span
class="n">authenticationService</span><span class="o">;</span>
+ <span class="o">}</span>
+
+ <span class="nd">@RequestMapping</span><span class="o">(</span><span
class="n">value</span> <span class="o">=</span> <span
class="s">"/login"</span><span class="o">,</span> <span class="n">method</span>
<span class="o">=</span> <span class="n">POST</span><span class="o">,</span>
<span class="n">produces</span> <span class="o">=</span> <span
class="n">TEXT_PLAIN_VALUE</span><span class="o">)</span>
+ <span class="kd">public</span> <span class="n">ResponseEntity</span><span
class="o"><</span><span class="n">String</span><span class="o">></span>
<span class="nf">login</span><span class="o">(</span>
+ <span class="nd">@RequestParam</span><span class="o">(</span><span
class="n">USERNAME</span><span class="o">)</span> <span class="n">String</span>
<span class="n">username</span><span class="o">,</span>
+ <span class="nd">@RequestParam</span><span class="o">(</span><span
class="n">PASSWORD</span><span class="o">)</span> <span class="n">String</span>
<span class="n">password</span><span class="o">)</span> <span class="o">{</span>
+
+ <span class="n">logger</span><span class="o">.</span><span
class="na">info</span><span class="o">(</span><span class="s">"Received login
request from user {}"</span><span class="o">,</span> <span
class="n">username</span><span class="o">);</span>
+ <span class="n">String</span> <span class="n">token</span> <span
class="o">=</span> <span class="n">authenticationService</span><span
class="o">.</span><span class="na">authenticate</span><span
class="o">(</span><span class="n">username</span><span class="o">,</span> <span
class="n">password</span><span class="o">);</span>
+ <span class="n">HttpHeaders</span> <span class="n">headers</span> <span
class="o">=</span> <span class="k">new</span> <span
class="n">HttpHeaders</span><span class="o">();</span>
+ <span class="n">headers</span><span class="o">.</span><span
class="na">add</span><span class="o">(</span><span
class="n">AUTHORIZATION</span><span class="o">,</span> <span
class="n">TOKEN_PREFIX</span> <span class="o">+</span> <span
class="n">token</span><span class="o">);</span>
+
+ <span class="n">logger</span><span class="o">.</span><span
class="na">info</span><span class="o">(</span><span class="s">"Authenticated
user {} successfully"</span><span class="o">,</span> <span
class="n">username</span><span class="o">);</span>
+ <span class="k">return</span> <span class="k">new</span> <span
class="n">ResponseEntity</span><span class="o"><>(</span><span
class="s">"Welcome, "</span> <span class="o">+</span> <span
class="n">username</span><span class="o">,</span> <span
class="n">headers</span><span class="o">,</span> <span class="n">OK</span><span
class="o">);</span>
+ <span class="o">}</span>
+
+ <span class="nd">@RequestMapping</span><span class="o">(</span><span
class="n">value</span> <span class="o">=</span> <span
class="s">"/validate"</span><span class="o">,</span> <span
class="n">method</span> <span class="o">=</span> <span
class="n">POST</span><span class="o">,</span> <span class="n">consumes</span>
<span class="o">=</span> <span
class="n">APPLICATION_JSON_UTF8_VALUE</span><span class="o">,</span> <span
class="n">produces</span> <span class="o">=</span> <span
class="n">TEXT_PLAIN_VALUE</span><span class="o">)</span>
+ <span class="nd">@ResponseBody</span>
+ <span class="kd">public</span> <span class="n">String</span> <span
class="nf">validate</span><span class="o">(</span><span
class="nd">@RequestBody</span> <span class="n">Token</span> <span
class="n">token</span><span class="o">)</span> <span class="o">{</span>
+ <span class="n">logger</span><span class="o">.</span><span
class="na">info</span><span class="o">(</span><span class="s">"Received
validation request of token {}"</span><span class="o">,</span> <span
class="n">token</span><span class="o">);</span>
+ <span class="k">return</span> <span
class="n">authenticationService</span><span class="o">.</span><span
class="na">validate</span><span class="o">(</span><span
class="n">token</span><span class="o">.</span><span
class="na">getToken</span><span class="o">());</span>
+ <span class="o">}</span>
+<span class="o">}</span>
+
+<span class="kd">class</span> <span class="nc">Token</span> <span
class="o">{</span>
+ <span class="kd">private</span> <span class="n">String</span> <span
class="n">token</span><span class="o">;</span>
+
+ <span class="n">Token</span><span class="o">()</span> <span
class="o">{</span>
+ <span class="o">}</span>
+
+ <span class="n">Token</span><span class="o">(</span><span
class="n">String</span> <span class="n">token</span><span class="o">)</span>
<span class="o">{</span>
+ <span class="k">this</span><span class="o">.</span><span
class="na">token</span> <span class="o">=</span> <span
class="n">token</span><span class="o">;</span>
+ <span class="o">}</span>
+
+ <span class="kd">public</span> <span class="n">String</span> <span
class="nf">getToken</span><span class="o">()</span> <span class="o">{</span>
+ <span class="k">return</span> <span class="n">token</span><span
class="o">;</span>
+ <span class="o">}</span>
+
+ <span class="nd">@Override</span>
+ <span class="kd">public</span> <span class="n">String</span> <span
class="nf">toString</span><span class="o">()</span> <span class="o">{</span>
+ <span class="k">return</span> <span class="s">"Token{"</span> <span
class="o">+</span>
+ <span class="s">"token='"</span> <span class="o">+</span> <span
class="n">token</span> <span class="o">+</span> <span class="sc">'\''</span>
<span class="o">+</span>
+ <span class="sc">'}'</span><span class="o">;</span>
+ <span class="o">}</span>
+<span class="o">}</span>
+</code></pre>
+</div>
+
+<p>åæ ·ï¼æ们éè¦æä¾æå¡åºç¨å¯å¨å
¥å£ä»¥å <code
class="highlighter-rouge">microservice.yaml</code>ï¼</p>
+
+<div class="language-java highlighter-rouge"><pre
class="highlight"><code><span class="nd">@SpringBootApplication</span>
+<span class="nd">@EnableServiceComb</span>
+<span class="kd">public</span> <span class="kd">class</span> <span
class="nc">DoormanApplication</span> <span class="o">{</span>
+
+ <span class="kd">public</span> <span class="kd">static</span> <span
class="kt">void</span> <span class="nf">main</span><span
class="o">(</span><span class="n">String</span><span class="o">[]</span> <span
class="n">args</span><span class="o">)</span> <span class="o">{</span>
+ <span class="n">SpringApplication</span><span class="o">.</span><span
class="na">run</span><span class="o">(</span><span
class="n">DoormanApplication</span><span class="o">.</span><span
class="na">class</span><span class="o">,</span> <span
class="n">args</span><span class="o">);</span>
+ <span class="o">}</span>
+<span class="o">}</span>
+</code></pre>
+</div>
+
+<div class="language-yaml highlighter-rouge"><pre
class="highlight"><code><span class="c1"># all interconnected microservices
must belong to an application wth the same ID</span>
+<span class="s">APPLICATION_ID</span><span class="pi">:</span> <span
class="s">company</span>
+<span class="s">service_description</span><span class="pi">:</span>
+<span class="c1"># name of the declaring microservice</span>
+ <span class="s">name</span><span class="pi">:</span> <span
class="s">doorman</span>
+ <span class="s">version</span><span class="pi">:</span> <span
class="s">0.0.1</span>
+<span class="s">cse</span><span class="pi">:</span>
+ <span class="s">service</span><span class="pi">:</span>
+ <span class="s">registry</span><span class="pi">:</span>
+ <span class="s">address</span><span class="pi">:</span> <span
class="s">http://sc.servicecomb.io:30100</span>
+ <span class="s">rest</span><span class="pi">:</span>
+ <span class="s">address</span><span class="pi">:</span> <span
class="s">0.0.0.0:9090</span>
+</code></pre>
+</div>
+
+<h2 id="ç»ç-manager">ç»ç (Manager)</h2>
+<p>为äºç®¡çææ人åå设æ½ï¼<strong>ç»ç</strong>ä½ä¸ºç¨æ·å¯ä¸æ¥å£äººï¼ä¸»è¦åè½æï¼</p>
+
+<ul>
+ <li>
+
<p>èç³»<strong>é¨å«</strong>认è¯ç¨æ·ï¼ä¿æ¤<strong>æå·¥</strong>å<strong>å
»è人</strong>ï¼ä»¥å
éæ³ç¨æ·éªåæå¡å¹¶éé¿æå¡è´¹ç¨</p>
+ </li>
+ <li>
+ <p>èç³»è½åç¸ç¬¦ç<strong>æå·¥</strong>å<strong>å
»è人</strong>ï¼å¹³è¡¡å·¥ä½éï¼é¿å
å个人åå·¥ä½è¶
è½½</p>
+ </li>
+ <li>
+ <p>管ç<strong>项ç®å½æ¡£</strong>ï¼é¿å
éå¤å·¥ä½ï¼ä¿è¯å
¬å¸æ¶çæ大å</p>
+ </li>
+</ul>
+
+<p>ç±äº<strong>ç»ç</strong>责任é大ï¼æ们éåäºä¸çæåç<a
href="https://github.com/Netflix/zuul">Netflix Zuul</a>ä½ä¸ºåé人并å
以å¹è®ï¼
+æåå
¶è½åï¼ä»¥ä¿è¯å
¶è½è任该èä½ã</p>
+
+<p>é¦å
æ们å¼å
¥ä¾èµï¼</p>
+
+<div class="language-xml highlighter-rouge"><pre class="highlight"><code>
<span class="nt"><dependency></span>
+ <span class="nt"><groupId></span>io.servicecomb<span
class="nt"></groupId></span>
+ <span
class="nt"><artifactId></span>spring-boot-starter-discovery<span
class="nt"></artifactId></span>
+ <span class="nt"></dependency></span>
+</code></pre>
+</div>
+
+<h3 id="ç¨æ·è®¤è¯æå¡">ç¨æ·è®¤è¯æå¡</h3>
+<p>å½ç¨æ·åééç»å½è¯·æ±æ¶ï¼æ们é¦å
éè¦éªè¯ç¨æ·åæ³ï¼å¨å¦ä¸æå¡ä¸ï¼æ们éè¿<strong>å示æ
</strong>è·å<strong>é¨å«</strong>èç³»æ¹å¼ï¼
+ç¶ååéç¨æ·tokenç»<strong>é¨å«</strong>è¿è¡è®¤è¯ã</p>
+
+<p><code class="highlighter-rouge">ServiceComb</code> æä¾äºç¸åº <code
class="highlighter-rouge">RestTemplate</code> å®ç°æ¥è¯¢<a
href="https://github.com/ServiceComb/service-center">Service Center</a>
+ä¸çæå¡æ³¨åä¿¡æ¯ï¼åªéå¨å°åä¸ä»¥å¦ä¸æ ¼å¼å
å«è¢«è°ç¨çæå¡å</p>
+
+<div class="language-html highlighter-rouge"><pre
class="highlight"><code>cse://doorman/path/to/rest/endpoint
+</code></pre>
+</div>
+
+<p><code class="highlighter-rouge">ServiceComb</code>
å°èªå¨æ¥è¯¢å¯¹åºæå¡å¹¶åé请æ±å°å°åä¸çæå¡ç«¯ç¹ã</p>
+
+<div class="language-java highlighter-rouge"><pre
class="highlight"><code><span class="nd">@Service</span>
+<span class="kd">public</span> <span class="kd">class</span> <span
class="nc">AuthenticationService</span> <span class="o">{</span>
+
+ <span class="kd">private</span> <span class="kd">static</span> <span
class="kd">final</span> <span class="n">Logger</span> <span
class="n">logger</span> <span class="o">=</span> <span
class="n">LoggerFactory</span><span class="o">.</span><span
class="na">getLogger</span><span class="o">(</span><span
class="n">AuthenticationService</span><span class="o">.</span><span
class="na">class</span><span class="o">);</span>
+ <span class="kd">private</span> <span class="kd">static</span> <span
class="kd">final</span> <span class="n">String</span> <span
class="n">DOORMAN_ADDRESS</span> <span class="o">=</span> <span
class="s">"cse://doorman"</span><span class="o">;</span>
+
+ <span class="kd">private</span> <span class="kd">final</span> <span
class="n">RestTemplate</span> <span class="n">restTemplate</span><span
class="o">;</span>
+
+ <span class="n">AuthenticationService</span><span class="o">()</span> <span
class="o">{</span>
+ <span class="k">this</span><span class="o">.</span><span
class="na">restTemplate</span> <span class="o">=</span> <span
class="n">RestTemplateBuilder</span><span class="o">.</span><span
class="na">create</span><span class="o">();</span>
+
+ <span class="k">this</span><span class="o">.</span><span
class="na">restTemplate</span><span class="o">.</span><span
class="na">setErrorHandler</span><span class="o">(</span><span
class="k">new</span> <span class="n">ResponseErrorHandler</span><span
class="o">()</span> <span class="o">{</span>
+ <span class="nd">@Override</span>
+ <span class="kd">public</span> <span class="kt">boolean</span> <span
class="nf">hasError</span><span class="o">(</span><span
class="n">ClientHttpResponse</span> <span
class="n">clientHttpResponse</span><span class="o">)</span> <span
class="kd">throws</span> <span class="n">IOException</span> <span
class="o">{</span>
+ <span class="k">return</span> <span class="kc">false</span><span
class="o">;</span>
+ <span class="o">}</span>
+
+ <span class="nd">@Override</span>
+ <span class="kd">public</span> <span class="kt">void</span> <span
class="nf">handleError</span><span class="o">(</span><span
class="n">ClientHttpResponse</span> <span
class="n">clientHttpResponse</span><span class="o">)</span> <span
class="kd">throws</span> <span class="n">IOException</span> <span
class="o">{</span>
+ <span class="o">}</span>
+ <span class="o">});</span>
+ <span class="o">}</span>
+
+ <span class="nd">@HystrixCommand</span><span class="o">(</span><span
class="n">fallbackMethod</span> <span class="o">=</span> <span
class="s">"timeout"</span><span class="o">)</span>
+ <span class="kd">public</span> <span class="n">ResponseEntity</span><span
class="o"><</span><span class="n">String</span><span class="o">></span>
<span class="nf">validate</span><span class="o">(</span><span
class="n">String</span> <span class="n">token</span><span class="o">)</span>
<span class="o">{</span>
+ <span class="n">logger</span><span class="o">.</span><span
class="na">info</span><span class="o">(</span><span class="s">"Validating token
{}"</span><span class="o">,</span> <span class="n">token</span><span
class="o">);</span>
+ <span class="n">ResponseEntity</span><span class="o"><</span><span
class="n">String</span><span class="o">></span> <span
class="n">responseEntity</span> <span class="o">=</span> <span
class="n">restTemplate</span><span class="o">.</span><span
class="na">postForEntity</span><span class="o">(</span>
+ <span class="n">DOORMAN_ADDRESS</span> <span class="o">+</span> <span
class="s">"/rest/validate"</span><span class="o">,</span>
+ <span class="n">validationRequest</span><span class="o">(</span><span
class="n">token</span><span class="o">),</span>
+ <span class="n">String</span><span class="o">.</span><span
class="na">class</span>
+ <span class="o">);</span>
+
+ <span class="k">if</span> <span class="o">(!</span><span
class="n">responseEntity</span><span class="o">.</span><span
class="na">getStatusCode</span><span class="o">().</span><span
class="na">is2xxSuccessful</span><span class="o">())</span> <span
class="o">{</span>
+ <span class="n">logger</span><span class="o">.</span><span
class="na">warn</span><span class="o">(</span><span class="s">"No such user
found with token {}"</span><span class="o">,</span> <span
class="n">token</span><span class="o">);</span>
+ <span class="o">}</span>
+ <span class="n">logger</span><span class="o">.</span><span
class="na">info</span><span class="o">(</span><span class="s">"Validated
request of token {} to be user {}"</span><span class="o">,</span> <span
class="n">token</span><span class="o">,</span> <span
class="n">responseEntity</span><span class="o">.</span><span
class="na">getBody</span><span class="o">());</span>
+ <span class="k">return</span> <span class="n">responseEntity</span><span
class="o">;</span>
+ <span class="o">}</span>
+
+ <span class="kd">private</span> <span class="n">ResponseEntity</span><span
class="o"><</span><span class="n">String</span><span class="o">></span>
<span class="nf">timeout</span><span class="o">(</span><span
class="n">String</span> <span class="n">token</span><span class="o">)</span>
<span class="o">{</span>
+ <span class="n">logger</span><span class="o">.</span><span
class="na">warn</span><span class="o">(</span><span class="s">"Request to
validate token {} timed out"</span><span class="o">,</span> <span
class="n">token</span><span class="o">);</span>
+ <span class="k">return</span> <span class="k">new</span> <span
class="n">ResponseEntity</span><span class="o"><>(</span><span
class="n">REQUEST_TIMEOUT</span><span class="o">);</span>
+ <span class="o">}</span>
+
+ <span class="kd">private</span> <span class="n">HttpEntity</span><span
class="o"><</span><span class="n">Token</span><span class="o">></span>
<span class="nf">validationRequest</span><span class="o">(</span><span
class="n">String</span> <span class="n">token</span><span class="o">)</span>
<span class="o">{</span>
+ <span class="n">HttpHeaders</span> <span class="n">headers</span> <span
class="o">=</span> <span class="k">new</span> <span
class="n">HttpHeaders</span><span class="o">();</span>
+ <span class="n">headers</span><span class="o">.</span><span
class="na">setContentType</span><span class="o">(</span><span
class="n">MediaType</span><span class="o">.</span><span
class="na">APPLICATION_JSON_UTF8</span><span class="o">);</span>
+
+ <span class="k">return</span> <span class="k">new</span> <span
class="n">HttpEntity</span><span class="o"><>(</span><span
class="k">new</span> <span class="n">Token</span><span class="o">(</span><span
class="n">token</span><span class="o">),</span> <span
class="n">headers</span><span class="o">);</span>
+ <span class="o">}</span>
+<span class="o">}</span>
+</code></pre>
+</div>
+
+<h3 id="请æ±è¿æ»¤">请æ±è¿æ»¤</h3>
+<p>æ¥ä¸æ¥æ们æä¾ <code class="highlighter-rouge">ZuulFilter</code>
å®ç°è¿æ»¤ç¨æ·è¯·æ±ï¼è°ç¨ <code
class="highlighter-rouge">authenticationService.validate(token)</code>
认è¯ç¨æ·tokenã
+è¥ç¨æ·åæ³åè·¯ç±ç¨æ·è¯·æ±å°å¯¹åºæå¡ï¼å¦åè¿å <code
class="highlighter-rouge">403 forbidden</code>ã</p>
+
+<div class="language-java highlighter-rouge"><pre
class="highlight"><code><span class="nd">@Component</span>
+<span class="kd">class</span> <span
class="nc">AuthenticationAwareFilter</span> <span class="kd">extends</span>
<span class="n">ZuulFilter</span> <span class="o">{</span>
+
+ <span class="kd">private</span> <span class="kd">static</span> <span
class="kd">final</span> <span class="n">Logger</span> <span
class="n">logger</span> <span class="o">=</span> <span
class="n">LoggerFactory</span><span class="o">.</span><span
class="na">getLogger</span><span class="o">(</span><span
class="n">AuthenticationAwareFilter</span><span class="o">.</span><span
class="na">class</span><span class="o">);</span>
+
+ <span class="kd">private</span> <span class="kd">static</span> <span
class="kd">final</span> <span class="n">String</span> <span
class="n">LOGIN_PATH</span> <span class="o">=</span> <span
class="s">"/login"</span><span class="o">;</span>
+
+ <span class="kd">private</span> <span class="kd">final</span> <span
class="n">AuthenticationService</span> <span
class="n">authenticationService</span><span class="o">;</span>
+ <span class="kd">private</span> <span class="kd">final</span> <span
class="n">PathExtractor</span> <span class="n">pathExtractor</span><span
class="o">;</span>
+
+ <span class="nd">@Autowired</span>
+ <span class="n">AuthenticationAwareFilter</span><span class="o">(</span>
+ <span class="n">AuthenticationService</span> <span
class="n">authenticationService</span><span class="o">,</span>
+ <span class="n">PathExtractor</span> <span
class="n">pathExtractor</span><span class="o">)</span> <span class="o">{</span>
+
+ <span class="k">this</span><span class="o">.</span><span
class="na">authenticationService</span> <span class="o">=</span> <span
class="n">authenticationService</span><span class="o">;</span>
+ <span class="k">this</span><span class="o">.</span><span
class="na">pathExtractor</span> <span class="o">=</span> <span
class="n">pathExtractor</span><span class="o">;</span>
+ <span class="o">}</span>
+
+ <span class="nd">@Override</span>
+ <span class="kd">public</span> <span class="n">String</span> <span
class="nf">filterType</span><span class="o">()</span> <span class="o">{</span>
+ <span class="k">return</span> <span class="s">"pre"</span><span
class="o">;</span>
+ <span class="o">}</span>
+
+ <span class="nd">@Override</span>
+ <span class="kd">public</span> <span class="kt">int</span> <span
class="nf">filterOrder</span><span class="o">()</span> <span class="o">{</span>
+ <span class="k">return</span> <span class="mi">1</span><span
class="o">;</span>
+ <span class="o">}</span>
+
+ <span class="nd">@Override</span>
+ <span class="kd">public</span> <span class="kt">boolean</span> <span
class="nf">shouldFilter</span><span class="o">()</span> <span class="o">{</span>
+ <span class="n">String</span> <span class="n">path</span> <span
class="o">=</span> <span class="n">pathExtractor</span><span
class="o">.</span><span class="na">path</span><span class="o">(</span><span
class="n">RequestContext</span><span class="o">.</span><span
class="na">getCurrentContext</span><span class="o">());</span>
+ <span class="n">logger</span><span class="o">.</span><span
class="na">info</span><span class="o">(</span><span class="s">"Received request
with query path: {}"</span><span class="o">,</span> <span
class="n">path</span><span class="o">);</span>
+ <span class="k">return</span> <span class="o">!</span><span
class="n">path</span><span class="o">.</span><span
class="na">endsWith</span><span class="o">(</span><span
class="n">LOGIN_PATH</span><span class="o">);</span>
+ <span class="o">}</span>
+
+ <span class="nd">@Override</span>
+ <span class="kd">public</span> <span class="n">Object</span> <span
class="nf">run</span><span class="o">()</span> <span class="o">{</span>
+ <span class="n">filter</span><span class="o">();</span>
+ <span class="k">return</span> <span class="kc">null</span><span
class="o">;</span>
+ <span class="o">}</span>
+
+ <span class="kd">private</span> <span class="kt">void</span> <span
class="nf">filter</span><span class="o">()</span> <span class="o">{</span>
+ <span class="n">RequestContext</span> <span class="n">context</span> <span
class="o">=</span> <span class="n">RequestContext</span><span
class="o">.</span><span class="na">getCurrentContext</span><span
class="o">();</span>
+
+ <span class="k">if</span> <span class="o">(</span><span
class="n">doesNotContainToken</span><span class="o">(</span><span
class="n">context</span><span class="o">))</span> <span class="o">{</span>
+ <span class="n">logger</span><span class="o">.</span><span
class="na">warn</span><span class="o">(</span><span class="s">"No token found
in request header"</span><span class="o">);</span>
+ <span class="n">rejectRequest</span><span class="o">(</span><span
class="n">context</span><span class="o">);</span>
+ <span class="o">}</span> <span class="k">else</span> <span
class="o">{</span>
+ <span class="n">String</span> <span class="n">token</span> <span
class="o">=</span> <span class="n">token</span><span class="o">(</span><span
class="n">context</span><span class="o">);</span>
+ <span class="n">ResponseEntity</span><span class="o"><</span><span
class="n">String</span><span class="o">></span> <span
class="n">responseEntity</span> <span class="o">=</span> <span
class="n">authenticationService</span><span class="o">.</span><span
class="na">validate</span><span class="o">(</span><span
class="n">token</span><span class="o">);</span>
+ <span class="k">if</span> <span class="o">(!</span><span
class="n">responseEntity</span><span class="o">.</span><span
class="na">getStatusCode</span><span class="o">().</span><span
class="na">is2xxSuccessful</span><span class="o">())</span> <span
class="o">{</span>
+ <span class="n">logger</span><span class="o">.</span><span
class="na">warn</span><span class="o">(</span><span class="s">"Unauthorized
token {} and request rejected"</span><span class="o">,</span> <span
class="n">token</span><span class="o">);</span>
+ <span class="n">rejectRequest</span><span class="o">(</span><span
class="n">context</span><span class="o">);</span>
+ <span class="o">}</span> <span class="k">else</span> <span
class="o">{</span>
+ <span class="n">logger</span><span class="o">.</span><span
class="na">info</span><span class="o">(</span><span class="s">"Token {}
validated"</span><span class="o">,</span> <span class="n">token</span><span
class="o">);</span>
+ <span class="o">}</span>
+ <span class="o">}</span>
+ <span class="o">}</span>
+
+ <span class="kd">private</span> <span class="kt">void</span> <span
class="nf">rejectRequest</span><span class="o">(</span><span
class="n">RequestContext</span> <span class="n">context</span><span
class="o">)</span> <span class="o">{</span>
+ <span class="n">context</span><span class="o">.</span><span
class="na">setResponseStatusCode</span><span class="o">(</span><span
class="n">SC_FORBIDDEN</span><span class="o">);</span>
+ <span class="n">context</span><span class="o">.</span><span
class="na">setSendZuulResponse</span><span class="o">(</span><span
class="kc">false</span><span class="o">);</span>
+ <span class="o">}</span>
+
+ <span class="kd">private</span> <span class="kt">boolean</span> <span
class="nf">doesNotContainToken</span><span class="o">(</span><span
class="n">RequestContext</span> <span class="n">context</span><span
class="o">)</span> <span class="o">{</span>
+ <span class="k">return</span> <span
class="nf">authorizationHeader</span><span class="o">(</span><span
class="n">context</span><span class="o">)</span> <span class="o">==</span>
<span class="kc">null</span>
+ <span class="o">||</span> <span class="o">!</span><span
class="n">authorizationHeader</span><span class="o">(</span><span
class="n">context</span><span class="o">).</span><span
class="na">startsWith</span><span class="o">(</span><span
class="n">TOKEN_PREFIX</span><span class="o">);</span>
+ <span class="o">}</span>
+
+ <span class="kd">private</span> <span class="n">String</span> <span
class="nf">token</span><span class="o">(</span><span
class="n">RequestContext</span> <span class="n">context</span><span
class="o">)</span> <span class="o">{</span>
+ <span class="k">return</span> <span
class="nf">authorizationHeader</span><span class="o">(</span><span
class="n">context</span><span class="o">).</span><span
class="na">replace</span><span class="o">(</span><span
class="n">TOKEN_PREFIX</span><span class="o">,</span> <span
class="s">""</span><span class="o">);</span>
+ <span class="o">}</span>
+
+ <span class="kd">private</span> <span class="n">String</span> <span
class="nf">authorizationHeader</span><span class="o">(</span><span
class="n">RequestContext</span> <span class="n">context</span><span
class="o">)</span> <span class="o">{</span>
+ <span class="k">return</span> <span class="n">context</span><span
class="o">.</span><span class="na">getRequest</span><span
class="o">().</span><span class="na">getHeader</span><span
class="o">(</span><span class="n">AUTHORIZATION</span><span class="o">);</span>
+ <span class="o">}</span>
+<span class="o">}</span>
+</code></pre>
+</div>
+
+<p>æåæä¾æå¡åºç¨å
¥å£ï¼</p>
+
+<div class="language-java highlighter-rouge"><pre
class="highlight"><code><span class="nd">@SpringBootApplication</span>
+<span class="nd">@EnableCircuitBreaker</span>
+<span class="nd">@EnableZuulProxy</span>
+<span class="nd">@EnableDiscoveryClient</span>
+<span class="nd">@EnableServiceComb</span>
+<span class="kd">public</span> <span class="kd">class</span> <span
class="nc">ManagerApplication</span> <span class="o">{</span>
+
+ <span class="kd">public</span> <span class="kd">static</span> <span
class="kt">void</span> <span class="nf">main</span><span
class="o">(</span><span class="n">String</span><span class="o">[]</span> <span
class="n">args</span><span class="o">)</span> <span class="o">{</span>
+ <span class="n">SpringApplication</span><span class="o">.</span><span
class="na">run</span><span class="o">(</span><span
class="n">ManagerApplication</span><span class="o">.</span><span
class="na">class</span><span class="o">,</span> <span
class="n">args</span><span class="o">);</span>
+ <span class="o">}</span>
+<span class="o">}</span>
+</code></pre>
+</div>
+
+<p><code class="highlighter-rouge">application.yaml</code>
ä¸å®ä¹è·¯ç±è§åï¼</p>
+
+<div class="language-yaml highlighter-rouge"><pre
class="highlight"><code><span class="s">zuul</span><span class="pi">:</span>
+ <span class="s">routes</span><span class="pi">:</span>
+ <span class="s">doorman</span><span class="pi">:</span>
+ <span class="s">serviceId</span><span class="pi">:</span> <span
class="s">doorman</span>
+ <span class="s">sensitiveHeaders</span><span class="pi">:</span>
+ <span class="s">worker</span><span class="pi">:</span>
+ <span class="s">serviceId</span><span class="pi">:</span> <span
class="s">worker</span>
+ <span class="s">beekeeper</span><span class="pi">:</span>
+ <span class="s">serviceId</span><span class="pi">:</span> <span
class="s">beekeeper</span>
+
+<span class="c1"># disable netflix eurkea since it's not used for service
discovery</span>
+<span class="s">ribbon</span><span class="pi">:</span>
+ <span class="s">eureka</span><span class="pi">:</span>
+ <span class="s">enabled</span><span class="pi">:</span> <span
class="s">false</span>
+</code></pre>
+</div>
+
+<p><code class="highlighter-rouge">microservice.yaml</code>
ä¸å®ä¹æå¡ä¸å¿å°åï¼</p>
+
+<div class="language-yaml highlighter-rouge"><pre
class="highlight"><code><span class="s">APPLICATION_ID</span><span
class="pi">:</span> <span class="s">company</span>
+<span class="s">service_description</span><span class="pi">:</span>
+ <span class="s">name</span><span class="pi">:</span> <span
class="s">manager</span>
+ <span class="s">version</span><span class="pi">:</span> <span
class="s">0.0.1</span>
+<span class="s">cse</span><span class="pi">:</span>
+ <span class="s">service</span><span class="pi">:</span>
+ <span class="s">registry</span><span class="pi">:</span>
+ <span class="s">address</span><span class="pi">:</span> <span
class="s">http://sc.servicecomb.io:30100</span>
+</code></pre>
+</div>
+
+<h2 id="项ç®å½æ¡£-project-archive">项ç®å½æ¡£ (Project Archive)</h2>
+<p><strong>ç»ç</strong>å¨æ¯æ¬¡ç¨æ·è¯·æ±åå°é¡¹ç®è¿è¡å½æ¡£ï¼å¦æå°æ¥æå
容ç¸åç请æ±å°è¾¾ï¼<strong>ç»ç</strong>å¯ä»¥å°±è¿è·åç»æï¼ä¸å¿
åè´ä¹°
+<strong>æå·¥</strong>å<strong>å
»è人</strong>æä¾ç计ç®æå¡ï¼èçå
¬å¸å¼æ¯ã</p>
+
+<p>对äºå½æ¡£åè½çå®ç°ï¼æ们éç¨äº<strong>Spring Cache
Abstraction</strong>ï¼å
·ä½ç»èè¶
åºäºè¿ç¯æç«
çèå´ï¼å¤§å®¶å¦ææå
´è¶£å¯ä»¥
+æ¥çgithubä¸<a
href="https://github.com/ServiceComb/LinuxCon-Beijing-WorkShop">workshop</a>ç
<code class="highlighter-rouge">manager</code> 模å代ç ã</p>
+
+<h2 id="人åèµæº-human-resource">人åèµæº (Human Resource)</h2>
+
+<p><strong>人åèµæº</strong>ä»è¿ç»´å±é¢ä¿è¯æå¡çå¯é
æ§ï¼ä¸»è¦åè½æ</p>
+
+<ul>
+ <li>
+ <p>å¼¹æ§ä¼¸ç¼©ï¼ä»¥ä¿è¯ç¨æ·è¯·æ±éè¶
è¿<strong>æå·¥</strong>æ<strong>å
»è人</strong>å¤çè½ååï¼æèæ´å¤<strong>æå·¥</strong>æ<strong>å
»è人</strong>å å
¥é¡¹ç®ï¼å½è¯·æ±éåè½åï¼è£åª<strong>æå·¥</strong>æ<strong>å
»è人</strong>以èçå
¬å¸å¼æ¯</p>
+ </li>
+ <li>
+ <p>å¥åº·æ£æ¥ï¼ä»¥ä¿è¯<strong>æå·¥</strong>æ<strong>å
»è人</strong>åç
æ¶ï¼è½ææ¿è¡¥æ¥æä»»å¡</p>
+ </li>
+ <li>
+
<p>æ»å¨å级ï¼ä»¥ä¿è¯é¡¹ç®éè¦æ°æè½æ¶ï¼è½æ¿æ¢ãå¹è®<strong>æå·¥</strong>æ<strong>å
»è人</strong>ï¼ä¸ä¸ææ¥æ¶ç¨æ·è¯·æ±</p>
+ </li>
+</ul>
+
+<p><strong>人åèµæº</strong>çåè½éè¦äºå¹³å°æä¾æ¯æï¼å¨åç»çæç«
ä¸ä¼è·å¤§å®¶ä»ç»ï¼æ们å¦ä½å¨å为äºä¸è½»æ¾å®ç°è¿äºåè½ã</p>
+
+<h2 id="æ»ç»">æ»ç»</h2>
+<p>å¨è¿ç¯æç« ä¸ï¼æ们ç¨ä¸ä¸ªå
¬å¸çç»ç»ç»æä½ä¸ºä¾åï¼ç»å¤§å®¶ä»ç»äºå¾®æå¡çå®æ´æ¶æï¼ä»¥åå¦ä½ä½¿ç¨å¾®æå¡æ¡æ¶
<code class="highlighter-rouge">ServiceComb</code>
+å¿«éå¼åå¾®æå¡ï¼ä»¥åæå¡é´äºéãå¥çº¦è®¤è¯ã</p>
+
+<p><a href="https://github.com/ServiceComb/LinuxCon-Beijing-WorkShop">Workshop
demo</a>项ç®ä¹å
å«å¤§éå®æ´ææçæµè¯
+代ç
ï¼ä»¥å使ç¨dockeréæå¾®æå¡ï¼æ¨¡æçåç¯å¢ï¼åæ¶åºç¨<a
href="https://travis-ci.org/">Travis</a>æ建æç»éæç¯å¢ï¼ä½ç°
+DevOpså¨å¾®æå¡å¼åä¸çå®è·µãå¸æè½å¯¹å¤§å®¶ææ帮å©ã</p>
+
+
+ </section>
+
+ <footer class="page__meta">
+
+
+
+
+
+
+
+
+
+ <p class="page__taxonomy">
+ <strong><i class="fa fa-fw fa-tags" aria-hidden="true"></i> Tags: </strong>
+ <span itemprop="keywords">
+
+
+
+ <a href="/tags/#demo" class="page__taxonomy-item" rel="tag">demo</a>
+
+ </span>
+ </p>
+
+
+
+
+
+
+
+
+ <p class="page__date"><strong><i class="fa fa-fw fa-calendar"
aria-hidden="true"></i> Updated:</strong> <time datetime="2017-06-15">June 15,
2017</time></p>
+
+
+
+ </footer>
+
+ <section class="page__share">
+
+ <h4 class="page__share-title">Share on</h4>
+
+
+ <a href="https://twitter.com/intent/tweet?via=ServiceComb&text=Linux Con
Workshop Demo /docs/linuxcon-workshop-demo/" class="btn btn--twitter"
title="Share on Twitter"><i class="fa fa-fw fa-twitter"
aria-hidden="true"></i><span> Twitter</span></a>
+
+ <a
href="https://www.facebook.com/sharer/sharer.php?u=/docs/linuxcon-workshop-demo/"
class="btn btn--facebook" title="Share on Facebook"><i class="fa fa-fw
fa-facebook" aria-hidden="true"></i><span> Facebook</span></a>
+
+ <a href="https://plus.google.com/share?url=/docs/linuxcon-workshop-demo/"
class="btn btn--google-plus" title="Share on Google Plus"><i class="fa fa-fw
fa-google-plus" aria-hidden="true"></i><span> Google+</span></a>
+
+ <a
href="https://www.linkedin.com/shareArticle?mini=true&url=/docs/linuxcon-workshop-demo/"
class="btn btn--linkedin" title="Share on LinkedIn"><i class="fa fa-fw
fa-linkedin" aria-hidden="true"></i><span> LinkedIn</span></a>
+</section>
+
+
+
+ <nav class="pagination">
+
+ <a href="#" class="pagination--pager disabled">Previous</a>
+
+
+ <a href="/cn/docs/linuxcon-workshop-demo/" class="pagination--pager"
title="Linux Con Workshop Demo
+">Next</a>
+
+ </nav>
+
+
+ </div>
+
+
+ <div class="page__comments">
+
+
+ <section id="static-comments">
+
+ <!-- Start static comments -->
+ <div class="js-comments">
+
+ </div>
+ <!-- End static comments -->
+
+ <!-- Start new comment form -->
+ <h4 class="page__comments-title">Leave a Comment</h4>
+ <p class="small">Your email address will not be published. Required
fields are marked <span class="required">*</span></p>
+ <form id="new_comment" class="page__comments-form js-form form"
method="post"
action="https://api.staticman.net/v1/entry/ServiceComb/servicesomb.github.io/master">
+ <div class="form__spinner">
+ <i class="fa fa-spinner fa-spin fa-3x fa-fw"></i>
+ <span class="sr-only">Loading...</span>
+ </div>
+
+ <fieldset>
+ <label for="comment-form-message">Comment <small
class="required">*</small></label>
+ <textarea type="text" rows="3" id="comment-form-message"
name="fields[message]" tabindex="1"></textarea>
+ <div class="small help-block"><a
href="https://daringfireball.net/projects/markdown/">Markdown is
supported.</a></div>
+ </fieldset>
+ <fieldset>
+ <label for="comment-form-name">Name <small
class="required">*</small></label>
+ <input type="text" id="comment-form-name" name="fields[name]"
tabindex="2" />
+ </fieldset>
+ <fieldset>
+ <label for="comment-form-email">Email address <small
class="required">*</small></label>
+ <input type="email" id="comment-form-email" name="fields[email]"
tabindex="3" />
+ </fieldset>
+ <fieldset>
+ <label for="comment-form-url">Website (optional)</label>
+ <input type="url" id="comment-form-url" name="fields[url]"
tabindex="4"/>
+ </fieldset>
+ <fieldset class="hidden" style="display: none;">
+ <input type="hidden" name="options[slug]"
value="linuxcon-workshop-demo">
+ <label for="comment-form-location">Not used. Leave blank if you
are a human.</label>
+ <input type="text" id="comment-form-location"
name="fields[hidden]" autocomplete="off"/>
+ </fieldset>
+ <!-- Start comment form alert messaging -->
+ <p class="hidden js-notice">
+ <strong class="js-notice-text"></strong>
+ </p>
+ <!-- End comment form alert messaging -->
+ <fieldset>
+ <button type="submit" id="comment-form-submit" tabindex="5"
class="btn btn--large">Submit Comment</button>
+ </fieldset>
+ </form>
+ <!-- End new comment form -->
+
+ </section>
+
+</div>
+
+
+ </article>
+
+
+
+ <div class="page__related">
+ <h4 class="page__related-title">You May Also Enjoy</h4>
+ <div class="grid__wrapper">
+
+
+
+
+
+<div class="grid__item">
+ <article class="archive__item" itemscope
itemtype="http://schema.org/CreativeWork">
+
+ <h2 class="archive__item-title" itemprop="headline">
+
+ <a href="/cn/docs/jira_beginner_guide/" rel="permalink">èå¸æºå¸¦ä½
å·ä»»å¡ - ServiceComb JIRAå
¥é¨æå
+</a>
+
+ </h2>
+ <p class="archive__item-excerpt" itemprop="description">ServiceComb JIRAå
¥é¨æå
+</p>
+
+ <p class="page__meta"><i class="fa fa-clock-o" aria-hidden="true"></i>
+
+
+
+
+ less than 1 minute read
+
+</p>
+
+ </article>
+</div>
+
+
+
+
+
+
+<div class="grid__item">
+ <article class="archive__item" itemscope
itemtype="http://schema.org/CreativeWork">
+
+ <h2 class="archive__item-title" itemprop="headline">
+
+ <a href="/docs/service-center-ui/" rel="permalink">Service-Center
Management UI Console
+</a>
+
+ </h2>
+ <p class="archive__item-excerpt" itemprop="description">An introduction
Service-Center Management Console
+</p>
+
+ <p class="page__meta"><i class="fa fa-clock-o" aria-hidden="true"></i>
+
+
+
+
+ 2 minute read
+
+</p>
+
+ </article>
+</div>
+
+
+
+
+
+
+<div class="grid__item">
+ <article class="archive__item" itemscope
itemtype="http://schema.org/CreativeWork">
+
+ <h2 class="archive__item-title" itemprop="headline">
+
+ <a href="/docs/service-center-ui/" rel="permalink">Service-Center
Management UI Console
+</a>
+
+ </h2>
+ <p class="archive__item-excerpt" itemprop="description">An introduction
Service-Center Management Console
+</p>
+
+ <p class="page__meta"><i class="fa fa-clock-o" aria-hidden="true"></i>
+
+
+
+
+ 2 minute read
+
+</p>
+
+ </article>
+</div>
+
+
+
+
+
+
+<div class="grid__item">
+ <article class="archive__item" itemscope
itemtype="http://schema.org/CreativeWork">
+
+ <h2 class="archive__item-title" itemprop="headline">
+
+ <a href="/cn/docs/how-to-reform-a-legacy-system/"
rel="permalink">æ头ç¼çéçç³»ç»è¯¥å¦ä½æ¹é ï¼
+</a>
+
+ </h2>
+ <p class="archive__item-excerpt"
itemprop="description">å¾®æå¡æ¯å¦æ¯ä¸çæå¾
å·²ä¹
çä¼ä¸æ¶æ解å³æ¹æ¡ï¼å¨å¯¹éçç³»ç»è¿è¡å¾®æå¡çæ¹é
è¿ç¨ä¸åå¨ææ ·çå°é¾åææï¼åºè¯¥æ³¨æäºä»ä¹ï¼
+</p>
+
+ <p class="page__meta"><i class="fa fa-clock-o" aria-hidden="true"></i>
+
+
+
+
+ 1 minute read
+
+</p>
+
+ </article>
+</div>
+
+
+ </div>
+ </div>
+
+</div>
+
+
+ <script async
src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
+ <div align="center" style="margin: 0 0;">
+ <ins class="adsbygoogle"
+ style="display:block; border-bottom: initial;"
+ data-ad-client="ca-pub-7328585512091257"
+ data-ad-slot="3049671934"
+ data-ad-format="auto"></ins>
+ </div>
+
+ <div class="page__footer">
+ <footer>
+ <!-- start custom footer snippets -->
+
+<!-- end custom footer snippets -->
+ <div class="container">
+ <div class="row justify-content-md-center">
+
+ <div class="col">
+ <ul>
+ <p class="header">Resources</p>
+ <li><a href="/docs/quick-start/">Quick Start</a></li>
+ <li><a href="/users/user-guide/">User Guide</a></li>
+ <li><a href="/slides/">Slides</a></li>
+ <li><a href="/users/faq/">Common Questions</a></li>
+ </ul>
+ </div>
+ <div class="col">
+ <ul>
+ <p class="header">Contribute</p>
+ <li><a
href="https://github.com/ServiceComb/ServiceComb.github.io/issues/new?title=Issue
with _posts/2017-06-15-linuxcon-workshop-demo.md">Report a Doc Issue</a></li>
+ <li><a
href="https://github.com/ServiceComb/ServiceComb.github.io/edit/master/_posts/2017-06-15-linuxcon-workshop-demo.md">Edit
This Page on Github</a></li>
+ <li><a href="/developers/submit-codes/">Code Submit Guide</a></li>
+ </ul>
+ </div>
+ <div class="col">
+ <ul class="social-icons">
+ <p class="header">Community</p>
+ <li>
+ <a
href="https://groups.google.com/forum/#!forum/servicecomb-developers"
target="_blank"><span class="group">Dev</span></a> |
+ <a
href="https://groups.google.com/forum/#!forum/servicecomb-users"
target="_blank">User</span></a>
+ </li>
+ <li>
+ <a href="http://github.com/ServiceComb" target="_blank"><span
class="github">Github</span></a>
+ </li>
+ <li>
+ <a href="https://twitter.com/ServiceComb" target="_blank"><span
class="twitter">Twitter</span></a>
+ </li>
+ <li>
+ <a href="/feed.xml" target="_blank"><span
class="rss">Feed</span></a>
+ </li>
+ </ul>
+ </div>
+ </div>
+</div>
+<div class="page__footer-bottom">
+ <div>© 2017 Apache incubator ServiceComb. Powered by <a
href="http://jekyllrb.com" rel="nofollow">Jekyll</a> & <a
href="https://mademistakes.com/work/minimal-mistakes-jekyll-theme/"
rel="nofollow">Minimal Mistakes</a>.</div>
+</div>
+
+ </footer>
+ </div>
+
+ <script src="/assets/js/main.min.js"></script>
+
+
+
+
+ <script>
+ (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new
Date();a=s.createElement(o),
+
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
+
+ ga('create', 'UA-101622733-1', 'auto');
+ ga('send', 'pageview');
+</script>
+
+
+
+
+
+
+
+
+ <script>
+ (function ($) {
+ var $comments = $('.js-comments');
+
+ $('#new_comment').submit(function () {
+ var form = this;
+
+ $(form).addClass('disabled');
+ $('#comment-form-submit').html('<i class="fa fa-spinner fa-spin
fa-fw"></i> Loading...');
+
+ $.ajax({
+ type: $(this).attr('method'),
+ url: $(this).attr('action'),
+ data: $(this).serialize(),
+ contentType: 'application/x-www-form-urlencoded',
+ success: function (data) {
+ $('#comment-form-submit').html('Submitted');
+ $('.page__comments-form .js-notice').removeClass('notice--danger');
+ $('.page__comments-form .js-notice').addClass('notice--success');
+ showAlert('Thanks for your comment! It will show on the site once it
has been approved.');
+ },
+ error: function (err) {
+ console.log(err);
+ $('#comment-form-submit').html('Submit Comment');
+ $('.page__comments-form .js-notice').removeClass('notice--success');
+ $('.page__comments-form .js-notice').addClass('notice--danger');
+ showAlert('Sorry, there was an error with your submission. Please
make sure all required fields have been completed and try again.');
+ $(form).removeClass('disabled');
+ }
+ });
+
+ return false;
+ });
+
+ function showAlert(message) {
+ $('.page__comments-form .js-notice').removeClass('hidden');
+ $('.page__comments-form .js-notice-text').html(message);
+ }
+ })(jQuery);
+ </script>
+
+
+
+
+
+
+
+ </body>
+</html>