加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

高CPU业务场景下的任务分发方案Gearman搭建一览

发布时间:2020-12-14 06:14:15 所属栏目:Java 来源:网络整理
导读:??Gearman是当年LiveJournal用来做图片resize的,大家也明白图片resize是一个高CPU的操作,如果让web网站去做这个高CPU的功能,有可能会拖垮你的 web应用,那本篇我们来看看gearman是如何解决这个问题的,它的架构图类似下面这样: 从上面这张图,你应该会看

  

  ??Gearman是当年LiveJournal用来做图片resize的,大家也明白图片resize是一个高CPU的操作,如果让web网站去做这个高CPU的功能,有可能会拖垮你的

web应用,那本篇我们来看看gearman是如何解决这个问题的,它的架构图类似下面这样:

从上面这张图,你应该会看到,Gearman是由三个部分组成:

? ? 这个就是Gearman的Job Server,通过它对Client 和 jobwork 进行桥接,是不是想起来了中介者模式。。。

? ?Gearman提供了Client API 给客户端调用,Client只需要将一个高CPU的业务函数名丢给Job Server,然后等待JobServer的返回执行结果。

? ?Gearman提供了work API 给work客户端进行调用。jobserver会根据后端的work集群的负载情况,分发给一个合适的work去执行,并等待结果。

说到这里,你应该就明白了,本质上它属于那种分布式的RPC调用,而且非常牛逼的地方在于Client 和 Work 可以用不同的语言实现。

? ? ? ? ?目前gearman的JobServer 有C,JAVA,Perl三种语言实现,由于C版本的JobServer是最活跃的,所以这里采用目前最新的1.1.17版本的gearmand在CentOS

上进行安装部署。

? ? 可以通过官网http://gearman.org/getting-started/中的getting-started进行快速安装。

基础依赖库安装和gearmand下载

yum -y install boost-devel gperf libevent-devel libuuid-devel gcc44 gcc-c++ wget https: cd gearmand-. tar xzvf gearmand-. cd gearmand-. [root@localhost gearmand-. aclocal.m4 build-aux configure.ac gear_config. libgearman- libhashkit- AUTHORS ChangeLog COPYING gearmand libgearmancore libhostile Makefile. benchmark configmake.h docs HACKING libgearman- bin configure examples libgearman libhashkit m4 NEWS tests

然后就是常规的./configure --prefix=/usr/myapp/gearman && make && make install ?这个过程超级慢,可以出去抽跟烟,

./configure --prefix=/usr/myapp/gearman && make && make install

若干年后,当你看到这个就算安装成功了。。。还是得恭喜一下。。。。至少没让你踩到缺少各种依赖包的界面。

See any operating system documentation about shared libraries more information,such the ld() and ld.so( ---------------------------------------------------------------------- /usr/bin/mkdir -p /usr/bin/install -c -m man/gearman_worker_create. man/gearman_worker_define_function. man/gearman_worker_echo. man/gearman_worker_errno. man/gearman_worker_error. man/gearman_worker_free. man/gearman_worker_function_exist. man/gearman_worker_grab_job. man/gearman_worker_options. man/gearman_worker_register. man/gearman_worker_remove_options. man/gearman_worker_remove_servers. man/gearman_worker_set_context. man/gearman_worker_set_log_fn. man/gearman_worker_set_namespace. man/gearman_worker_set_options. man/gearman_worker_set_timeout. man/gearman_client_has_option. man/gearman_client_options_t. man/gearman_task_attr_init. man/gearman_task_attr_init_background. man/gearman_task_attr_init_epoch. man/gearman_task_attr_t. man/gearman_worker_set_identifier. man/gearman_worker_set_workload_free_fn. man/gearman_worker_set_workload_malloc_fn. man/gearman_worker_st. man/gearman_worker_timeout. man/gearman_worker_unregister. man/gearman_worker_unregister_all. man/gearman_worker_wait. man/gearman_worker_work. man/libgearman. /bin/sh ./libtool --mode=install /usr/bin/install -c gearmand/gearmand libtool: install: /usr/bin/install -c gearmand/gearmand /usr/myapp/gearman/sbin/ /usr/bin/mkdir -p /bin/sh ./libtool --mode=install /usr/bin/install -c bin/gearman bin/gearadmin libtool: install: /usr/bin/install -c bin/.libs/gearman /usr/myapp/gearman/bin/ libtool: install: /usr/bin/install -c bin/gearadmin /usr/myapp/gearman/bin/ make[]: Leaving directory `/usr/myapp/gearmand-. make[]: Leaving directory `/usr/myapp/gearmand-. make[]: Leaving directory `/usr/myapp/gearmand-.

启动gearmand,你也可以用 -d 开启后台运行的模式,这里加上DEBUG只是看一下实时的DEBUG信息,如下所示:

[root@localhost myapp]# cd /usr/myapp/ [root@localhost bin]# cd /usr/myapp/ [root@localhost sbin]# ./gearmand -- ./gearmand: Could not open log file , DEBUG -- :: [ main ] THREADS: -> libgearman-server/gearmand.cc: INFO -- :: [ main ] Initializing Gear on port with SSL: INFO -- :: [ main ] Starting up with pid ,verbose DEBUG -- :: [ main ] Method libevent: epoll -> libgearman-server/gearmand.cc: DEBUG -- :: [ main ] Trying to listen on .: -> libgearman-server/gearmand.cc: INFO -- :: [ main ] Listening on .: ( DEBUG -- :: [ main ] Trying to listen on ::: -> libgearman-server/gearmand.cc: INFO -- :: [ main ] Listening on ::: ( DEBUG -- :: [ main ] Creating wakeup pipe -> libgearman-server/gearmand.cc: DEBUG -- :: [ main ] Creating threads -> libgearman-server/gearmand.cc: DEBUG -- :: [ main ] Initializing libevent IO thread -> libgearman-server/gearmand_thread.cc: DEBUG -- :: [ main ] Creating IO thread wakeup pipe -> libgearman-server/gearmand_thread.cc: DEBUG -- :: [ main ] Thread created -> libgearman-server/gearmand_thread.cc: DEBUG -- :: [ main ] Initializing libevent IO thread -> libgearman-server/gearmand_thread.cc: DEBUG -- :: [ main ] Creating IO thread wakeup pipe -> libgearman-server/gearmand_thread.cc: DEBUG -- :: [ main ] Thread created -> libgearman-server/gearmand_thread.cc: DEBUG -- :: [ main ] Initializing libevent IO thread -> libgearman-server/gearmand_thread.cc: DEBUG -- :: [ main ] Creating IO thread wakeup pipe -> libgearman-server/gearmand_thread.cc: DEBUG -- :: [ main ] Thread created -> libgearman-server/gearmand_thread.cc: DEBUG -- :: [ main ] Initializing libevent IO thread -> libgearman-server/gearmand_thread.cc: DEBUG -- :: [ main ] Creating IO thread wakeup pipe -> libgearman-server/gearmand_thread.cc: DEBUG -- :: [ main ] Thread created -> libgearman-server/gearmand_thread.cc: DEBUG -- :: [ main ] replaying queue: begin -> libgearman-server/gearmand.cc: DEBUG -- :: [ main ] __replay -> libgearman-server/plugins/queue//queue.cc: DEBUG -- :: [ main ] replaying queue: end -> libgearman-server/gearmand.cc: INFO -- :: [ main ] Adding listening socket ( INFO -- :: [ main ] Adding listening socket ( DEBUG -- :: [ main ] Adding wakeup pipe -> libgearman-server/gearmand.cc: DEBUG -- :: [ main ] Entering main loop -> libgearman-server/gearmand.cc: DEBUG -- :: [ ] Entering thread loop -> libgearman-server/gearmand_thread.cc: DEBUG -- :: [ ] Entering thread loop -> libgearman-server/gearmand_thread.cc: DEBUG -- :: [ main ] staring up Epoch thread -> libgearman-server/timer.cc: DEBUG -- :: [ ] Entering thread loop -> libgearman-server/gearmand_thread.cc: DEBUG -- :: [ ] Entering thread loop -> libgearman-server/gearmand_thread.cc:

最后通过netstat,lsof,ps -ef 三板斧可以找出来gearmand大概占用的端口号,就如你看到的默认占用的4370端口,

[root@localhost ~]# netstat - Proto Recv-Q Send- tcp .: .:* tcp .: .:* tcp .: .:* tcp .: .:* tcp6 ::: :::* tcp6 ::: :::* tcp6 ::: :::* tcp6 ::: :::* tcp6 ::: :::* tcp6 ::: :::* tcp6 .: :::* [root@localhost ~]# ps -ef | root : pts/ :: grep --color= [root@localhost ~]# lsof -i : COMMAND PID USER FD TYPE DEVICE SIZE/ gearmand root IPv6 0t0 TCP * [root@localhost ~]#

? ? ? ?为了演示,我可以做一个简单的 “字符串.ToUpper”的业务逻辑来验证一下这个架构是否可以跑的起来。

? ? 首先需要在mvn仓库中拉一下jar包:http://www.mvnrepository.com/artifact/org.gearman/gearman-java/0.6。

?

<1> UpperFunction类,这个类用于定义work具体的业务逻辑:

UpperFunction String param = ByteUtils.fromUTF8Bytes(([]) [] mybytes = GearmanJobResultImpl result = GearmanJobResultImpl(mybytes,,mybytes,,-1,-1 SimpleDateFormat formatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss" String dateString = formatter.format( System.out.println(String.format("当前时间:%s,过来的字符串:%s,返回的字符串:%s",dateString,param, }

<2> ?将UpperFunction注册到gearmand中,从红色代码可以看到,其实是一个kv模式,这里的key="myUpperFunc”的对应执行业务就是new UpperFunction。

? ? ? ? 这样Client只需要传递一个"myUpperFunc",Gearmand就知道这个“字符串”对应是哪一个处理函数。。。

GearmanWorker worker = GearmanNIOJobServerConnection conn = GearmanNIOJobServerConnection("192.168.23.170",4730 System.out.println("启动服务。。。。" }

? ? <1> GearSubmit类【简单的一个包装类,随便定义】

process() GearmanJobServerConnection conn = GearmanNIOJobServerConnection("192.168.23.170",4730 GearmanClient client = client.addJobServer(conn); [] data = ByteUtils.toUTF8Bytes("hello,world" GearmanJob job = GearmanJobImpl.createJob(functionName,data, GearmanJobResult jobResult = Future gearmanJobResult = jobResult = [] resultBytes = String value = System.out.println("执行结束" }

<2> 主程序,开多线程并发的去执行。

main(String[] args) ExecutorService executorService = Executors.newFixedThreadPool(100 ( i = 0; i < 10000; i++ executorService.execute( Gearsubmit submit= } (InterruptedException | }

好了,一切都准备好了,接下来为了演示,演示就是解释,我用Jar2Exe把work程序导出成jar再转换成exe,如下图:

然后我把3.exe开成5个实例,client用100个线程的线程池并发调用,当然一切都是模拟。。。。可以看到,当我client启动的时候,5个work都在执行,

如果这个时候,你把某一个work停止了,jobserver也不再将任务丢给它,而是转给其他负载相对小的work继续执行。

好了,本篇就说到这里,希望对你有帮助。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读