微服务从小白到专家

这是我学习《微服务从小白到专家》的学习笔记。官方代码地址:https://github.com/banxian-yao/broadview-coupon-center 第三章 第三章直接使用官方代码,所有的依赖服务:mysql, redis, kafka, rabbitmq,自己都使用Docker进行安装,使用docker-compose进行管理,docker-compose.yml内容如下: version: "3.9" services: mysql80: container_name: mysql80 image: mysql ports: - "3306:3306" volumes: - "./data/mysql:/var/lib/mysql" environment: - MYSQL_ROOT_PASSWORD=password zookeeper: container_name: zookeeper image: zookeeper ports: - "2181:2181" kafka: container_name: kafka image: wurstmeister/kafka ports: - "9092:9092" environment: - KAFKA_ADVERTISED_HOST_NAME=192.168.0.106 - KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181 rabbitmq: container_name: rabbitmq image: rabbitmq:management ports: - "5672:5672" - "15672:15672" environment: - RABBITMQ_DEFAULT_USER=guest - RABBITMQ_DEFAULT_PASS=guest redis: container_name: redis image: redis ports: - "6379:6379" 写docker-compose.yml配置的时候需要注意的几点: 升级spring boot到2.5.6版本 里面有commons-collections4和commons-lang3依赖的地方的版本特别注意,在最顶层的pom.xml里面重复写了两个,需要删掉一个。每个module下面也写了版本号,需要把版本号去掉 KAFKA_ADVERTISED_HOST_NAME 改成自己物理机的IP地址 RABBITMQ_DEFAULT_USER 和 RABBITMQ_DEFAULT_PASS 都是guest,而且rabbitmq启动之后必须在admin ui里面手动创建broadview.queue这个queue 第五章 Eureka 对spring-cloud-dependencies的依赖升级到2020.0.4 ...

October 27, 2021

Windows下Rust编译碰到lntddl not found

在学习使用actix-web的时候,使用systemfd、 listenfd来自动编译加载,但是碰到了gcc ... -lntdll not found的提示。使用的toolchain是stable-x86_64-pc-windows-gnu,而且电脑上也安装了msys2,经过搜索找到了解决办法。 需要配置 ~/.cargo/config 写入正面的内容: [target.x86_64-pc-windows-gnu] linker = "C:\\msys64\\mingw64\\bin\\gcc.exe" ar = "C:\\msys64\\mingw64\\bin\\ar.exe" 然后cargo build一切正常

September 4, 2019

Haskell在Windows上的起步

学习Haskel痛苦又快乐的经历 使用Haskell Platform安装的Haskell 安装的时候最好指定安装在c:\Hs目录,因为路径短。然后确保下面三个配置在cabal的配置里面是正确的路径。 extra-prog-path: C:\Hs\msys\usr\bin extra-lib-dirs: C:\Hs\mingw\lib extra-include-dirs: C:\Hs\mingw\include 这种方式安装的Haskell可以顺序安装stack,但是stack不会使用全局的ghc,如果有库使用到了同一个版本的ghc,stack还是傻傻的再去下载一个ghc到自己的目录里面(不应该这么傻,有可能什么都想自己控制吧)。这个情况通过下面的命令设置使用全局的ghc stack config set system-ghc --global true 安装Haskell IDE engine 这个玩意在windows安装是不成功的,可能是路径过长的问题(Windows最长是260个字符),可以把stack的根路径设置到C盘的根目录,设置环境变量STACK_ROOT为C:\stack。 设置完成后,上面一个步骤的system-ghc设置就无效了,因为stack会读取c:\stack\config.yaml以及c:\stack\global-project\stack.yaml两个文件来决定stack更新的方式。这是要注意的。

August 17, 2019

Python项目结构实践

相比于Java和Rust,Python的项目结构没有一个明确的规范,最近在做Python机器学习项目的时候碰到很多的情况是执行文件非常多,有些同学并没有把一些公用的方法和功能进行抽取,而是每个文件都含有读取/写入文件的重复代码。在对setuptools进行一些学习研究,其实Python项目的结构也可以做得非常好,只是大学在赶功能的时候并没有进行一定的规划。下面做一些总结,有了这个结构,可以把随手写的一些项目分享给其他的项目使用。 Setuptools Setuptools是用到构建和分发Python包(Packages或者叫项目)的一个工具,可以: 自动查找/下载/安装/升级项目的依赖包 项目内部多个模块之间的import更加方便 可以把项目用到的数据文件打包到一个压缩文件内 自动查找项目内的包/模块 自动生成可执行程序 以及其他一些好用的功能… 最主要的功能还是管理依赖,进行源代码的分发(可以把代码分发到Pypi上面,或者分发给其他项目使用) 首先需要确保你已经安装了这个工具: pip install -U setuptools 基本用法 在你的项目根目录下面创建一个setup.py文件,写入下面的内容: from setuptools import setup, find_packages setup( name="HelloWorld", version="0.1", packages=find_packages(), ) 这是一个最基本的配置脚本,定义了包名name,版本号version,以及这个项目包含的包列表packages,包列表使用setuptools提供的find_packages自动在目录里面进行查找。 如果你是在开发阶段可以使用下面的命令来安装你的包,以开发模式安装的包不会安装在site-packages目录,而是在site-packages目录下面会建立一个链接(快捷方式)指向到你的开发目录,这样你所做的改动会马上体现出来。 pip install -e . 两种目录结构 假设我们的包名为hello,下面以两种结构分别介绍如何来进行配置 结构一 hello (1) |- hello (2) | |- __init__.py | `- world.py |- main.py `- setup.py 这种目录结构是pythonic的风格,以包名为源代码的根目录名称,然后把所有的模块都放在这个目录下面(即hello(2)目录)。 这种结果的setup.py如下: from setuptools import setup, find_packages setup( name='hello', version='0.1.0', description='' packages=find_packages(), install_requires=[] ) 结构二 hello |- src | `- hello | |- __init__.py | `- world.py |- main.py `- setup.py 这种目录结构把所有的源码文件都放在src子目录里面,这样的习惯可能是Java程序员比较喜欢的。 ...

June 26, 2019

Solr教程-安装运行

Solr是一个分布式高性能全文搜索引擎,是基于Lucene开发的非常流行的企业搜索引擎平台。Solr提供了非常丰富的搜索功能,可以用来构建非常复杂的搜索业务。 这个系列教程旨在介绍Solr的常用功能。 准备 在开始之前你需要准备一些必要的硬件及软件设施: JDK 1.8 (或者更高版本) Solr 7.5.x Postman (可选) CentOS 7.x (本系列以此OS为准) VirtualBox (可选) CentOS可以选择安装,Solr是支持多操作系统的,但是在Linux下体验更好,大部分生产环境也都是Linux系统,建议使用CentOS来学习以及使用Solr。 VirtualBox可以选择安装,如果你是Windows操作系统,建议使用VirtualBox安装CentOS来学习使用Solr。 后面的操作都是基于CentOS 7.x版本操作系统来运行。 安装Solr 安装Solr需要Java 1.8或者更高版本,可以使用java -version命令检查你系统上安装的Java版本。由于Java语言有好几个实现,有些实现并不能非常好的支持Solr,根据Lucene JavaBugs来检查你的Java是否对Solr有很好的支持。Solr支持的操作系统包括Linux, MacOS, Windows。 到https://lucene.apache.org/solr/mirrors-solr-latest-redir.html下载对应操作系统的7.5.0版本的Solr安装包。 solr-7.5.0.tgz 是针对Linux/Unix/MacOS系统的安装包 solr-7.5.0.zip 是针对Windows系统的安装包 solr-7.5.0-src.tgz 是源码包 tar zxf solr-7.5.0.tgz cd solr-7.5.0 bin/solr start 然后使用浏览器打开http://localhost:8983,你就可以看到Solr Admin UI的界面了,这是Solr自带的管理界面,使用非常方便,在里面可以查看状态,管理core,进行查询。 以bin/solr start运行的solr是以standalone模式(非分布式)运行的,如果是学习可以使用此模式快速的尝试。但是建议使用后面将要介绍的SolrCloud模式来运行,SolrCloud模式可以很好的进行扩展,应对海量数据的实时搜索,动态剔除/增加机器节点,动态转移数据分片(shard),所有这些操作都可以不停机进行操作。生产环境也建议使用SolrCloud模式运行。 这是以SolrCloud模式启动solr的命令,只需要添加一个-c参数即可 bin/solr start -c 详细的命令行参数请参考Solr控制脚本参考 SolrCloud启动之后会占用8983端口,默认会启动一个内置的zookeeper实例,占用9983端口(在solr的端口上加1000)。 多节点的SolrCloud安装-生产环境部署 一般生产环境部署会把zookeeper单独部署,其他的solr节点单独部署。 外部Zookeeper 下面假设是生产环境部署zookeeper,建议至少需要三个zookeeper节点。 开发环境以及测试使用一个zookeeper也没有关系。 假设已经有三个机器来运行zookeeper来组建一个小的zookeeper集群: 192.168.1.2 192.168.1.3 192.168.1.4 步骤为:下载zookeeper-3.4.13 -> 解压 -> 配置conf/zoo.cfg -> 启动 curl -o zookeeper-3.4.13.tar.gz 'https://mirrors.tuna.tsinghua.edu.cn/apache/zookeeper/zookeeper-3.4.13/zookeeper-3.4.13.tar.gz' tar -xzvf zookeeper-3.4.13.tar.gz cd zookeeper-3.4.13 cp conf/zoo_sample.cfg conf/zoo.cfg sed -i 's/dataDir=.*/dataDir=.\/data/g' conf/zoo.cfg mkdir data echo -e "\nserver.1=192.168.1.2:2888:3888\nserver.2=192.168.1.3:2888:3888\nserver.3=192.168.1.4:2888:3888" >> conf/zoo.cfg echo 1 > data/myid 解释一下上面的一些命令: ...

March 5, 2019

Solr SearchComponent开发实战

先介绍一下Solr的SearchHandler,SearchHandler是用来处理查询请求的配置。一个SearchHandler里面包含了若干个SearchComponent,实际的逻辑处理就在SearchComponent里面进行处理,还可以自行开发符合自己业务逻辑的SearchComponent,然后经过配置可以灵活的组合各种SearchComponent。各个SearchComponent就像流水线一样处理请求,各自负责自己的逻辑处理。 基于Solr 7.5.0测试 配置 最常使用的/select查询,使用的就是下面默认的配置: <requestHandler name="/select" class="solr.SearchHandler"> <lst name="defaults"> <str name="echoParams">explicit</str> <int name="rows">10</int> </lst> </requestHandler> 里面配置的defaults可以参考官方文档 除了最常使用的默认搜索配置之外,这个/select配置还支持First-components和Last-componets的配置,也就是说在defaults的前面或者后面可以添加一些SearchComponent。具体的流程可以参考下面的图: defaults +-----------+ | query | +------------------+ | facet | +-----------------+ | First-Components | --> | mlt | --> | Last-Components | +------------------+ | highlight | +-----------------+ | ...... | +-----------+ 如果添加了First-Components和Last-Components之后,完整的配置看起来就是下面的样子: <requestHandler name="/select" class="solr.SearchHandler"> <arr name="first-components"> <str>mycomponent1</str> <str>mycomponent2</str> </arr> <lst name="defaults"> <str name="echoParams">explicit</str> <int name="rows">10</int> </lst> <arr name="last-components"> <str>spellcheck</str> <str>mycomponent3</str> </arr> </requestHandler> 还可以完全自定义整个查询的handler的流程,不使用默认的的SearchComponent: <requestHandler name="/select_2" class="solr.SearchHandler"> <arr name="components"> <str>mycomponent1</str> <str>query</str> <str>mycomponent2</str> <str>debug</str> <str>mycomponent3</str> </arr> </requestHandler> 可以结合自己实现的SearchComponents以及官方提供的一起来实现一个符合自己业务逻辑的查询请求。 代码实现 先上代码,看一下一个TestComponent的实现最基本的方法需要实现哪些: ...

March 1, 2019

使用Surprise实现电影推荐

本文记录学习使用Surprise库实现电影数据集MovieLens的推荐系统。 安装 pip pip install numpy pip install scikit-surprise conda conda install -c conda-forge scikit-surprise 先来看一下Surprise官方的例子 from surprise import SVD from surprise import Dataset from surprise.model_selection import cross_validate # 加载movielens-100k数据集,如果本地没有则会自动下载 data = Dataset.load_builtin('ml-100k') # 使用SVD算法 algo = SVD() # 对数据集切成5份进行交叉验证 cross_validate(algo, data, measures=['RMSE', 'MAE'], cv=5, verbose=True) 会看到类似如下的输出结果: Evaluating RMSE, MAE of algorithm SVD on 5 split(s). Fold 1 Fold 2 Fold 3 Fold 4 Fold 5 Mean Std RMSE 0.9311 0.9370 0.9320 0.9317 0.9391 0.9342 0.0032 MAE 0.7350 0.7375 0.7341 0.7342 0.7375 0.7357 0.0015 Fit time 6.53 7.11 7.23 7.15 3.99 6.40 1.23 Test time 0.26 0.26 0.25 0.15 0.13 0.21 0.06 基于用户的推荐 基本思想是先找到给定用户User的相似用户,然后取各相似用户的观影记录推荐给那个给定的用户User。下面使用代码来实现。 ...

January 30, 2019

Solr集群索引以及查询对负载的影响

今天对Solr 7.6.0的集群的索引以及查询对负载的影响做一点测试,记录一下测试结果。 collection的shards和leader分布情况如下 ip和name对应如下表: ip name 172.31.1.253 solr1 172.31.7.73 solr2 172.31.2.236 solr3 172.31.8.221 solr4 172.31.9.13 solr5 索引 测试的点是往没有leader的机器发文档进行索引,统计到的cpu utilization如下图。 从图中可以看出,发往没有leader的机器进行索引,所有机器的cpu都差不多。从而推论不管往哪个机器发文档进行索引,各个机器的cpu utilization都是均匀的。 索引数据如下: title_t字段为随机生成80-100个字符的文本,文本为英文数据。 id为数字。只有这两个字段,每一个批次为100条数据,每个批次间隔5秒。 一次索引完成大概在1.2-1.3秒左右。 下面是索引中文时机器的cpu指标,中文使用单字分词,有title, content。content字段字符数量大概在1000-2000之间。索引时间在5-60秒不等。每一批为100条数据。 从图中可以看到solr5(接收请求)机器负载稍微高一点点。 查询 使用的查询数据为随机生成的200000个关键词,间隔200毫秒。collection里面的数据量在10000左右。 上图分成三个区间来看:15:30之前,15:30-16:05,16:05之后,每一个区间使用不同的查询方法。 另外,solr5那个机器是没有leader在上面的。 15:30之前 这个时间区间使用的是所有请求串行发送,也就是一个接一个的发送,CPU的负载整体都不是很高,所有请求都发送到solr5那个机器上面,很明显的看到solr5机器的cpu负载要高于其他机器,其他机器的负载差不多。 15:30-16:05 这个时间区间使用跟上面一样的方法,只是并发数为10,请求也是只发送到solr5机器上面。可以看到solr5的负载明显高于其他机器。其他4个机器负载差不多。 16:05之后 这个时间区间使用同样的查询数据,10个并发,请求发送到solr1上面。从图上可以看到solr1的负载要高于其他4个机器,其他4个机器负载差不多。这一个测试的结果说明,不管一个节点上有没有leader,这个机器都会去比承担一部分的查询请求。 结论 索引的时候各机器的负载差不多。查询的时候,请求的机器负载高于其他机器,其他机器负载相差不大。所以要集群查询的时候可以使用轮询的方式,每一次查询请求可以发送到不同的机器,这样就可以保证所有机器的负载相当了。

January 10, 2019

在AWS上部署Elasticsearch集群

下面介绍一下在AWS上面部署Elasticsearch集群,结合AWS提供的负载均衡器(Elastic Load Balancing)和Auto Scaling Group功能实现,Elasticsearch的集群搭建。演示的版本为Elasticsearch 6.5.4。 启动EC2实例 首先启动一个EC2的实例,在这个实例里面安装Elasticsearch。 启动新实例,选择Amazon Linux 2 AMI (HVM), SSD Volume Type的AMI(Amazon Machine Image),然后点下一步:配置实例详细信息。配置详细信息界面,只需要选择一下子网即可,然后保留默认配置即可,然后点击下一步:添加存储。保持默认配置,继续点下一步:添加标签。添加标签不需要做配置,继续点下一步:配置安全组。在配置安全组界面,选择一个现有的安全组,或者创建一个都可以,但是有一点需要注意的:保证你选择(创建)的安全组可以让你自己或者所有IP访问。这里选择现有的安全组,后面还会介绍对安全组的配置。在安全组 ID表格里面选择default那一行,然后点击审核和启动。信息没有问题最后点启动。 在弹出的选择现有密钥对或创建新密钥对对话框中选择你已经存在的或者创建一个新的密钥对,这个密钥对是通过ssh来访问aws的ec2实例的。如果这一步不清楚就选择创建新密钥对。 安装Elasticsearch 假设上一次最后创建的密钥对为aws.pem,实例公有DNS(域名)为ec2-100-26-149-233.compute-1.amazonaws.com,使用ssh登录ec2实例: ssh -i aws.pem ec2-user@ec2-100-26-149-233.compute-1.amazonaws.com 实例的公有DNS(IPv4)到ec2的管理界面,点击前面启动的实例,在下面的信息面板就可以看到。 Amazon本身提供的AMI是基于CentOS系列的Linux系统,可以直接使用yum来安装Elasticsearch。根据Elasticsearch官方提供的文档进行安装。 修改文件/etc/yum.repos.d/amzn2-core.repo,在文件后面添加下面的内容: [elasticsearch-6.x] name=Elasticsearch repository for 6.x packages baseurl=https://artifacts.elastic.co/packages/6.x/yum gpgcheck=1 gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch enabled=1 autorefresh=1 type=rpm-md 然后执行下面的命令: sudo yum install -y java-1.8.0 sudo yum install -y elasticsearch sudo systemctl daemon-reload sudo systemctl enable elasticsearch.service 后面两条systemctl命令设置Linux开机启动Elasticsearch。这样就安装好了最新版本的Elasticsearch,下面就需要对其进行配置,以及制作自己的AMI了。 配置Elasticsearch以及制作AMI AWS的IAM IAM是个什么鬼呢。IAM就是AWS在一个账户下面,提供一种机制在SDK或者aws命令行来操作AWS服务的认证方式。一个AWS账户可以创建多个IAM访问权限,Elasticsearch需要使用access_key和secret_key。 在服务里面找到IAM,进入到控制面板里面,点击左侧的用户,然后按添加用户,用户名输入:elasticsearch,在访问类型一栏,把编程访问勾上,然后点击下一步:权限。在设置权限界面选择直接附加现有策略,在下面的列表当中选择AdministratorAccess ,然后点击下一步:标签,保持默认,继续下一步。最后点击创建用户。 创建成功后需要把访问密钥 ID和私有访问密钥保存下面,在下面的配置当中需要使用。 配置Elasticsearch 首先需要对Linux系统做一点配置。修改/etc/security/limits.conf文件,添加如下内容到文件后面: * - nofile 65536 * - nproc 4096 还需要安装一下EC2 Discovery Plugin插件: ...

January 8, 2019

ClojureScript使用npm模块

Javascript现在的生态系统一点也不输Java的生态,而且还在以高速的发展事态占领了企业招聘的热门技术榜单。Javascript社区不仅充满激情、创新,而且非常具有活力,同时也是一个非常开放的社区,从其他的编程语言借鉴了很多优点。 Javascript社区如此丰富的模块与库,作为ClojureScript的使用者也不得不来使用npm的模块。下面简单介绍一下如何在ClojureScript里面使用npm的module,这里用react为例说明如何使用。 Requirement leiningen figwheel cljsbuild React ReactDom Create project lein new figwheel hello-world 直接使用figwheel的templaate来创建项目 Add dependencies 修改project.clj,在cljsbuild修改id为dev的:compiler内容,添加如下代码: :closure-defines {process.env/NODE_ENV "development"} :install-deps true :npm-deps {:react "16.4.1" :react-dom "16.4.1"} id为min的:compiler内容,只是修改了:closure-defines: :closure-defines {process.env/NODE_ENV "production"} :install-deps true :npm-deps {:react "16.4.1" :react-dom "16.4.1"} :closure-defines定义的内容,可以直接在cljs里面进行读取。 Source code ClojureScript代码如下: (ns hello-world.core (:require [react :refer [createElement]] [react-dom :refer [render]])) (enable-console-print!) (js/console.log "Node enviornment is" process.env/NODE_ENV) (def appDiv (.getElementById js/document "app")) (render (createElement "h1" nil "Hello, World!") appDiv) require部分的使用跟cljs的包一样,可以直接从一个包require函数以及对象,剩下的部分就跟js使用react/react-dom的方式一样,调用render函数渲染元素到指定的html节点下面。 Run lein figwheel 使用此命令运行代码,编译完成后figwheel会自动打开浏览器访问:http://localhost:3449/index.html,完成后你会看到下面的内容:

July 16, 2018