月盾的博客

pm2的fork模式和cluster模式的区别

月盾
pm2的fork模式和cluster模式的区别 fork模式 pm2默认启动的是fork模式,是以单核单进程运行的,在fork模式下可以直接运行coffee-script,PHP,python。 参考:http://pm2.keymetrics.io/docs/tutorials/using-transpilers-with-pm2 运行非js语言必须设置运行模式为fork_mode cluster模式 cluster模式可以根据CPU数量进行实例扩展,可以开启多进程而不需要修改代码。可提高程序性能和可靠性。类似于分布式系统,只不过是在单台机器上开启多实例,而pm2自带负载均衡。 ** 使用方法 ** pm2 start app.js -i max 使用-i参数,max代表最大CPU进程数 也可以使用文件方式: processes.json文件: { "apps" : [{ "script" : "api.js", "instances" : "max", "exec_mode" : "cluster" }] } pm2 start processes.json

本地producer和consumer连接不上远程kafka服务

月盾
Hostname and port the broker will advertise to producers and consumers. If not set, it uses the value for “listeners” if configured. Otherwise, it will use the value returned from java.net.InetAddress.getCanonicalHostName(). advertised.listeners=PLAINTEXT://ip:9092 打开advertised.listeners=PLAINTEXT://ip:9092配置,ip为kafka服务ip

推荐在Nodejs使用的java常用技术和工具

月盾
作为Nodejs开发者可能会对java中常用的一些技术工具不太关心,主要原因大概除了语言级别的间隙就是Nodejs相对于java来说比较轻量级,大多用来开发简单系统,用不到其他工具。根据经验来说,开发相同功能的系统,Nodejs的开发周期和代码体量上也会比Java少太多,毕竟java出生年代长,生态丰富,如果不使用几个框架都感觉不是在开发系统。而Nodejs要开发一个web系统基本使用express或koa就差不多够了。所以对于Nodejs开发者来说,分布式,消息队列,远程调用等技术接触就少些。当然,不用这些技术其实也不会有太大影响,但是对于一个有追求有理想的码农来说我们的眼界不应该局限于系统能运行就行。 下面就来介绍一些可以在nodejs中使用的JAVA常用工具和技术。 elasticsearch ElasticSearch(以下简称ES)是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。看见了吧,这就是一个使用JAVA开发的全文搜索引擎,到底有什么用呢?就是可以提供像google和百度一样的搜索功能,就算不需要这样功能,也可以用于管理后台的字段搜索,大家知道数据库的搜索效率比较差,有索引的字段还好,没有的就很慢了,这时ES就可以派上用场了,把数据同步进ES,不论查询列表还是以字段搜索都是极快的,是redis缓存的很好补充。 ELK ELK(ElasticSearch,LogStash,Kibana)是三个工具的组合, Logstash是一款轻量级的日志搜集处理框架,可以方便的把分散的、多样化的日志搜集起来,并进行自定义的处理,然后传输到指定的位置,比如某个服务器或者文件。 Kibana是一个使用nodejs开发的web应用,用于查询和操作ES,就是一个ES的图形界面。 如果nodejs系统布署在多台服务器,那么查看日志是件很头疼的事,你不知道请求发送到哪一台服务器,需要挨个查看,如果服务超过5台,这绝对是噩梦。这时候ELK就是很好的解决方案,LogStash收集每一台服务器的日志统一存到ES中,利用ES的优点,查询任何关键字都很快很方便。 消息中间件(kafka) 拿用户注册为例,需要发送邮件,短信,这两个服务之间本没有关联关系,但我们的一贯作风是用户注册的时候调用邮件服务,短信服务,严谨一点会放在事务中操作,假如一个服务失败可能会让事务回滚,所有操作都失败。这是一种情况,另一种情况是如果要再注册后加积分,那么就得改代码,要是有更多服务要添加就得每次改代码发布,启停服务,不送积分了又要删代码,这就是耦合度太高导致的结果。使用消息中间件不仅能保证服务完整性还可以有效解耦,有兴趣可以去了解kafka,rabbitMQ,roketMQ等消息中间件。 远程调用RPC 通俗的来讲就是两台服务器A和B,A服务器直接调用B服务器上的函数,如果没有一个具体事例很难理解A服务器怎么可能调用到B服务器的函数,感兴趣可下载尝试:https://github.com/yuedun/nodejs-grpc 那么为什么要用rpc呢?A服务器要调用B服务的资源直接用http提供接口不就行了吗?其实http也算是一种远程调用,而且也比较简单直观,但是其效率较低,调用成本高,三次握手耗时,甚至请求头的数据量比请求体还大。那么就需要一种更高效的调用协议了——rpc。为什么需要RPC,而不是简单的HTTP接口 总结:以上的这些工具和技术和语言并没有绑定,java可以使用,nodejs也可以使用,推荐理由:投入成本小,使用收益高。
为什么需要RPC,而不是简单的HTTP接口

为什么需要RPC,而不是简单的HTTP接口

月盾
目前有很多Java的RPC框架,有基于Json的,有基于XML,也有基于二进制对象的。 论复杂度,RPC框架肯定是高于简单的HTTP接口的。但毋庸置疑,HTTP接口由于受限于HTTP协议,需要带HTTP请求头,导致传输起来效率或者说安全性不如RPC。 现在问题是,遇到怎样的瓶颈了才需要或者说更适合用RPC(比如像阿里这么大的请求并发量,简单的HTTP肯定达不到预期),但问题是大家所在的公司,要有像阿里这么大的量是比较少的,甚至说1/1000的量可能都没有,那我们还需要使用RPC吗? 技术应该不是为了使用新技术而去使用,而应该是旧技术存在某些瓶颈,存在难以支撑或者扩展性越老越差等问题暴露出来之后,用新技术来进行解决。 那RPC最大的优点,或者说它相比简单的HTTP接口,它的优势、更适合它的业务场景是怎样呢?简单的HTTP又哪里不足,哪些场景明显不太适合呢? RPC=Remote Produce Call 是一种技术的概念名词. HTTP是一种协议,RPC可以通过HTTP来实现,也可以通过Socket自己实现一套协议来实现.所以楼主可以换一个问法,为何RPC还有除HTTP 之外的实现法,有何必要.毕竟除了HTTP实现外,私有协议不具备通用性.那么我想唯一的答案就在于HTTP不能满足其业务场景的地方,所以这个就要具体 案例具体分析了. http接口是在接口不多、系统与系统交互较少的情况下,解决信息孤岛初期常使用的一种通信手段;优点就是简单、直接、开发方便。利用现成的http协议 进行传输。但是如果是一个大型的网站,内部子系统较多、接口非常多的情况下,RPC框架的好处就显示出来了,首先就是长链接,不必每次通信都要像http 一样去3次握手什么的,减少了网络开销;其次就是RPC框架一般都有注册中心,有丰富的监控管理;发布、下线接口、动态扩展等,对调用方来说是无感知、统 一化的操作。第三个来说就是安全性。最后就是最近流行的服务化架构、服务化治理,RPC框架是一个强力的支撑。 rpc是一种概念,http也是rpc实现的一种方式。论复杂度,dubbo/hessian用起来是超级简单的。最近用dubbo和hessian比较多,http的几乎都被废弃了。 至于为什么用,其实很简单,业务场景不一样。我最早的单位所有的代码都在一个工程里,一次要发布几百m的代码。这种架构是非常有利于小程序的。但是我们为什么要应用rpc层呢,一个功能,一套代码下来不就解决了么?我觉得有几个好处: 1 灵活部署 2 解耦 至于为什么,当你用到的时候,你会体会。 系统做大了,肯定是需要做微服务的。 现在我们做电商就是这样,单独有一个订单系统,支付系统,商品系统,用户系统。都是分开部署,单独上线的。 但我们交互是用HTTP接口来交互的,我想转用RPC,但问题是我现在还没发现为什么需要用RPC,我还没能理解它的作用和意义。 用http交互其实就已经属于rpc了。 RPC:远程过程调用。RPC的核心并不在于使用什么协议。RPC的目的是让你在本地调用远程的方法,而对你来说这个调用是透明的,你并不知道这个调用的方法是部署哪里。通过RPC能解耦服务,这才是使用RPC的真正目的。RPC的原理主要用到了动态代理模式,至于http协议,只是传输协议而已。简单的实现可以参考spring remoting,复杂的实现可以参考dubbo。 RPC是一个软件结构概念,是构建分布式应用的理论基础。就好比为啥你家可以用到发电厂发出来的电?是因为电是可以传输的。至于用铜线还是用铁丝还是其他 种类的导线,也就是用http还是用其他协议的问题了。这个要看什么场景,对性能要求怎么样。比如在java中的最基本的就是RMI技术,它是java原 生的应用层分布式技术。我们可以肯定的是在传输性能方面,RMI的性能是优于HTTP的。那为啥很少用到这个技术?那是因为用这个有很多局限性,首先它要 保证传输的两端都要要用java实现,且两边需要有相同的对象类型和代理接口,不需要容器,但是加大了编程的难度,在应用内部的各个子系统之间还是会看到 他的身影,比如EJB就是基于rmi技术的。这就与目前的bs架构的软件大相径庭。用http必须要服务端位于http容器里面,这样减少了网络传输方面 的开发,只需要关注业务开发即可。所以在架构一个软件的时候,不能一定根据需求选定技术。 转自:https://www.cnblogs.com/winner-0715/p/5847638.html

请求发送到Nodejs服务器以后响应非常慢

月盾
在项目中遇到过这种情况:请求发送后迟迟没有响应,但也并没有报错,在代码中一步步调试都没有发现问题,明明已经走到最后返回数据一步了客户端却没有返回。原因是在中间件中使用了redis或memcache缓存,然后连接缓存服务失败,然后就会一直等待,直到连接缓存超时才会继续执行后续操作。

读写数据库与读写文件哪个更快?

月盾
由于开发物流信息网,关于这个问题也是最近才想到的,就是到底读文件更快还是读数据库更快,能快多少,书生也搜索过,没见有网友就这个问题答复过, 也可能是太简单的缘故,我们本文还是来实测一下,由于时间关系,VC还没装,书生先用PHP测试了一下,下次有时间在C/C++上补充测试到本文来,因为 PHP的底层解析应该也是基于C的,所以估计两者环境测试结果差不多,小问题大收获,现在就来看一下测试过程及结果。 测试程序如下: //说明1:由于读数据库语句调用简单的封包函数两次,所以把读文件也改成连续调用两次,数据库记录ID为1就在第一条,并且唯一索引。 //说明2:测试两次一次是4K数据,一次是整形数据 set_time_limit(0); function fnGet($filename) { $content = file_get_contents($filename); return $content; } function fnGetContent($filename) { $content = fnGet($filename); return $content; } $times=100000; echo '数据库查询结果:<br/>'; //--------------------------------- $begin=fnGetMicroTime(); for($i=0;$i<$times;$i++) { $res=$dbcon->mydb_query("SELECT log_Content FROM blog WHERE log_ID='1'"); $row=$dbcon->mydb_fetch_row($res); $content=$row[0]; } echo 'fetch_row '.$times.' 次时间:<font color=red>'.(fnGetMicroTime()-$begin).'</font>秒<br/>'; //--------------------------------- $begin=fnGetMicroTime(); for($i=0;$i<$times;$i++) { $res=$dbcon->mydb_query("SELECT log_Content FROM blog WHERE log_ID='1'"); $row=$dbcon->mydb_fetch_array($res); $content=$row['log_Content']; } echo 'fetch_array '.$times.' 次时间:<font color=red>'.(fnGetMicroTime()-$begin).'</font>秒<br/>'; //--------------------------------- $begin=fnGetMicroTime(); for($i=0;$i<$times;$i++) { $res=$dbcon->mydb_query("SELECT log_Content FROM blog WHERE log_ID='1'"); $row=$dbcon->mydb_fetch_object($res); $content=$row->log_Content; } echo 'fetch_object '.

Dockerfile CMD命令没有执行npm start

月盾
Dockerfile FROM hub.c.163.com/public/nodejs:6.11.0 WORKDIR /app COPY . /app RUN npm install EXPOSE 3000 # CMD ["npm", "start"] ENTRYPOINT ["npm", "start"] docker ps: CONTAINER ID IMAGE COMMAND 59988bd90894 myfd "/bin/sh -c '/usr/..." 在Dockerfile中配置了CMD ["npm", "start"],docker ps后显示COMMAND为"/bin/sh -c '/usr/..." 改为ENTRYPOINT ["npm", "start"]就可以了

sequelize外键关联报错SequelizeDatabaseError: Cant write; duplicate key in table #sql-454_d

月盾
Assistance.belongTo(User)会报以下错误: ALTER TABLE `assistance` ADD CONSTRAINT `assistance_user_id_foreign_idx` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE NO ACTION ON UPDATE CASCADE; Unhandled rejection SequelizeDatabaseError: Can't write; duplicate key in table '#sql-454_d' at Query.formatError (/home/hale/workspace/issue-tracking-system/node_modules/sequelize/lib/dialects/mysql/query.js:223:16) at Query.connection.query [as onResult] (/home/hale/workspace/issue-tracking-system/node_modules/sequelize/lib/dialects/mysql/query.js:55:23) at Query.Command.execute (/home/hale/workspace/issue-tracking-system/node_modules/mysql2/lib/commands/command.js:30:12) at Connection.handlePacket (/home/hale/workspace/issue-tracking-system/node_modules/mysql2/lib/connection.js:515:28) at PacketParser.onPacket (/home/hale/workspace/issue-tracking-system/node_modules/mysql2/lib/connection.js:94:16) at PacketParser.executeStart (/home/hale/workspace/issue-tracking-system/node_modules/mysql2/lib/packet_parser.js:77:14) at Socket.<anonymous> (/home/hale/workspace/issue-tracking-system/node_modules/mysql2/lib/connection.js:102:29) at emitOne (events.js:115:13) at Socket.emit (events.js:210:7) at addChunk (_stream_readable.js:264:12) at readableAddChunk (_stream_readable.js:251:11) at Socket.Readable.push (_stream_readable.js:209:10) at TCP.onread (net.

typescript开发sequelize返回ModelInstance或null值无法获取属性值

月盾
从图片中的代码可以看出 let userRecord = await item.getUser();获取到的是Bluebird<UserInstance | null>类型,然后在下面获取对象属性的时候报错,错误信息是: [ts] Object is possibly 'null'. let userRecord: UserInstance | null 说对象可能是null,所以无法获取其中的属性。遇到这种情况请设置typescript的编译选项,tsconfig.json文件中的 "strictNullChecks": true, /* Enable strict null checks. */ 默认是true,即严格null检查,设置为falsse即可。

sequelize.js不能将驼峰camelCased命名转化为下划线underscored命名

月盾
定义Model的时候有这样两个参数: underscored,underscoredAll, Converts all camelCased columns to underscored if true. Will not affect timestamp fields named explicitly by model options and will not affect fields with explicitly set field option 其意思是说转化所有驼峰字段为下划线字段,但实际情况并不是如此。 var Model = sequelize.define<ModelInstance, ModelAttributes>( 'Assistance', { title: Sequelize.STRING, description: Sequelize.STRING, fullName: Sequelize.STRING }, { underscored: true, tableName: 'assistance', charset: 'utf8', collate: 'utf8_unicode_ci' } ); CREATE TABLE IF NOT EXISTS `assistance` (`id` INTEGER NOT NULL auto_increment , `title` VARCHAR(255), `description` VARCHAR(255), `fullName` VARCHAR(255), `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_unicode_ci; 其中fullName字段在创建表的时候还是和模型中保持一致,并没有转换为full_name,underscored的设置其实只影响到了createdAt和updatedAt等内置字段。 在github上也有相关讨论:https://github.