女朋友讓我更新項(xiàng)目了
大家好,我是3y
今天更新下austin的番外篇#02(本來想著休息下,沒辦法,女朋友讓我趕緊更新,說好多人等著看呢,于是我就很不情愿又去了一趟圖書館。花了一個(gè)下午寫好了這篇文章)
這不會周末點(diǎn)進(jìn)來就不給點(diǎn)贊和在看吧?
前幾天在朋友圈和群吐槽了下:“我搭Kafka一個(gè)晚上都還沒成功”。有好多同學(xué)都發(fā)出了自己親生經(jīng)歷的教程給我(甚至在發(fā)送之前還主動驗(yàn)證了下該內(nèi)容有沒有問題),我依靠著這么多教程也順利搭出來了。(十分感謝這些大佬)
之前剛建項(xiàng)目的時(shí)候有很多同學(xué)都說要跟著我一起做austin,我嘴上沒答應(yīng)。但是真正直接過來提pull request的,我是沒辦法拒絕的(只要你的代碼是合理的,對項(xiàng)目整個(gè)結(jié)構(gòu)或流程是有幫助,我是非常歡迎的)

這個(gè)項(xiàng)目的初衷一方面是能夠成為Java小白的項(xiàng)目,另一方面是我也能從中學(xué)到東西。每個(gè)人都有自己熟悉的領(lǐng)域,我對很多東西可能都是不了解或者說是片面的(不要以為我寫文章多了,我就啥都懂,這是不可能的)
上周有個(gè)在評論區(qū)討論得挺多的問題:MySQL數(shù)據(jù)庫中創(chuàng)建時(shí)間/更新時(shí)間字段為什么用int類型?
當(dāng)我被問到,我在建表的時(shí)候?yàn)槭裁从胕nt,而不是datetime或者timestamp這種MySQL提供的日期字段類型呢?我當(dāng)時(shí)的第一反應(yīng)是:“存儲時(shí)間戳進(jìn)去不是很正常嗎?我一直都這樣干的”
于是我抱著好奇的心態(tài)問了一遍相關(guān)留言的大佬,用datetime有什么好處,總結(jié)大概兩點(diǎn)吧:
在數(shù)據(jù)庫上看時(shí)間直觀(不需要轉(zhuǎn)義) 可以自動更新(updated字段可以不由程序員控制,當(dāng)更新記錄時(shí),框架自動更新該自動)
至于int和datetime的存儲大小和處理速度其實(shí)并不在我的考慮范圍內(nèi),但最終還是沒能讓我將int改成datetime。
一方面,我在以前的公司幾乎所有的表都是int類型(我用習(xí)慣了,我承認(rèn)了,我是懶惰的),另一方面我認(rèn)為int是最通用的(跨平臺,跨數(shù)據(jù)庫,跨語言,也不需要管時(shí)區(qū)什么的)。
每個(gè)應(yīng)用程序下都會有對應(yīng)的TimeUtils工具類,獲取一個(gè)時(shí)間戳和格式化一個(gè)時(shí)間戳對于程序而言就只是調(diào)用一個(gè)方法,用得也不糟心。而提出最主要的直觀,這個(gè)確實(shí)會帶來好處,但按照我以往的工作經(jīng)歷上貌似也好像不會提高很多效率。
如果有更好的觀點(diǎn),歡迎在評論區(qū)繼續(xù)留言探討,并且我希望:提出疑問或者反對的同時(shí),最好能說明理由(這樣會提高我們交流的效率)。
00、搭建Kafka環(huán)境
下周要在austin項(xiàng)目下引入kafka組件了,今天也來記錄下搭建kafka的過程,好讓跟著做項(xiàng)目的同學(xué)可以快速搭建起來。了解過Kafka的同學(xué)可能就知道,Kafka還得依賴Zookeeper組件,這要是在原生的環(huán)境下搭建Kafka和Zookeeper還是比較麻煩的。

我個(gè)人是不喜歡把時(shí)間耗費(fèi)在搭建環(huán)境上的,所以就直接上Docker/Docker Compose吧。
環(huán)境:CentOS 7.6 64bit
01、Docker環(huán)境
首先我們需要安裝GCC相關(guān)的環(huán)境:
yum?-y?install?gcc
yum?-y?install?gcc-c++
安裝Docker需要的依賴軟件包:
yum?install?-y?yum-utils?device-mapper-persistent-data?lvm2
設(shè)置國內(nèi)的鏡像(提高速度)
yum-config-manager?--add-repo?http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
更新yum軟件包索引:
yum?makecache?fast
安裝DOCKER CE(注意:Docker分為CE版和EE版,一般我們用CE版就夠用了)
yum?-y?install?docker-ce
啟動Docker:
systemctl?start?docker
下載回來的Docker版本::
docker?version
來一發(fā)HelloWorld:
docker?run?hello-world

02、Docker compose環(huán)境
Compose 是用于定義和運(yùn)行多容器 Docker 應(yīng)用程序的工具。通過 Compose,您可以使用 YML 文件來配置應(yīng)用程序需要的所有服務(wù)。然后,使用一個(gè)命令,就可以從 YML 文件配置中創(chuàng)建并啟動所有服務(wù)
運(yùn)行以下命令以下載 Docker Compose 的當(dāng)前穩(wěn)定版本:
sudo?curl?-L?"https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname?-s)-$(uname?-m)"?-o?/usr/local/bin/docker-compose
將可執(zhí)行權(quán)限應(yīng)用于二進(jìn)制文件:
sudo?chmod?+x?/usr/local/bin/docker-compose
創(chuàng)建軟鏈:
sudo?ln?-s?/usr/local/bin/docker-compose?/usr/bin/docker-compose
測試是否安裝成功:
docker-compose?--version

03、compose 文件
新建搭建kafka環(huán)境的docker-compose.yml文件,內(nèi)容如下:
version:?'3'
services:
??zookepper:
????image:?wurstmeister/zookeeper????????????????????#?原鏡像`wurstmeister/zookeeper`
????container_name:?zookeeper????????????????????????#?容器名為'zookeeper'
????volumes:?????????????????????????????????????????#?數(shù)據(jù)卷掛載路徑設(shè)置,將本機(jī)目錄映射到容器目錄
??????-?"/etc/localtime:/etc/localtime"
????ports:???????????????????????????????????????????#?映射端口
??????-?"2181:2181"
??kafka:
????image:?wurstmeister/kafka????????????????????????????????#?原鏡像`wurstmeister/kafka`
????container_name:?kafka????????????????????????????????????#?容器名為'kafka'
????volumes:?????????????????????????????????????????????????#?數(shù)據(jù)卷掛載路徑設(shè)置,將本機(jī)目錄映射到容器目錄
??????-?"/etc/localtime:/etc/localtime"
????environment:???????????????????????????????????????????????????????#?設(shè)置環(huán)境變量,相當(dāng)于docker?run命令中的-e
??????KAFKA_BROKER_ID:?0???????????????????????????????????????????????#?在kafka集群中,每個(gè)kafka都有一個(gè)BROKER_ID來區(qū)分自己
??????KAFKA_ADVERTISED_LISTENERS:?PLAINTEXT://ip:9092?#?TODO?將kafka的地址端口注冊給zookeeper
??????KAFKA_LISTENERS:?PLAINTEXT://0.0.0.0:9092????????????????????????#?配置kafka的監(jiān)聽端口
??????KAFKA_ZOOKEEPER_CONNECT:?zookeeper:2181????????????????#?zookeeper地址
??????KAFKA_CREATE_TOPICS:?"hello_world"
????ports:??????????????????????????????#?映射端口
??????-?"9092:9092"
????depends_on:?????????????????????????#?解決容器依賴啟動先后問題
??????-?zookepper
??kafka-manager:
????image:?sheepkiller/kafka-manager?????????????????????????#?原鏡像`sheepkiller/kafka-manager`
????container_name:?kafka-manager????????????????????????????#?容器名為'kafka-manager'
????environment:????????????????????????#?設(shè)置環(huán)境變量,相當(dāng)于docker?run命令中的-e
??????ZK_HOSTS:?zookeeper:2181??#??zookeeper地址
??????APPLICATION_SECRET:?xxxxx
??????KAFKA_MANAGER_AUTH_ENABLED:?"true"??#?開啟kafka-manager權(quán)限校驗(yàn)
??????KAFKA_MANAGER_USERNAME:?admin???????#?登陸賬戶
??????KAFKA_MANAGER_PASSWORD:?123456??????#?登陸密碼
????ports:??????????????????????????????#?映射端口
??????-?"9000:9000"
????depends_on:?????????????????????????#?解決容器依賴啟動先后問題
??????-?kafka
文件內(nèi)TODO 中的ip需要改成自己的,并且如果你用的是云服務(wù)器,那需要把端口給打開。

04、啟動kafka
在存放docker-compose.yml的目錄下執(zhí)行啟動命令:
docker-compose?up?-d
可以查看下docker鏡像運(yùn)行的情況:
docker?ps?

進(jìn)入kafka 的容器:
docker?exec?-it?kafka?sh
創(chuàng)建一個(gè)topic(這里我的topicName就叫austin,你們可以改成自己的)
$KAFKA_HOME/bin/kafka-topics.sh?--create?--topic?austin?--partitions?4?--zookeeper?zookeeper:2181?--replication-factor?1?
查看剛創(chuàng)建的topic信息:
$KAFKA_HOME/bin/kafka-topics.sh?--zookeeper?zookeeper:2181?--describe?--topic?austin

啟動一個(gè)消費(fèi)者:
$KAFKA_HOME/bin/kafka-console-consumer.sh?--bootstrap-server?kafka:9092?--from-beginning?--topic?austin
新增一個(gè)窗口,啟動一個(gè)生產(chǎn)者:
docker?exec?-it?kafka?sh
$KAFKA_HOME/bin/kafka-console-producer.sh?--topic=austin?--broker-list?kafka:9092


05、Java程序驗(yàn)證Kafka
引入Kafka依賴(SpringBoot有默認(rèn)的版本,不需要寫version)
<dependency>
??<groupId>org.springframework.kafkagroupId>
??<artifactId>spring-kafkaartifactId>
dependency>
定義一個(gè)實(shí)體類:
@Data
@Accessors(chain?=?true)
public?class?UserLog?{
????private?String?username;
????private?String?userid;
????private?String?state;
}
定義生產(chǎn)者(austin是topicName):
@Component
public?class?UserLogProducer?{
????@Autowired
????private?KafkaTemplate?kafkaTemplate;
????/**
?????*?發(fā)送數(shù)據(jù)???
?????*?@param?userid
?????*/
????public?void?sendLog(String?userid){
????????UserLog?userLog?=?new?UserLog();
????????userLog.setUsername("jhp").setUserid(userid).setState("0");
????????System.err.println("發(fā)送用戶日志數(shù)據(jù):"+userLog);
????????kafkaTemplate.send("austin",?JSON.toJSONString(userLog));
????}
}
定義消費(fèi)者:
@Component
@Slf4j
public?class?UserLogConsumer?{
????@KafkaListener(topics?=?{"austin"},groupId?=?"austinGroup1")
????public?void?consumer(ConsumerRecord,?>?consumerRecord){
????????//判斷是否為null
????????Optional>?kafkaMessage?=?Optional.ofNullable(consumerRecord.value());
????????log.info(">>>>>>>>>>?record?="?+?kafkaMessage);
????????if(kafkaMessage.isPresent()){
????????????//得到Optional實(shí)例中的值
????????????Object?message?=?kafkaMessage.get();
????????????System.err.println("消費(fèi)消息:"+message);
????????}
????}
}
定義接口:
@RestController
public?class?KafkaTestController?{
????@Autowired
????private?UserLogProducer?userLogProducer;
????/**
?????*?test?insert
?????*/
????@GetMapping("/kafka/insert")
????public?String?insert(String?userId)?{
????????userLogProducer.sendLog(userId);
????????return?null;
????}
}
測試:http://localhost:8080/kafka/insert?userId=3y

06、總結(jié)
搭建環(huán)境什么的沒什么需要總結(jié)的,按著教程一步一步執(zhí)行應(yīng)該就完事了?下周會具體實(shí)現(xiàn)austin-api和austin-api-impl模塊的內(nèi)容,可以繼續(xù)關(guān)注下。
Gitee地址:https://gitee.com/zhongfucheng/austin
GitHub地址:https://github.com/ZhongFuCheng3y/austin
聽說公眾號改了推送規(guī)則,星標(biāo)公眾號和點(diǎn)擊在看和點(diǎn)贊的才能第一時(shí)間收到我發(fā)的文章??。

《對線面試官》公眾號還在持續(xù)分享面試題,沒關(guān)注的同學(xué)可以關(guān)注一波!這是austin項(xiàng)目的上一個(gè)系列,質(zhì)量桿桿的
