File Coverage

blib/lib/Vayne.pm
Criterion Covered Total %
statement 25 26 96.1
branch 3 6 50.0
condition 3 8 37.5
subroutine 8 8 100.0
pod n/a
total 39 48 81.2


line stmt bran cond sub pod time code
1             package Vayne;
2              
3 1     1   45930 use strict;
  1         2  
  1         22  
4 1     1   3 use warnings;
  1         1  
  1         18  
5              
6 1     1   447 use YAML::XS;
  1         1845  
  1         41  
7 1     1   4 use File::Spec;
  1         1  
  1         15  
8 1     1   613 use Data::Printer;
  1         27013  
  1         8  
9 1     1   817 use Log::Log4perl qw(:easy);
  1         33472  
  1         4  
10             Log::Log4perl->easy_init($DEBUG);
11              
12             require Exporter;
13              
14             our $VERSION = '0.01';
15             our $NAMESPACE = $ENV{VAYNE_SPACE} || 'vayne';
16             our $HOME = $ENV{VAYNE_HOME} || '~/vayne';
17              
18             =encoding utf8
19              
20             =head1 NAME
21              
22             Vayne - Distribute task queue
23              
24             =head1 SYNOPSIS
25              
26             use Vayne;
27             use Vayne::Callback;
28             use Vayne::Tracker;
29              
30             my @workload = <>; chomp @workload;
31             my $tracker = Vayne::Tracker->new();
32             my $step = Vayne->task('foo');
33             my $taskid = $tracker->add_task(
34             'region:region-first',
35             {
36             name => 'foo',
37             step => $step,
38             expire => 90,
39             },
40             @workload
41             );
42             my $call = Vayne::Callback->new();
43             my $stat = $call->wait($taskid);
44              
45             =head1 GETTING STARTED
46              
47             # First time only
48             > vayne-init -d $HOME/vayne
49              
50             # Setup configurations in $HOME/vayne/conf (zookeeper mongodb redis)
51              
52             # Add our first region, then the region info will upload to zk server.
53             > vayne-ctrl --set --region region-first --server redisserver:port --password redispasswd
54              
55             # Define our first task, $HOME/vayne/task/foo
56              
57             # check server ssh server
58             - name: 'check ssh' #step's name
59             worker: tcp #step's worker
60             param: #step's parameters
61             port: 22
62             input: ''
63             check: '^SSH-2.0-OpenSSH'
64              
65             - name: 'foo'
66             worker: dump
67             param:
68             bar: baz
69              
70             - name: 'only suc'
71             need:
72             - 'check ssh': 1
73             worker: dump
74             param:
75             - array
76             - key1: value1
77             key2: value2
78              
79             # tracke the job result
80             - name: 'tracker'
81             worker: track
82              
83             # Switch the server you run workers to our first region.
84             > vayne-ctrl --switch --region region-first
85              
86             # Run workers.
87             > $HOME/vayne/worker/tcp &
88             > $HOME/vayne/worker/dump &
89             > $HOME/vayne/worker/tracker &
90              
91             # Run task tracker.
92             > vayne-tracker &
93              
94             # Submit our task by CLI.
95             > echo '127.0.0.1'|vayne-task --add --name foo --expire 60 --strategy region:region-first
96             # or
97             > vayne-task --add --name foo --expire 60 --strategy region:region-first < server_list
98              
99             # Query our task through taskid by CLI.
100             > vayne-task --taskid 9789F5E6-2644-11E6-A6F0-AF9AF8F9E07F --query
101              
102             # Or use Vayne lib in your program like SYNOPSIS.
103              
104             =head1 DESCRIPTION
105              
106             Vayne is a distribute task queue with many feature.
107              
108             =head2 FEATURE
109              
110             =over 3
111              
112             =item Logical Region with Flexible Spawning Strategy
113              
114             Has the concept of logical region.
115             You can spawn task into different region with strategy.
116             Spawning strategy can be easily write.
117              
118             =item Custome Task Flow with Reusable Worker
119              
120             Worker is a process can do some specific stuffs.
121             Step have a step's name, a worker's name and parameters.
122             You can define custome task flow by constructing any steps.
123              
124             =item Simple Worker Interface with Good Performance
125              
126             L<Vayne::Worker> is using L<Coro> which can provide excellent performance in network IO.
127             Worker has a simple interface to write, also you can use Coro::* module to enhance worker performance.
128             Whole system is combined with Message Queue.
129             You can get a better performance easily by increasing the worker counts while MQ is not the bottleneck.
130              
131             =back
132              
133             =head2 HOW IT WORKS
134              
135             +--------+
136             |Worker A| x N
137             +--------+
138             +------------+ Workers may run on several servers
139             | | +--------+
140             | Region A | |Worker B| x N
141             | | +--------+
142             +------------+
143             .....
144             +-----------+ +----------+
145             | | +------------+ |JobTracker| x N
146             | Task Conf | | | +----------+
147             | | | Region B |
148             | +-------+ | | |
149             | | step1 | | +-----------+ +------------+ +-----------+ +-----------+
150             | +-------+ | | | Spawn Jobs Save Job Information | | +------> | |
151             | | + | workloads | +----------------> +---------------------> | Mongodb | |TaskTracker|
152             | +-------+ | | | with Strategy to Center Mongodb | | <------+ | |
153             | | step2 | | +-----------+ +------------+ +-----------+ +-----------+
154             | +-------+ | | |
155             | ... | | Region C | ..... ^
156             | +-------+ | | | |
157             | | stepN | | +------------+ |
158             | +-------+ | |
159             | | |
160             +-----------+ +------------+ |
161             | | |
162             | Region D | |
163             | | | |
164             | +------------+ |
165             | |
166             | |
167             | |
168             | |
169             | Save Task Information to Center Mongodb |
170             +----------------------------------------------------------------------------------------------------------+
171            
172              
173             =head3 0. Task Conf & Step
174              
175             The Task Conf is combined with several ordered steps.
176             Each step have a step's name, a worker's name and parameters.
177             Workload will be prosessed step by step.
178              
179             =head3 1. Spawn Task
180              
181             Vayne support CLI and API to spawn a task.
182             A task contain numbers of jobs.
183             Task info will write to I<task collection> in mongodb first.
184             Jobs will be hashed into saperated region by strategy.
185             Then enqueue jobs to their region's redis queue named by first step of the job, and write to I<job collection> in mongodb.
186              
187             =head3 2. Queue & Region
188              
189             Like L<Redis::JobQueue>, Vayne use I<redis> for job queuing and job info caching.
190             The data structure is nearly the same as L<Redis::JobQueue/"JobQueue data structure stored in Redis">.
191              
192             Each B<region> has a I<queue(redis server)>. Both their infomation are saved on I<zookeeper server>.
193              
194             Each I<real server> which you want to run workers should belong to a B<region>.
195              
196             B<Worker> will register its names under real server's B<region> on I<zookeeper server> when it start.
197              
198             Details see L<Vayne::Zk/"DATA STRUCTURE">.
199              
200             =head3 2. Worker
201              
202             When it start, worker register its names on I<zookeeper server>.
203             Then generate some L<Coro> threads below:
204              
205             =over 4
206              
207             =item Check the Registration
208              
209             Go die when the registration changed.
210             Ex: Region info changed; Real Server switch to another region; Connection to zk failed.
211              
212             I< * The worker will die very quickly when zookeeper server is not available. It may cause some problems. Should be careful. >
213              
214             =item Job Consumer
215              
216             BLPOP queues which worker registered, then put the job into L<Coro::Channel>
217              
218             =item Worker
219              
220             Get B<job> from L<Coro::Channel>, and do the stuff with it.
221             Tag the I<result> and I<status> on the B<job>.
222             Put the B<job> to update L<Coro::Channel>.
223              
224             =item Update Job Info
225              
226             Get B<Job> from update L<Coro::Channel>.
227             Push the job to next queue according to the job's step.
228              
229             =back
230              
231             C<INT>, C<TERM>, C<HUP> signals will be catched.
232             Then graceful stop the worker.
233              
234              
235             =head3 4. JOB TRACKER
236              
237             Job tracker is a special worker, it just send the job info dealed by previous workers to mongodb.
238             Usually 'tracker' should be the last step of a job.
239              
240             =head3 5. TASK TRACKER
241              
242             Script L<vayne-tracker>
243             Loop
244             bla..
245              
246              
247             =head2 BACKEND
248              
249             Redis-3.2 L<http://redis.io/>
250              
251             Zookeeper-3.3.6 L<http://zookeeper.apache.org/>
252              
253             MongoDB-3.0.6 L<https://www.mongodb.com/>
254              
255             =head2 DATA STRUCTURE
256              
257             =head3 Zookeeper
258              
259             L<Vayne::Zk/"DATA STRUCTURE">
260              
261             =head3 Redis
262              
263             Data Structure for job&queue is nearly the same as
264             L<Redis::JobQueue/"JobQueue data structure stored in Redis">
265              
266             =head3 MongoDB
267              
268             bla bla..
269              
270              
271             =head2 HOW TO WRITE A WORKER
272              
273             bla bla..
274              
275             =cut
276              
277             my %STUB =
278             (
279             conf => sub { eval{YAML::XS::LoadFile $_[0]} or LOGWARN $@;},
280             task => sub { eval{YAML::XS::LoadFile $_[0]} or LOGWARN $@;},
281             strategy => sub { eval{do $_[0]} or LOGWARN $@; },
282             );
283              
284             #init logger
285             {
286             my $conf = Vayne->conf('logger');
287             $_->{level} = $Log::Log4perl::Level::PRIORITY{ $_->{level} } for @$conf;
288             Log::Log4perl->easy_init(@$conf);
289             }
290              
291 1     1   52 sub _path{File::Spec->join( $Vayne::HOME, @_)}
292              
293             sub AUTOLOAD
294             {
295 1 50   1   4 return if our $AUTOLOAD =~ /::DESTROY$/;
296              
297 1         7 my $class = __PACKAGE__;
298 1         14 my( $func ) = $AUTOLOAD =~ /^$class\:\:(.+)$/;
299 1 50 33     5 return unless $func && $STUB{$func};
300              
301 1         1 my($foo, $name) = @_;
302 1 50 50     2 LOGWARN "$name is not a file" and return unless $name = _path($func, $name) and -f $name;
      33        
303 0           $STUB{$func}->($name);
304             }
305              
306              
307              
308             1;
309             __END__
310              
311             =head1 AUTHOR
312              
313             SiYu Zhao E<lt>zuyis@cpan.orgE<gt>
314              
315             =head1 COPYRIGHT
316              
317             Copyright 2016- SiYu Zhao
318              
319             =head1 LICENSE
320              
321             This library is free software; you can redistribute it and/or modify
322             it under the same terms as Perl itself.
323              
324             =head1 SEE ALSO
325              
326             L<Redis::JobQueue>
327              
328             =cut