内容简介:如何为zabbix创建自己的的ansible module
作为一个运维狗,zabbix这个强大的 工具 肯定知道吧,因为我们大部分的时间都在zabbix上:添加监控,ack报警,我们要创建一个个的template,一个个的item,和一个个的trigger
当然,我们可以直接web页面添加,但是,如果有一天,zabbix彻底坏了,重新创建上千条监控的手动工作量你是的懂的…..
既然不向手动创建,肯定是想把这些item,template, trigger, 通过文件管理起来,然后通过github来管理版本,然后通过ansible-playbook来统一创建,下次有人告诉你zabbix挂了的时候,不用着急,ansible-palybook一跑,半个小时给你一个全新的一模一样的zabbix(数据库得自己备份)
进入正题: ansible 其实是提供监控模块的 http://docs.ansible.com/ansible/list_of_monitoring_modules.html
我们可以用这个现成的模块来做一些基本的操作:例如增加一个mantain:
- name: Create a named maintenance window for host www1 for 90 minutes zabbix_maintenance: name: Update of www1 host_name: www1.example.com state: present minutes: 90 server_url: https://monitoring.example.com login_user: ansible login_password: pAsSwOrD
或者更新一个主机信息:http://docs.ansible.com/ansible/zabbix_host_module.html
但是,毕竟,这些是有限的,例如,我们想创建一个item, 创建一个模版,官方是没有提供的,这个时候,我们就要自己写,要自己写module,首先确定了如下:
1: zabbix 提供了相应的api
2:python 可以调去api
满足以上两个条件之后,自己写module就不成问题了
首先,我们要创建一个zabbix api文件,用来负责建立连接(参见:https://github.com/openshift/openshift-tools/blob/prod/openshift_tools/zbxapi/__init__.py)
#!/usr/bin/env python
'''
ZabbixAPI library
if __name__ == '__main__':
server = 'http://localhost/zabbix/api_jsonrpc.php'
username = ''
password = ''
zbc = ZabbixConnection(server, username, password)
zbx = ZabbixAPI(data)
print zbx.get_content('user', 'get', {})
'''
# vim: expandtab:tabstop=4:shiftwidth=4
# Copyright 2015 Red Hat Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Purpose: An ansible module to communicate with zabbix.
# Requires Packages on python < 2.7.9:
# python-pyasn1 python-ndg_httpsclient pyOpenSSL
#
# pylint: disable=line-too-long
# Disabling line length for readability
import json
import requests
import httplib
import copy
class ZabbixAPIError(Exception):
'''
ZabbixAPIError
Exists to propagate errors up from the api
'''
pass
# Disabling to have DTO
# pylint: disable=too-few-public-methods
# DTO needs an extra arg
# pylint: disable=too-many-arguments
class ZabbixConnection(object):
'''
Placeholder for connection options
'''
def __init__(self, server, username, password, ssl_verify=False, verbose=False):
self.server = server
self.username = username
self.password = password
self.verbose = verbose
self.ssl_verify = ssl_verify
class ZabbixAPI(object):
'''
ZabbixAPI class
'''
classes = {
'Action': ['create', 'delete', 'get', 'update'],
'Alert': ['get'],
'Application': ['create', 'delete', 'get', 'massadd', 'update'],
'Configuration': ['export', 'import'],
'Dhost': ['get'],
'Dcheck': ['get'],
'Discoveryrule': ['copy', 'create', 'delete', 'get', 'isreadable', 'iswritable', 'update'],
'Drule': ['copy', 'create', 'delete', 'get', 'isreadable', 'iswritable', 'update'],
'Dservice': ['get'],
'Event': ['acknowledge', 'get'],
'Graph': ['create', 'delete', 'get', 'update'],
'Graphitem': ['get'],
'Graphprototype': ['create', 'delete', 'get', 'update'],
'History': ['get'],
'Hostgroup': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'massadd', 'massremove', 'massupdate', 'update'],
'Hostinterface': ['create', 'delete', 'get', 'massadd', 'massremove', 'replacehostinterfaces', 'update'],
'Host': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'massadd', 'massremove', 'massupdate', 'update'],
'Hostprototype': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'update'],
'Httptest': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'update'],
'Iconmap': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'update'],
'Image': ['create', 'delete', 'get', 'update'],
'Item': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'update'],
'Itemprototype': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'update'],
'Maintenance': ['create', 'delete', 'get', 'update'],
'Map': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'update'],
'Mediatype': ['create', 'delete', 'get', 'update'],
'Proxy': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'update'],
'Screen': ['create', 'delete', 'get', 'update'],
'Screenitem': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'update', 'updatebyposition'],
'Script': ['create', 'delete', 'execute', 'get', 'getscriptsbyhosts', 'update'],
'Service': ['adddependencies', 'addtimes', 'create', 'delete', 'deletedependencies', 'deletetimes', 'get', 'getsla', 'isreadable', 'iswritable', 'update'],
'Template': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'massadd', 'massremove', 'massupdate', 'update'],
'Templatescreen': ['copy', 'create', 'delete', 'get', 'isreadable', 'iswritable', 'update'],
'Templatescreenitem': ['get'],
'Trigger': ['adddependencies', 'create', 'delete', 'deletedependencies', 'get', 'isreadable', 'iswritable', 'update'],
'Triggerprototype': ['create', 'delete', 'get', 'update'],
'User': ['addmedia', 'create', 'delete', 'deletemedia', 'get', 'isreadable', 'iswritable', 'login', 'logout', 'update', 'updatemedia', 'updateprofile'],
'Usergroup': ['create', 'delete', 'get', 'isreadable', 'iswritable', 'massadd', 'massupdate', 'update'],
'Usermacro': ['create', 'createglobal', 'delete', 'deleteglobal', 'get', 'update', 'updateglobal'],
'Usermedia': ['get'],
}
def __init__(self, zabbix_connection=None):
self.server = zabbix_connection.server
self.username = zabbix_connection.username
self.password = zabbix_connection.password
if any([value == None for value in [self.server, self.username, self.password]]):
raise ZabbixAPIError('Please specify zabbix server url, username, and password.')
self.verbose = zabbix_connection.verbose
self.ssl_verify = zabbix_connection.ssl_verify
if self.verbose:
httplib.HTTPSConnection.debuglevel = 1
httplib.HTTPConnection.debuglevel = 1
self.auth = None
for cname, _ in self.classes.items():
setattr(self, cname.lower(), getattr(self, cname)(self))
# pylint: disable=no-member
# This method does not exist until the metaprogramming executed
resp, content = self.user.login(user=self.username, password=self.password)
if resp.status_code == 200:
if content.has_key('result'):
self.auth = content['result']
elif content.has_key('error'):
raise ZabbixAPIError("Unable to authenticate with zabbix server. {0} ".format(content['error']))
else:
raise ZabbixAPIError("Error in call to zabbix. Http status: {0}.".format(resp.status_code))
def perform(self, method, rpc_params):
'''
This method calls your zabbix server.
It requires the following parameters in order for a proper request to be processed:
jsonrpc - the version of the JSON-RPC protocol used by the API;
the Zabbix API implements JSON-RPC version 2.0;
method - the API method being called;
rpc_params - parameters that will be passed to the API method;
id - an arbitrary identifier of the request;
auth - a user authentication token; since we don't have one yet, it's set to null.
'''
jsonrpc = "2.0"
rid = 1
headers = {}
headers["Content-type"] = "application/json"
body = {
"jsonrpc": jsonrpc,
"method": method,
"params": rpc_params.get('params', {}),
"id": rid,
'auth': self.auth,
}
if method in ['user.login', 'api.version']:
del body['auth']
body = json.dumps(body)
if self.verbose:
print "BODY:", body
print "METHOD:", method
print "HEADERS:", headers
request = requests.Request("POST", self.server, data=body, headers=headers)
session = requests.Session()
req_prep = session.prepare_request(request)
response = session.send(req_prep, verify=self.ssl_verify)
if response.status_code not in [200, 201]:
raise ZabbixAPIError('Error calling zabbix. Zabbix returned %s' % response.status_code)
if self.verbose:
print "RESPONSE:", response.text
try:
content = response.json()
except ValueError as err:
content = {"error": err.message}
return response, content
@staticmethod
def meta(cname, method_names):
'''
This bit of metaprogramming is where the ZabbixAPI subclasses are created.
For each of ZabbixAPI.classes we create a class from the key and methods
from the ZabbixAPI.classes values. We pass a reference to ZabbixAPI class
to each subclass in order for each to be able to call the perform method.
'''
def meta_method(_class, method_name):
'''
This meta method allows a class to add methods to it.
'''
# This template method is a stub method for each of the subclass
# methods.
def template_method(self, params=None, **rpc_params):
'''
This template method is a stub method for each of the subclass methods.
'''
if params:
rpc_params['params'] = params
else:
rpc_params['params'] = copy.deepcopy(rpc_params)
return self.parent.perform(cname.lower()+"."+method_name, rpc_params)
template_method.__doc__ = \
"https://www.zabbix.com/documentation/2.4/manual/api/reference/%s/%s" % \
(cname.lower(), method_name)
template_method.__name__ = method_name
# this is where the template method is placed inside of the subclass
# e.g. setattr(User, "create", stub_method)
setattr(_class, template_method.__name__, template_method)
# This class call instantiates a subclass. e.g. User
_class = type(cname,
(object,),
{'__doc__': \
"https://www.zabbix.com/documentation/2.4/manual/api/reference/%s" % cname.lower()})
def __init__(self, parent):
'''
This init method gets placed inside of the _class
to allow it to be instantiated. A reference to the parent class(ZabbixAPI)
is passed in to allow each class access to the perform method.
'''
self.parent = parent
# This attaches the init to the subclass. e.g. Create
setattr(_class, __init__.__name__, __init__)
# For each of our ZabbixAPI.classes dict values
# Create a method and attach it to our subclass.
# e.g. 'User': ['delete', 'get', 'updatemedia', 'updateprofile',
# 'update', 'iswritable', 'logout', 'addmedia', 'create',
# 'login', 'deletemedia', 'isreadable'],
# User.delete
# User.get
for method_name in method_names:
meta_method(_class, method_name)
# Return our subclass with all methods attached
return _class
def get_content(self, zbx_class_name, method, params):
'''
This bit of metaprogramming takes a zabbix_class_name (e.g. 'user' )
This gets the instantiated object of type user and calls method
with params as the parameters.
Returns the zabbix query results
'''
zbx_class_inst = self.__getattribute__(zbx_class_name.lower())
zbx_class = self.__getattribute__(zbx_class_name.capitalize())
return zbx_class.__dict__[method](zbx_class_inst, params)[1]
# Attach all ZabbixAPI.classes to ZabbixAPI class through metaprogramming
for _class_name, _method_names in ZabbixAPI.classes.items():
setattr(ZabbixAPI, _class_name, ZabbixAPI.meta(_class_name, _method_names))
目录结构:
$tree zbxapi/ zbxapi/ `-- __init__.py
然后就是我们的module了(这个地方要注意,module的名字,就是你的文件名)https://github.com/openshift/openshift-tools/tree/prod/ansible/roles/lib_zabbix/library
#!/usr/bin/env python
'''
Ansible module for zabbix items
'''
# vim: expandtab:tabstop=4:shiftwidth=4
#
# Zabbix item ansible module
#
#
# Copyright 2015 Red Hat Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# This is in place because each module looks similar to each other.
# These need duplicate code as their behavior is very similar
# but different for each zabbix class.
# pylint: disable=duplicate-code
# pylint: disable=import-error
from openshift_tools.zbxapi import ZabbixAPI, ZabbixConnection
def exists(content, key='result'):
''' Check if key exists in content or the size of content[key] > 0
'''
if not content.has_key(key):
return False
if not content[key]:
return False
return True
def get_data_type(data_type):
'''
Possible values:
0 - decimal;
1 - octal;
2 - hexadecimal;
3 - bool;
'''
vtype = 0
if 'octal' in data_type:
vtype = 1
elif 'hexadecimal' in data_type:
vtype = 2
elif 'bool' in data_type:
vtype = 3
return vtype
def get_value_type(value_type):
'''
Possible values:
0 - numeric float;
1 - character;
2 - log;
3 - numeric unsigned;
4 - text
'''
vtype = 0
if 'int' in value_type:
vtype = 3
elif 'log' in value_type:
vtype = 2
elif 'char' in value_type:
vtype = 1
elif 'str' in value_type:
vtype = 4
return vtype
def get_app_ids(application_names, app_name_ids):
''' get application ids from names
'''
applications = []
if application_names:
for app in application_names:
applications.append(app_name_ids[app])
return applications
def get_template_ids(zapi, template_name):
'''
get related templates
'''
template_ids = []
app_ids = {}
# Fetch templates by name
content = zapi.get_content('template',
'get',
{'search': {'host': template_name},
'selectApplications': ['applicationid', 'name']})
if content.has_key('result'):
template_ids.append(content['result'][0]['templateid'])
for app in content['result'][0]['applications']:
app_ids[app['name']] = app['applicationid']
return template_ids, app_ids
def get_host_ids(module, zapi, hostname):
'''
get related host_id
'''
host_ids = []
content = zapi.get_content('host',
'get',
{'search': {'host': hostname}})
# Module exit attempting to catch details about the following error during
# TASK [tools_roles/os_zabbix_cluster_stats : item: openshift.master.cluster.all.cpu.idle_sum]:
# in get_host_ids\n host_ids.append(content['result'][0]['hostid'])
# IndexError: list index out of range
try:
if content.has_key('result'):
host_ids.append(content['result'][0]['hostid'])
except IndexError as ierror:
module.exit_json(failed=True,
changed=False,
results='Error (%s): get host ids for %s did not contain expected content format: %s' % \
(str(ierror), hostname, str(content)),
state="Unknown")
return host_ids
def get_multiplier(inval):
''' Determine the multiplier
'''
if inval == None or inval == '':
return None, 0
rval = None
try:
rval = int(inval)
except ValueError:
pass
if rval:
return rval, 1
return rval, 0
def get_zabbix_type(ztype):
'''
Determine which type of discoverrule this is
'''
_types = {'agent': 0,
'SNMPv1': 1,
'trapper': 2,
'simple': 3,
'SNMPv2': 4,
'internal': 5,
'SNMPv3': 6,
'active': 7,
'aggregate': 8,
'web': 9,
'external': 10,
'database monitor': 11,
'ipmi': 12,
'ssh': 13,
'telnet': 14,
'calculated': 15,
'JMX': 16,
'SNMP trap': 17,
}
for typ in _types.keys():
if ztype in typ or ztype == typ:
_vtype = _types[typ]
break
else:
_vtype = 2
return _vtype
# The branches are needed for CRUD and error handling
# pylint: disable=too-many-branches, too-many-statements
def main():
'''
ansible zabbix module for zbx_item
'''
module = AnsibleModule(
argument_spec=dict(
zbx_server=dict(default='https://localhost/zabbix/api_jsonrpc.php', type='str'),
zbx_user=dict(default=os.environ.get('ZABBIX_USER', None), type='str'),
zbx_password=dict(default=os.environ.get('ZABBIX_PASSWORD', None), type='str'),
zbx_debug=dict(default=False, type='bool'),
name=dict(default=None, type='str'),
key=dict(default=None, type='str'),
template_name=dict(default=None, type='str'),
hostname=dict(default=None, type='str'),
zabbix_type=dict(default='trapper', type='str'),
value_type=dict(default='int', type='str'),
data_type=dict(default='decimal', type='str'),
interval=dict(default=60, type='int'),
delta=dict(default=0, type='int'),
multiplier=dict(default=None, type='str'),
description=dict(default=None, type='str'),
units=dict(default=None, type='str'),
history=dict(default=None, type='int'),
trends=dict(default=None, type='int'),
applications=dict(default=None, type='list'),
state=dict(default='present', type='str'),
params=dict(default=None, type='str'),
),
#supports_check_mode=True
mutually_exclusive=[
['template_name', 'hostname'],
['applications', 'hostname'],
]
)
zapi = ZabbixAPI(ZabbixConnection(module.params['zbx_server'],
module.params['zbx_user'],
module.params['zbx_password'],
module.params['zbx_debug']))
#Set the instance and the template for the rest of the calls
zbx_class_name = 'item'
state = module.params['state']
template_ids = None
app_name_ids = None
host_ids = None
content = None
if module.params['template_name']:
template_ids, app_name_ids = get_template_ids(zapi, module.params['template_name'])
if not template_ids:
module.exit_json(failed=True,
changed=False,
results='Error: Could not find template with name %s for item.' % \
module.params['template_name'],
state="Unknown")
if len(template_ids) != 1:
module.exit_json(failed=True,
changed=False,
results='Error: Found multiple templates matching %s for item.' % \
module.params['template_name'],
state="Unknown")
content = zapi.get_content(zbx_class_name,
'get',
{'search': {'key_': module.params['key']},
'selectApplications': 'applicationid',
'templateids': template_ids,
})
if module.params['hostname']:
host_ids = get_host_ids(module, zapi, module.params['hostname'])
if not host_ids:
module.exit_json(failed=True,
changed=False,
results='Error: Could not find host with name %s for item.' % module.params['hostname'],
state="Unknown")
if len(host_ids) != 1:
module.exit_json(failed=True,
changed=False,
results='Error: Found multiple hosts matching %s for item.' % module.params['hostname'],
state="Unknown")
content = zapi.get_content(zbx_class_name,
'get',
{'search': {'key_': module.params['key']},
'hostids': host_ids,
})
#******#
# GET
#******#
if state == 'list':
module.exit_json(changed=False, results=content['result'], state="list")
#******#
# DELETE
#******#
if state == 'absent':
if not exists(content):
module.exit_json(changed=False, state="absent")
content = zapi.get_content(zbx_class_name, 'delete', [content['result'][0]['itemid']])
module.exit_json(changed=True, results=content['result'], state="absent")
# Create and Update
if state == 'present':
formula, use_multiplier = get_multiplier(module.params['multiplier'])
params = {'name': module.params.get('name', module.params['key']),
'key_': module.params['key'],
'type': get_zabbix_type(module.params['zabbix_type']),
'value_type': get_value_type(module.params['value_type']),
'data_type': get_data_type(module.params['data_type']),
'formula': formula,
'multiplier': use_multiplier,
'description': module.params['description'],
'units': module.params['units'],
'history': module.params['history'],
'trends': module.params['trends'],
'delay': module.params['interval'],
'delta': module.params['delta'],
'params': module.params['params'],
}
if module.params['hostname']:
params['hostid'] = host_ids[0]
else:
params['applications'] = get_app_ids(module.params['applications'], app_name_ids)
params['hostid'] = template_ids[0]
# Remove any None valued params
_ = [params.pop(key, None) for key in params.keys() if params[key] is None]
#******#
# CREATE
#******#
if not exists(content):
content = zapi.get_content(zbx_class_name, 'create', params)
if content.has_key('error'):
module.exit_json(failed=True, changed=True, results=content['error'], state="present")
module.exit_json(changed=True, results=content['result'], state='present')
########
# UPDATE
########
_ = params.pop('hostid', None)
differences = {}
zab_results = content['result'][0]
for key, value in params.items():
if key == 'applications':
app_ids = [item['applicationid'] for item in zab_results[key]]
if set(app_ids) != set(value):
differences[key] = value
elif zab_results[key] != value and zab_results[key] != str(value):
differences[key] = value
if not differences:
module.exit_json(changed=False, results=zab_results, state="present")
# We have differences and need to update
differences['itemid'] = zab_results['itemid']
content = zapi.get_content(zbx_class_name, 'update', differences)
if content.has_key('error'):
module.exit_json(failed=True, changed=False, results=content['error'], state="present")
module.exit_json(changed=True, results=content['result'], state="present")
module.exit_json(failed=True,
changed=False,
results='Unknown state passed. %s' % state,
state="unknown")
# pylint: disable=redefined-builtin, unused-wildcard-import, wildcard-import, locally-disabled
# import module snippets. This are required
from ansible.module_utils.basic import *
main()
目录结构:
$tree lib_zabbix/ lib_zabbix/ |-- build | |-- ansible | | `-- zbx_maintenance.py | |-- doc | | `-- maintenance | |-- generate.py | |-- lib | | |-- base.py | | |-- hostgroup.py | | |-- host.py | | `-- zbxapi.py | `-- src | `-- zbx_maintenance.py |-- library | |-- __init__.py | |-- zbx_action.py | |-- zbx_application.py | |-- zbx_discoveryrule.py | |-- zbx_graphprototype.py | |-- zbx_graph.py | |-- zbx_hostgroup.py | |-- zbx_host.py | |-- zbx_httptest.py | |-- zbx_itemprototype.py | |-- zbx_item.py | |-- zbx_itservice.py | |-- zbx_maintenance.py | |-- zbx_mediatype.py | |-- zbx_template.py | |-- zbx_triggerprototype.py | |-- zbx_trigger.py | |-- zbx_usergroup.py | |-- zbx_user_media.py | `-- zbx_user.py |-- README.md `-- tasks |-- create_template.yml `-- create_user.yml
,目录结构里有很多其它方法,全是我们组在使用的module,全部在github上,大家可以自行前往(我大Redhat! 威武霸气)
然后就是具体使用了:
- name: Create Items
zbx_item:
zbx_server: "{{ server }}"
zbx_user: "{{ user }}"
zbx_password: "{{ password }}"
key: "{{ item.key }}"
name: "{{ item.name | default(item.key, true) }}"
value_type: "{{ item.value_type | default('int') }}"
data_type: "{{ item.data_type | default('decimal') }}"
description: "{{ item.description | default('', True) }}"
multiplier: "{{ item.multiplier | default('', True) }}"
units: "{{ item.units | default('', True) }}"
history: "{{ item.history | default(14, True) }}"
trends: "{{ item.trends | default(omit, True) }}"
template_name: "{{ template.name }}"
applications: "{{ item.applications }}"
zabbix_type: "{{ item.zabbix_type | default('trapper') }}"
interval: "{{ item.interval | default(60, True) }}"
delta: "{{ item.delta | default(0, True) }}"
params: "{{ item.params | default(omit, True) }}"
with_items: "{{ template.zitems | default([]) }}"
register: created_items
我们将写好的变量存放到/var下的yml文件, 引入之后,通过with_items来进行循环,直接调用,zabbix就自动创建了
- name: Include Template OpenShift Cluster
include: ../../lib_zabbix/tasks/create_template.yml
vars:
template: "{{ g_template_openshift_cluster }}"
server: "{{ ozb_server }}"
user: "{{ ozb_user }}"
password: "{{ ozb_password }}"
tags:
- clusterwide
调用这个方法的时候,已经传入template变量了
具体的存储模版是
https://github.com/openshift/openshift-tools/blob/prod/ansible/roles/os_zabbix/vars/template_openshift_master.yml
以上所述就是小编给大家介绍的《如何为zabbix创建自己的的ansible module》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Spark技术内幕
张安站 / 机械工业出版社 / 2015-9-1
Spark是不断壮大的大数据分析解决方案家族中备受关注的新增成员。它不仅为分布式数据集的处理提供一个有效框架,而且以高效的方式处理分布式数据集。它支持实时处理、流处理和批处理,提供了AllinOne的统一解决方案,使得Spark极具竞争力。 本书以源码为基础,深入分析Spark内核的设计理念和架构实现,系统讲解各个核心模块的实现,为性能调优、二次开发和系统运维提供理论支持;本文最后以项目实战......一起来看看 《Spark技术内幕》 这本书的介绍吧!