├── .gitignore ├── README.md ├── docker-compose.yml └── seckill_service ├── .idea ├── .name ├── Seckill_Service.iml ├── encodings.xml ├── jsLibraryMappings.xml ├── libraries │ └── Seckill_Service_node_modules.xml ├── misc.xml ├── modules.xml ├── runConfigurations │ └── bin_www.xml └── workspace.xml ├── app.js ├── bin └── www ├── package.json ├── public └── stylesheets │ └── style.css ├── routes ├── index.js ├── seckill.js └── users.js ├── seckill_kafka_consumer.js └── views ├── error.jade ├── index.jade └── layout.jade /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MockSecKill 2 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | zookeeper: 4 | image: wurstmeister/zookeeper 5 | ports: 6 | - "2181:2181" 7 | kafka: 8 | image: wurstmeister/kafka 9 | links: 10 | - zookeeper:zk 11 | ports: 12 | - "9092:9092" 13 | depends_on: 14 | - zookeeper 15 | environment: 16 | KAFKA_ADVERTISED_HOST_NAME: 192.168.2.107 17 | KAFKA_ADVERTISED_PORT: "9092" 18 | KAFKA_ZOOKEEPER_CONNECT: zk:2181 19 | redis: 20 | image: redis 21 | ports: 22 | - "6379:6379" 23 | mysql: 24 | image: mysql 25 | ports: 26 | - "3306:3306" 27 | environment: 28 | MYSQL_ROOT_PASSWORD: root 29 | -------------------------------------------------------------------------------- /seckill_service/.idea/.name: -------------------------------------------------------------------------------- 1 | Seckill_Service -------------------------------------------------------------------------------- /seckill_service/.idea/Seckill_Service.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /seckill_service/.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /seckill_service/.idea/jsLibraryMappings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /seckill_service/.idea/libraries/Seckill_Service_node_modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /seckill_service/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /seckill_service/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /seckill_service/.idea/runConfigurations/bin_www.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /seckill_service/.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 14 | 15 | 16 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 140 | 141 | 142 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | true 160 | 161 | 162 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 200 | 201 | 202 | 203 | 206 | 207 | 210 | 211 | 212 | 213 | 216 | 217 | 220 | 221 | 224 | 225 | 226 | 227 | 230 | 231 | 234 | 235 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | $PROJECT_DIR$ 296 | true 297 | 298 | bdd 299 | 300 | DIRECTORY 301 | 302 | false 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 1484492752471 326 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 357 | 358 | 359 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | -------------------------------------------------------------------------------- /seckill_service/app.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var path = require('path'); 3 | var favicon = require('serve-favicon'); 4 | var logger = require('morgan'); 5 | var cookieParser = require('cookie-parser'); 6 | var bodyParser = require('body-parser'); 7 | 8 | var index = require('./routes/index'); 9 | var users = require('./routes/users'); 10 | var seckill = require('./routes/seckill'); 11 | 12 | var app = express(); 13 | app.listen(3000); 14 | 15 | // view engine setup 16 | app.set('views', path.join(__dirname, 'views')); 17 | app.set('view engine', 'jade'); 18 | 19 | // uncomment after placing your favicon in /public 20 | //app.use(favicon(path.join(__dirname, 'public', 'favicon.ico'))); 21 | app.use(logger('dev')); 22 | app.use(bodyParser.json()); 23 | app.use(bodyParser.urlencoded({ extended: false })); 24 | app.use(cookieParser()); 25 | app.use(express.static(path.join(__dirname, 'public'))); 26 | 27 | app.use('/', index); 28 | app.use('/users', users); 29 | app.use('/seckill', seckill); 30 | 31 | // catch 404 and forward to error handler 32 | app.use(function(req, res, next) { 33 | var err = new Error('Not Found'); 34 | err.status = 404; 35 | next(err); 36 | }); 37 | 38 | // error handler 39 | app.use(function(err, req, res, next) { 40 | // set locals, only providing error in development 41 | res.locals.message = err.message; 42 | res.locals.error = req.app.get('env') === 'development' ? err : {}; 43 | 44 | // render the error page 45 | res.status(err.status || 500); 46 | res.render('error'); 47 | }); 48 | 49 | module.exports = app; 50 | -------------------------------------------------------------------------------- /seckill_service/bin/www: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /** 4 | * Module dependencies. 5 | */ 6 | 7 | var app = require('../app'); 8 | var debug = require('debug')('seckill-service:server'); 9 | var http = require('http'); 10 | 11 | /** 12 | * Get port from environment and store in Express. 13 | */ 14 | 15 | var port = normalizePort(process.env.PORT || '3000'); 16 | app.set('port', port); 17 | 18 | /** 19 | * Create HTTP server. 20 | */ 21 | 22 | var server = http.createServer(app); 23 | 24 | /** 25 | * Listen on provided port, on all network interfaces. 26 | */ 27 | 28 | server.listen(port); 29 | server.on('error', onError); 30 | server.on('listening', onListening); 31 | 32 | /** 33 | * Normalize a port into a number, string, or false. 34 | */ 35 | 36 | function normalizePort(val) { 37 | var port = parseInt(val, 10); 38 | 39 | if (isNaN(port)) { 40 | // named pipe 41 | return val; 42 | } 43 | 44 | if (port >= 0) { 45 | // port number 46 | return port; 47 | } 48 | 49 | return false; 50 | } 51 | 52 | /** 53 | * Event listener for HTTP server "error" event. 54 | */ 55 | 56 | function onError(error) { 57 | if (error.syscall !== 'listen') { 58 | throw error; 59 | } 60 | 61 | var bind = typeof port === 'string' 62 | ? 'Pipe ' + port 63 | : 'Port ' + port; 64 | 65 | // handle specific listen errors with friendly messages 66 | switch (error.code) { 67 | case 'EACCES': 68 | console.error(bind + ' requires elevated privileges'); 69 | process.exit(1); 70 | break; 71 | case 'EADDRINUSE': 72 | console.error(bind + ' is already in use'); 73 | process.exit(1); 74 | break; 75 | default: 76 | throw error; 77 | } 78 | } 79 | 80 | /** 81 | * Event listener for HTTP server "listening" event. 82 | */ 83 | 84 | function onListening() { 85 | var addr = server.address(); 86 | var bind = typeof addr === 'string' 87 | ? 'pipe ' + addr 88 | : 'port ' + addr.port; 89 | debug('Listening on ' + bind); 90 | } 91 | -------------------------------------------------------------------------------- /seckill_service/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "seckill-service", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/www" 7 | }, 8 | "dependencies": { 9 | "body-parser": "~1.15.2", 10 | "cookie-parser": "~1.4.3", 11 | "debug": "~2.2.0", 12 | "express": "~4.14.0", 13 | "jade": "~1.11.0", 14 | "kafka-node": "^1.3.0", 15 | "morgan": "~1.7.0", 16 | "mysql": "^2.12.0", 17 | "redis": "^2.6.5", 18 | "serve-favicon": "~2.3.0" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /seckill_service/public/stylesheets/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 50px; 3 | font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; 4 | } 5 | 6 | a { 7 | color: #00B7FF; 8 | } 9 | -------------------------------------------------------------------------------- /seckill_service/routes/index.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | 4 | /* GET home page. */ 5 | router.get('/', function(req, res, next) { 6 | res.render('index', { title: 'Express' }); 7 | }); 8 | 9 | module.exports = router; 10 | -------------------------------------------------------------------------------- /seckill_service/routes/seckill.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | var redis = require('redis'); 4 | var kafka = require('kafka-node'); 5 | var Producer = kafka.Producer; 6 | var kafkaClient = new kafka.Client(); 7 | var producer = new Producer(kafkaClient); 8 | var count = 0; 9 | 10 | router.post('/seckill', function (req, res) { 11 | console.log('count=' + count++); 12 | var fn = function (optionalClient) { 13 | if (optionalClient == 'undefined' || optionalClient == null) { 14 | var client = redis.createClient(); 15 | }else{ 16 | var client = optionalClient; 17 | } 18 | client.on('error', function (er) { 19 | console.trace('Here I am'); 20 | console.error(er.stack); 21 | client.end(true); 22 | }); 23 | client.watch("counter"); 24 | client.get("counter", function (err, reply) { 25 | if (parseInt(reply) > 0) { 26 | var multi = client.multi(); 27 | multi.decr("counter"); 28 | multi.exec(function (err, replies) { 29 | if (replies == null) { 30 | console.log('should have conflict') 31 | fn(client); 32 | } else { 33 | var payload = [ 34 | { 35 | topic: 'CAR_NUMBER', 36 | messages: 'buy 1 car', 37 | partition: 0 38 | } 39 | ]; 40 | producer.send(payload, function (err, data) { 41 | console.log(data); 42 | }); 43 | res.send(replies); 44 | client.end(true); 45 | } 46 | }); 47 | } else { 48 | console.log("sold out!"); 49 | res.send("sold out!"); 50 | client.end(true); 51 | } 52 | }) 53 | }; 54 | fn(); 55 | }); 56 | 57 | module.exports = router; -------------------------------------------------------------------------------- /seckill_service/routes/users.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | 4 | /* GET users listing. */ 5 | router.get('/', function(req, res, next) { 6 | res.send('respond with a resource'); 7 | }); 8 | 9 | module.exports = router; 10 | -------------------------------------------------------------------------------- /seckill_service/seckill_kafka_consumer.js: -------------------------------------------------------------------------------- 1 | var kafka = require('kafka-node'), 2 | Consumer = kafka.Consumer, 3 | client = new kafka.Client(), 4 | consumer = new Consumer( 5 | client, 6 | [ 7 | {topic: 'CAR_NUMBER', partition: 0} 8 | ], 9 | { 10 | autoCommit: true 11 | } 12 | ); 13 | 14 | var mysql = require('mysql'); 15 | var connection = mysql.createConnection({ 16 | host : 'localhost', 17 | user : 'root', 18 | password : 'root', 19 | database : 'seckill' 20 | }); 21 | 22 | connection.connect(); 23 | 24 | consumer.on('message', function (message) { 25 | connection.query('INSERT INTO seckill set ?', {date: new Date()}, function(error, results, fields){ 26 | if(error){ 27 | console.error(error); 28 | } 29 | console.log(results); 30 | }) 31 | }); -------------------------------------------------------------------------------- /seckill_service/views/error.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | h1= message 5 | h2= error.status 6 | pre #{error.stack} 7 | -------------------------------------------------------------------------------- /seckill_service/views/index.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | h1= title 5 | p Welcome to #{title} 6 | -------------------------------------------------------------------------------- /seckill_service/views/layout.jade: -------------------------------------------------------------------------------- 1 | doctype html 2 | html 3 | head 4 | title= title 5 | link(rel='stylesheet', href='/stylesheets/style.css') 6 | body 7 | block content 8 | --------------------------------------------------------------------------------