blob: 27eeebfbaad614aec61ecd26a3dd88ab02d78d08 [file] [log] [blame]
<!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>SecKill Develop Journey (II) - Apache ServiceComb</title>
<meta name="description" content="an introduction how to build seckill demo project step by step">
<meta name="author" content="Yangyong Zheng">
<meta property="og:locale" content="en">
<meta property="og:site_name" content="Apache ServiceComb">
<meta property="og:title" content="SecKill Develop Journey (II)">
<link rel="canonical" href="https://github.com/pages/apache/incubator-servicecomb-website/docs/seckill-development-journey-part-II/">
<meta property="og:url" content="https://github.com/pages/apache/incubator-servicecomb-website/docs/seckill-development-journey-part-II/">
<meta property="og:description" content="an introduction how to build seckill demo project step by step">
<meta name="twitter:site" content="@ServiceComb">
<meta name="twitter:title" content="SecKill Develop Journey (II)">
<meta name="twitter:description" content="an introduction how to build seckill demo project step by step">
<meta name="twitter:url" content="">
<meta name="twitter:card" content="summary">
<meta name="twitter:creator" content="@">
<meta property="og:type" content="article">
<meta property="article:published_time" content="2017-08-30T00:00:00+08:00">
<script type="application/ld+json">
{
"@context" : "http://schema.org",
"@type" : "Person",
"name" : "Apache ServiceComb",
"url" : "https://github.com/pages/apache/incubator-servicecomb-website",
"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 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/vendor/prism/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?v=1">
<link rel="stylesheet" href="/assets/vendor/prism/prism.css?v=1">
<!--[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" onmouseleave="$('#childrenShow').css('display', 'none')">
<div class="masthead__inner-wrap">
<div class="masthead__menu">
<nav id="site-nav" class="greedy-nav">
<a class="site-title active" href="/"><img src="https://www.apache.org/img/servicecomb.png"></a>
<ul class="visible-links">
<li class="masthead__menu-item" onmouseenter="$('#childrenShow').css('display', 'none')">
<a href="/">Home</a>
</li>
<li class="masthead__menu-item" onmouseenter="$('#childrenShow').css('display', 'none')">
<a href="/developers/">Projects</a>
</li>
<li class="def-nav-li" onmouseenter="$('#childrenShow').css('display', 'block')">
<a href="/docs/users/">Documentation</a>
<ul id="childrenShow" class="def-children-show-en" onmouseleave="$('#childrenShow').css('display', 'none')">
<li><a href="/docs/getting-started/" class="">Getting started</a></li>
<li><a href="/docs/users/" class="">Docs</a></li>
<li><a href="/slides/" class="">Video</a></li>
<li><a href="/faqs/" class="">FAQ</a></li>
</ul>
</li>
<li class="masthead__menu-item" onmouseenter="$('#childrenShow').css('display', 'none')">
<a href="/developers/contributing">Community</a>
</li>
<li class="masthead__menu-item" onmouseenter="$('#childrenShow').css('display', 'none')">
<a href="/year-archive/">Blogs</a>
</li>
<li class="masthead__menu-item" onmouseenter="$('#childrenShow').css('display', 'none')">
<a href="/release/">Downloads</a>
</li>
</ul>
<button><div class="navicon"></div></button>
<ul class="hidden-links hidden"></ul>
<div class="nav-lang">
<a href=/cn/docs/seckill-development-journey-part-II/>中文</a>
</div>
</nav>
</div>
</div>
</div>
<div id="main" role="main">
<div class="sidebar sticky">
<div class="back-to-home"><a href="/">Home</a> > SecKill Develop Journey (II)</div>
<div itemscope itemtype="http://schema.org/Person">
<div class="author__content">
<h3 class="author__name" itemprop="name">Yangyong Zheng</h3>
<p class="author__bio" itemprop="description">
Fast Action, do not ask
</p>
</div>
<div class="author__urls-wrapper">
<button class="btn btn--inverse">Follow</button>
<ul class="author__urls social-icons">
<li>
<a href="https://zhengyangyong.github.io" itemprop="url">
<i class="fa fa-fw fa-chain" aria-hidden="true"></i> Website
</a>
</li>
<li>
<a href="mailto:yangyong.zheng@huawei.com">
<meta itemprop="email" content="yangyong.zheng@huawei.com" />
<i class="fa fa-fw fa-envelope-square" aria-hidden="true"></i> Email
</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="SecKill Develop Journey (II)">
<meta itemprop="description" content="an introduction how to build seckill demo project step by step">
<meta itemprop="datePublished" content="August 30, 2017">
<meta itemprop="dateModified" content="September 13, 2017">
<div class="page__inner-wrap">
<header>
<h1 class="page__title" itemprop="headline">SecKill Develop Journey (II)
</h1>
<p class="page__meta"><i class="fa fa-clock-o" aria-hidden="true"></i>
1 minute read
</p>
</header>
<section class="page__content" itemprop="text">
<p><a href="/docs/seckill-development-journey-part/">Previous article</a> We only built a core function seckill demo, this article we will gradually improve more features in order to let it had complete function.</p>
<h2 id="problems">Problems</h2>
<p>Review what we has been done, we can find that:</p>
<ol>
<li>Service for Promotion entity is not provided (inject by Spring);</li>
<li>Lack some base check and features, include:
<ul>
<li>One customer can only grab one coupon per promotion</li>
<li>Support multi promotion activing (discount of each promotion is different)</li>
</ul>
</li>
<li>If Command micro-service down, it will recovery all uncompleted promotions immediately before start-up again.</li>
</ol>
<p>Maybe you would say that customer management and customer login function are not listed? Indeed, the customer is indispensable in our scenario, in order to simply design, we don’t include login and token authentication etc., if you are interesting about this, you can see ServiceComb’s <a href="https://github.com/ServiceComb/ServiceComb-Company-WorkShop">Company</a> demo application to get more information.</p>
<h2 id="improvement-design">Improvement Design</h2>
<p>For entity, domain-driven design (<a href="https://en.wikipedia.org/wiki/Domain-driven_design">DDD</a>) recommended to use a separate interface, so we design a new Admin micro-service to provide service:</p>
<p><img src="/assets/images/seckill-develop-course-part-II-arth-en.png" alt="Fig-1 Architecture after Admin micro-service added" class="align-center" /></p>
<h2 id="improvement-implement">Improvement Implement</h2>
<h3 id="implement-of-admin-micro-service">Implement of Admin micro-service</h3>
<p>Admin micro-service only provide services for promotion entity, we can map this function to REST method:</p>
<ul>
<li>New promotion map to Post;</li>
<li>Modify promotion map to Put;   </li>
<li>Query promotion map to Get;   </li>
<li>
<p>Delete promotion map to Delete.  </p>
<p>To match current requirement we only need implement Post and Get, In addition, already started promotion should not be able to modify, so we increased the corresponding check.</p>
</li>
</ul>
<h3 id="new-check-and-features-implement">New check and features Implement</h3>
<p>Add a HashSet per promotion to check whether customer had grab coupon; <br />
Add “SecKillPromotionBootstrap” class as promotion bootstrap manager for support multi active, “SecKillCommandService” and “SecKillPersistentRunner” now managed(create) by it。</p>
<h3 id="command-micro-service-auto-recovery-implement">Command micro-service auto recovery Implement</h3>
<p>Add “SecKillRecoveryService” class to check state of promotion, uncomplement promotions whether unstart or activing all need check by it to init start-up information including left coupons, grabbed customers list, etc.</p>
<h2 id="function-verification">Function Verification</h2>
<p>Finally, we use PostMan to check completed functions, Please ensure request body fill with JSON format, and set Content-Type to application/json:</p>
<h3 id="create-promotion">Create Promotion</h3>
<p><img src="/assets/images/seckill-develop-course-part-II-create-promotion.png" alt="Fig-2 Create promotion" class="align-center" /></p>
<h3 id="query-activing-promotions">Query Activing Promotions</h3>
<p><img src="/assets/images/seckill-develop-course-part-II-query-active-promotion.png" alt="Fig-3 Query activing promotions" class="align-center" /></p>
<h3 id="reject-duplicate-grab">Reject duplicate Grab</h3>
<p><img src="/assets/images/seckill-develop-course-part-II-reject-duplicate-grab.png" alt="Fig-4 Reject duplicate grab" class="align-center" /></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/#seckill" class="page__taxonomy-item" rel="tag">seckill</a>
</span>
</p>
<p class="page__date"><strong><i class="fa fa-fw fa-calendar" aria-hidden="true"></i> Updated:</strong> <time datetime="2017-09-13">September 13, 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=SecKill Develop Journey (II) /docs/seckill-development-journey-part-II/" 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/seckill-development-journey-part-II/" 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/seckill-development-journey-part-II/" 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/seckill-development-journey-part-II/" 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="/cn/docs/seckill-development-journey-part-I/" class="pagination--pager" title="秒杀开发历程(一)
">Previous</a>
<a href="/cn/docs/seckill-development-journey-part-II/" class="pagination--pager" title="秒杀开发历程(二)
">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/apache/incubator-servicecomb-website/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="seckill-develop-course-part-II">
<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/playing-on-the-open-source-community-with-Apache-ServiceComb-GDUT/" rel="permalink">与Apache ServiceComb一起玩开源-广工站 (PPT Download)
</a>
</h2>
<p class="archive__item-excerpt" itemprop="description">与Apache ServiceComb一起玩开源-广工站 (PPT Download)
</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="/cn/docs/servicecomb-service-center-client/" rel="permalink">使用ServiceComb客户端轻松调用ServiceCenter
</a>
</h2>
<p class="archive__item-excerpt" itemprop="description">使用ServiceComb客户端轻松调用ServiceCenter
</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/playing-on-the-open-source-community-with-Apache-ServiceComb-BUPT/" rel="permalink">与Apache ServiceComb一起玩开源-北邮站 (PPT Download)
</a>
</h2>
<p class="archive__item-excerpt" itemprop="description">与Apache ServiceComb一起玩开源-北邮站 (PPT Download)
</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/servicecomb-accept-newcapec-institute-code-donation/" rel="permalink">Apache ServiceComb Accept Code Donation From NewCapec Institute
</a>
</h2>
<p class="archive__item-excerpt" itemprop="description">Apache ServiceComb Accept Code Donation From NewCapec Institute
</p>
<p class="page__meta"><i class="fa fa-clock-o" aria-hidden="true"></i>
less than 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/getting-started/">Getting started</a></li>
<li><a href="/docs/users/">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">ASF</p>
<li><a href="http://www.apache.org">Foundation</a></li>
<li><a href="http://www.apache.org/licenses/">License</a></li>
<li><a href="http://www.apache.org/events/current-event">Events</a></li>
<li><a href="http://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li>
<li><a href="http://www.apache.org/foundation/thanks.html">Thanks</a></li>
</ul>
</div>
<div class="col">
<ul>
<p class="header">Contribute</p>
<li><a href="http://issues.apache.org/jira/browse/SCB">Report a Doc Issue</a></li>
<li><a href="https://github.com/apache/servicecomb-website/edit/master/_posts/2017-08-30-seckill-develop-course-part-II.md">Edit This Page on Github</a></li>
<li><a href="/developers/submit-codes/">Code Submit Guide</a></li>
<li><a href="/security">Security</a></li>
</ul>
</div>
<div class="col">
<ul class="social-icons">
<p class="header">Community</p>
<li>
<a href="mailto:dev-subscribe@servicecomb.incubator.apache.org" rel="nofollow"><span class="mail">Mailing List</span></a>
</li>
<li>
<a href="https://github.com/apache?q=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>&copy; 2019 Apache ServiceComb. Powered by <a href="http://jekyllrb.com" rel="nofollow">Jekyll</a> &amp; <a href="https://mademistakes.com/work/minimal-mistakes-jekyll-theme/" rel="nofollow">Minimal Mistakes</a>.</div>
<div>All other marks mentioned may be trademarks or registered trademarks of their respective owners.</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>