Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
擊上方 "程序員小樂"關注, 星標或置頂一起成長
每天凌晨00點00分, 第一時間與你相約
每日英文
Someday, you will find the one, who will watch every sunrise with you until the sunset of your life.
總有一天,你會遇上那個人,陪你看每一次日出,直到你的人生落幕。
每日掏心話
每個人的心里,都有一個禁地,不愿再觸及,也不愿再想起,卻永遠無法忘記。既然忘不了,就不必費神忘記,做人本就很累,何必再自尋煩惱。
來自:等你歸去來 | 責編:樂樂
鏈接:cnblogs.com/yougewe/p/10327217.html
程序員小樂(ID:study_tech)第 835 次推文 圖片來自百度
往日回顧:手把手教你如何解決代碼中 if…else 過多的問題
正文
談到線上環境,一般開發同學,不太容易接觸到。即使接觸到,也只是其中的冰山一角!
所以,其實說起線上環境的部署,咱們好像都有點懂,但是又都不一定完全懂!網上的知識無窮無盡,但往往都是各司一職,對于普通同學,很難窺其全貌!
所以,我今天就來說說,一些普通的線上環境的部署步驟,和一些腳本小技巧吧。只希望通過這篇文章,能夠讓大家有一個運維的全局觀!
我將會分幾條線來整理咱們的運維思路!
一、從理論上講,我們應該怎么做?
1.針對的是什么樣的用戶群體,體量大概會有多少?
這是一個部署規劃的前題。為啥呢?
一、如果你針對的是后臺管理員,人數也不多,那么你可能只需要一個服務器就可以了,前后端也都可以部署在同一臺服務器上;如果稍微考慮下單點故障問題,則頂多兩臺服務器搞定!
二、如果針對的是前端普通用戶,那么,往往就會考慮多機部署,前后端分離,單點問題,負載均衡了;至于具體要部署多少臺,則要根據你的用戶情況來定了,當然,前期一般沒必要部署很多臺服務器!更多的考慮是橫向擴展的能力。只要能支持橫向擴展,則短期內,往往不用擔心性能和架構問題!
2.為支持預估的用戶量,大概需要多少的帶寬?
有訪問就會有流量產生,而預估的用戶量,則是一個帶寬資源需求的一個決斷依據!
一般針對前期用戶不太確定的場景,可以先買個 10M 左右的共享帶寬,基本能夠應付;經過一段時間的觀察后,再進行帶寬的變更也可以;
當然,考慮帶寬,自然也會存在一個公網IP的問題,因為流量是從IP進來的。而在IP之前,則是域名的訪問。域名問題則又涉及到DNS,不必細說!
公網IP可以是直接指向機器的,也可以是指向負載均衡器的。如果想要支持橫向擴展,則IP的指向一定是一個負載均衡器。因為只有這樣,當遇到流量突增,或者做活動的時候,才能更快速的進行擴容!
3.數據庫規劃如何?
數據在當下時代,算是重中之重了。機器沒了可以再買,代碼沒了可以再寫,但是數據沒了就完蛋了!
數據庫一般要遵從幾個基本原則: 一、帶寬要大;二、運算速度要快;三、要能承受足夠大的運算空間;(即:帶寬足夠大/cpu核數夠多/內存容量夠大/最大并發連接數/…)
所以,一般不要在數據庫上省錢,能多點就多點!
另外,也不要什么樣的數據都往數據庫(關系型數據庫)存,搞清楚各類型數據庫的強項與弱項,做出明智的選擇。否則會帶來很多不必要的麻煩!
4.應用要基于操作系統來部署還是基于容器來部署?
這是個決策性的問題!基于操作系統的部署,是一種比較傳統和常見的部署方式。優點是,很多系統工具都是完善的,只要你大概知道要部署什么,部署下來一般不會有太多問題,因為這是個完整的系統。
但是,由于系統與系統之間可能不能完全一致,有各種各樣的差異,所以,你在這個機器上運行成功的東西,在另外的機器上則不一定能成功。因此,基于系統的部署將會使我們的問題排查難度大大增加,而且移值性會很差。比如你在機器A上安裝了10個軟件,你可能配置了n個選項,但是,當你在安裝B機器的時候,你并不能很好的利用原有的配置,你還得從頭一個個地來!
因此,有另一個部署方案,基于容器的部署(我這里是基于docker容器的部署)。docker就類似于一個個的虛擬機,但是它更加輕量級,當一個docker部署好后,你可以任意復制到其他機器上運行,看起來很誘人吧。
不過,docker只是入門級容器,對于大量集群容器的管理,還是顯得力不從心,當然你很容易找到另一個方案: Kubernetes (K8s); 你只要花上少許的時間了解下,你就可以應用了!
當然了,使用容器的方案,有沒有什么缺點呢?應該是有的,比如本來可以基于系統的監控方案,因為接入容器后,監控指標則不一定適用了,當然現成的方案還是有的,不過得另外再花點時間研究了。再比如:如果容器出了問題,是否能排查出來,這也是另一個問題!
5.都有些什么樣的基礎設施或者中間件?
想要運行應用程序,自然是先考慮運行環境的。比如:應用需要 nginx 來做http服務器,用 tomcat 來做java web應用服務器,用redis來做緩存中間件,用zk來做應用協調中間件,用rabbitmq來做消息中間件,等等!
因此,要在代碼跑起來之前,先要把這些環境給準備好咯。
準備這些中間件或基礎設施之前,也要問下當下的形勢,是否有高性能高可用應用需求?比如:是否需要集群部署,或者單機部署?往往集群部署又會依賴其他的中間件!也更復雜!
當然,這些都不是事。事兒是在出問題之后,能夠有意識,能夠猜測到問題發生的點!
6.應用代碼應該怎樣部署?
當基礎環境就緒后,就應該讓主角上場了。應用代碼怎么部署?
最簡單的: 通過ftp上傳代碼到服務器上后,一個個部署!這種方案是最原始的,也是在沒有辦法搞更好的方案的時候使用的,不應長期使用;
稍微好點的: 使用集成工具(如jenkins)進行打包,然后上傳一個私有yum鏡像服務器(yum 源)。然后在線進行yum 安裝;這種方式,借助了集成工具,幾個好處:
可以檢測代碼合法性如:單元測試、代碼規范(可能需要插件);
對任何的改動有簡單留檔,可以備查的同時,也為代碼的回滾提供了可能;
減少了手動上傳導致的包破壞的可能性;
適合大規模應用;
再成熟點的: 再往后面,手動 yum 安裝也已經太累了,所以急需一個部署平臺,實現自動化部署;(這里的自動化部署可能就是基于CI集成部署的一種升級版)。總之,大大減小了人工參與程序,提升了效率,同時也保證了質量!當然,這種部署平臺已經經過了嚴格的測試,出錯的可能性也比較小了!
7.服務器的安全性?
不考慮服務器的安全性的應用,無異于自暴自棄。黑客無處不在,不過幸好現在系統也是越來越完善,只要稍加控制,即不那么容易被攻破了。但是如果放棄安全防護,則隨便來一個菜鳥程序員就把你搞死了,那時的損失就大了。推薦:如何設計一個安全的對外接口
網絡安全是個很專業的領域,我不敢造次去談它。不過我們可以簡單的做下防護: 如防火墻、授權操作、病毒庫等等。當然,如果使用xx云服務,則輕松方便多了,在后臺點點設置幾下搞定!
8.服務的可監控性?
無監控,不上線!
這是一個警示,如果線上服務沒有監控,則所有線上的東西,都成了盲區,這對程序員GG們來說,簡直太糟糕了,雖然他們很自信!
監控分兩個方面:一是系統級別的監控;二是應用級別的監控;(一般忽略其他監控: 如網絡)
系統級別的監控一般可以安裝第三方的軟件來解決: 如 zabbix, grafana …
而應用級別的監控,則需要自己擁有一套監控代碼了,而這對初期項目,則往往比較吃力。當然,如果引入一些開源的解決方案也是可以的,比如 ELK, 做到分布式日志中心的作用的同時,也可以根據日志做相應的應用報錯監控!然而這又涉及另外的機器費用和人力成本問題,也顯得不那么簡單了。
而如果使用xx云服務,則往往都會自帶服務器監控的,可以很方便地查看到服務器情況,站在高層次預估應用是否存在潛藏的問題!
如上,就是一些個人覺得的在部署一整套線上環境的時候,需要考慮的事項!從理論上講解了下個人見解,不對之處,請賜教!
二、接下來,我將給到一些實際的操作捷徑或提示?(linux)
1.免密登錄服務器?
在n服務器之間跳轉,如果每次都要求輸入密碼,那確實太煩了。尤其在密碼一般還很不容易記住的情況下!
所以,可以將一臺服務器作為跳板機,在這臺服務器上,可以免密地登錄到允許的n臺子服務器;
操作步驟有二:
# 1. 先使用 ssh-keygen 生成本機的key
ssh-keygen -t rsa # 如果已生成不要重復生成
# 2. 使用 ssh-copy-id 將本機的 key 發送到需要免密登錄的服務器,首次copy時會要求輸入密碼,后續則免密了
ssh-copy-id -i ~/.ssh/id_rsa.pub root@172.1.2.111
2.服務器之間文件(夾)拷貝?
拷貝文件的目的有很多,比如:代碼同步,文件同步,資源同步,甚至是會話同步….
# 1. 使用scp 拷貝文件
scp /home/ol-web.war root@xxx.com:/www/tomcat/wepapps/ # 從本機拷貝到遠程
scp /home/ol-web.war root@xxx.com:/www/tomcat/wepapps/ # 從遠程拷貝到本機
scp -r /www/nginx/html/ root@.2.3.2:/www/nginx/html/ # 從本機拷貝文件夾到遠程
# 2. 使用 rsync 同步文件,(可能需要安裝 rsync 服務)
rsync -av --delete /www/nginx/html/ root@.2.3.1:/www/nginx/html/ # 同步所有屬性,本地刪除的文件也同步遠程刪除
其中,scp一般是系統自帶的命令,而rsync則需要自行安裝服務。
scp復制你可以認為是增量復制,所以遠程文件往往會越來越大,垃圾文件越來越多。
而rsync則是保持兩端完全一致,可能會符合應用場景!但是,別忘了把rsync服務加入到開機啟動項中!
3.快捷使用 ssh 等等命令,使用 tab 鍵進行信息補全?
當使用 ssh / scp 等等命令操作的時候,其操作對象往往 1.2.3.x 這樣的ip顯示,如果不能友好點,那確實太累了!我們可以如下操作,以實現 ssh 也能更好的記憶:
# 在文件 /root/.bashrc 中,添加腳本如下,使自動補全添加 ssh
# auto complete ...
complete -W "$(echo $(grep -v '^$|#' .ssh/config | sort -u | sed 's/^ssh //'))" ssh
# 在文件 /root/.ssh/config 中,添加需要自動補全的服務器,
Host 172.2.3.5 server-api-01
Host 172.2.3.6 server-api-02
# 以上服務器名字需要在 /etc/hosts 文件中添加相應解析
# 而登錄 server時,只需, ssh server-api-01 即可
如上補全工作,無需在所有服務器上進行操作,只需在相應的跳板機上提供功能即可!
4.簡要 saltstack 搭建指南?
salt 是個方便易用的集群管理工具,比如你可以用于批量重啟服務,全局搜索日志等等;
# 1. 安裝, 僅需到相應機器上安裝即可
yum install salt-master salt-minion
# 2. 配置 /etc/salt/master /etc/salt/minion, 最簡單的,只需修改 minion 配置,指向 master 的ip即可;
#指定master,冒號后有一個空格, minion
master: 172.1.2.22
id: server-api-01
user: root
# 3. 啟動所有節點, status, restart
systemctl start salt-master # 162機器可用
systemctl start salt-minion
/etc/init.d/salt-master start # 155機器可用
/etc/init.d/salt-minion start
# 4. 將所有salt-minion 添加到 master 集群管理
salt-key -A
# 5. 登錄跳板機 api_01, 運行salt 操作,執行集群管理工作
salt server-api-02 cmd.run 'lsof -i:80'
salt '*' test.ping
5.簡要集群復制shell腳本?
有時,你可能需要將你的應用發布到n臺服務中,你可以直接改如下shell,也可以依賴于salt這樣的高級工具進行發布!shell 參考如下:
#!/bin/bash
# find out my ip to exclude...
MY_MERCHINE_IP=`ifconfig eth0 |awk -F "[: ]+" '/inet addr/{print }'`;
MERCHINE_IP_LIST="172.1.2.7 172.1.3.4";
for m_ip in $MERCHINE_IP_LIST;
do
if [[ $m_ip !=$MY_MERCHINE_IP ]]; then
echo "- Installing apps to mechine@${m_ip} ...";
# install api apps
scp /www/test/hello-1.0.0-SNAPSHOT.jar root@${m_ip}:/www/test/
rsync -av --delete /www/html/ root@${m_ip}:/www/html/
echo "- Install apps to merchine@${m_ip} done.";
fi;
done;
6.簡要docker搭建指南?
docker 作為一個容器化的基石,一出世就被追棒。包括現在的 k8s ,也是基于docker的。docker 可以讓你在一處搭建,處處運行,從而避免每次新買機器就要搞很久的尷尬局面;其搭建也是很簡單的(簡單應用):
為方便任意發揮,我們可以基于centos這種系統級別的鏡像進行創建自己的image;
# docker 安裝:
yum install docker
service docker start
# 拉取 centos6 的 docker 鏡像
docker pull centos:6
docker images
# 構建一個 image, 創建空目錄,編輯 Dockerfile
vim Dockerfile # 內容可變
FROM centos:6
MAINTAINER oom <w@163.com>
# move all configuration files into container
# RUN yum install -y lsof
# EXPOSE 80
# CMD ["sh","-c","service httpd start;bash"]
# 創建鏡像
docker build -t tmp_image:1.0 .
# 創建并運行容器
docker run -h tmp_container -itd --name tmp_container -v /opt/docker/webapps:/www/webapp tmp_image:1.0
# 進入容器,相當于進入 centos 操作系統
docker exec -it tmp_container bash
# 保存容器修改到images
docker commit -m 'web final.' 49d79fc19eaa tmp_image:1.2
# 備份容器修改后的docker鏡像
docker save > /opt/images/images_final/tmp_image.final.tar tmp_image:1.2
# 恢復你的備份鏡像,即全網發布
# 可以在任何裝 docker 的地方加載保存的鏡像
docker load -i /opt/images/images_final/tmp_image.final.tar
7.定制你的登錄歡迎語?
由于可能存在線上環境與測試環境共存的情況,一不小心的切換錯誤,就可能導致不可挽回的損失。所以,如果我們能在登錄的時候,做一個簡單的提示,那么就會少一點出錯的可能性。所以,訂制你的登錄歡迎語吧!
# 修改登錄歡迎語 vim /etc/motd
*****************************************************************
!!! WARNING: 歡迎來到線上機器: service-api-01 ,請謹慎操作哦 !!!
*****************************************************************
這樣,用戶登錄后,就會清楚的知道自己是在操作生產環境了!
8.更方便的查看nginx的訪問日志?
對于后端的日志而言,往往都是主動打印到某個固定位置,從而開發人員可以直接使用 tail -f xxx.log 進行日志的查看!
然而對于前端的代碼而言,則往往沒有相應的開發日志,唯一可以借助的就是 http 服務器的日志來排查問題了!
所以,比如使用 nginx 作為 http 服務器,那么就應該把盡可能多的有用日志打印出來。那么,如何快速查看 nginx 日志,則是有必要的!比如我們可以這樣:
# vim /usr/bin/log_nginx_host , 使用 log_nginx_host 直接查看所有 nginx 日志
tail -f /var/log/nginx/access.log /var/log/nginx/error.log
如上,將會把訪問日志與錯誤日志一起打印出來,從而快速定位問題!
歡迎在留言區留下你的觀點,一起討論提高。如果今天的文章讓你有新的啟發,學習能力的提升上有新的認識,歡迎轉發分享給更多人。
猜你還想看
阿里、騰訊、百度、華為、京東最新面試題匯集
從上帝視角看Java如何運行
一次項目代碼重構:使用Spring容器干掉條件判斷
IDEA-2020.1 版本針對調試器和代碼分析器的改進,值得期待
關注訂閱號「程序員小樂」,收看更多精彩內容
嘿,你在看嗎?
Grpc的優勢這里我就不說了, 第一它是基于Http2.0協議的, 可以保持客戶端與服務器端長連接, 基于二進制流,也就是字節流, 不是文本流.
? 同時他提供了跨平臺(語言)的開發方案 , 但是他也有成本就是需要定義他的接口規范, 遵循他的一套規范, 也就是說就算你是Java語言, 你不能隨意定義一個接口, 我就能幫你實現RPC , 只是他可以幫助你生成一個符合他規范的接口.
? 我們還是快速體驗一下吧. pom配置在文章最后
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-all</artifactId>
<version>1.12.0</version>
</dependency>
插件和全部依賴都在文章最后面 . 全局粘貼
idea 介意下載一個 protobuf的插件, 可以有代碼提示. 這里直接去pluging里搜就行了.
我使用的是proto3的版本.
可以參考一下這個文章 https://www.cnblogs.com/tohxyblog/p/8974763.html
注意這個文件是在 你的src/proto/XX.proto 中定義的, 文件目錄必須寫好.
syntax="proto3"; // 協議版本
// 選項配置
option java_package="com.example.grpc.api";
option java_outer_classname="RPCDateServiceApi";
option java_multiple_files=true;
// 定義包名
package com.example.grpc.api;
// 服務接口.定義請求參數和相應結果
service RPCDateService {
rpc getDate (RPCDateRequest) returns (RPCDateResponse) {
}
}
// 定義請求體
message RPCDateRequest {
string userName=1;
}
// 定義相應內容
message RPCDateResponse {
string serverDate=1;
}
使用maven插件, 編譯.
第一個命令執行完. 在 target目錄里找就行了. 第二個命令也就是找就行了. 然后將生成的Java文件拷貝到你的目錄里.就可以了, 類似于Mybatis的mapper插件.
package com.example.grpc.service;
// RPCDateServiceGrpc.RPCDateServiceImplBase 這個就是接口.
// RPCDateServiceImpl 我們需要繼承他的,實現方法回調
public class RPCDateServiceImpl extends RPCDateServiceGrpc.RPCDateServiceImplBase {
@Override
public void getDate(RPCDateRequest request, StreamObserver<RPCDateResponse> responseObserver) {
// 請求結果,我們定義的
RPCDateResponse rpcDateResponse=null;
String userName=request.getUserName();
String response=String.format("你好: %s, 今天是%s.", userName, LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
try {
// 定義響應,是一個builder構造器.
rpcDateResponse=RPCDateResponse
.newBuilder()
.setServerDate(response)
.build();
} catch (Exception e) {
responseObserver.onError(e);
} finally {
// 這種寫法是observer,異步寫法,老外喜歡用這個框架.
responseObserver.onNext(rpcDateResponse);
}
responseObserver.onCompleted();
}
}
public class GRPCServer {
private static final int port=9999;
public static void main(String[] args) throws Exception {
// 設置service接口.
Server server=ServerBuilder.
forPort(port)
.addService(new RPCDateServiceImpl())
.build().start();
System.out.println(String.format("GRpc服務端啟動成功, 端口號: %d.", port));
server.awaitTermination();
}
}
public class GRPCClient {
private static final String host="localhost";
private static final int serverPort=9999;
public static void main(String[] args) throws Exception {
// 1. 拿到一個通信的channel
ManagedChannel managedChannel=ManagedChannelBuilder.forAddress(host, serverPort).usePlaintext().build();
try {
// 2.拿到道理對象
RPCDateServiceGrpc.RPCDateServiceBlockingStub rpcDateService=RPCDateServiceGrpc.newBlockingStub(managedChannel);
RPCDateRequest rpcDateRequest=RPCDateRequest
.newBuilder()
.setUserName("anthony")
.build();
// 3. 請求
RPCDateResponse rpcDateResponse=rpcDateService.getDate(rpcDateRequest);
// 4. 輸出結果
System.out.println(rpcDateResponse.getServerDate());
} finally {
// 5.關閉channel, 釋放資源.
managedChannel.shutdown();
}
}
}
以上就是完整的流程. 啟動服務器端, 啟動客戶端打印一下信息 :
服務端日志 :
2020-02-29 11:04:50,991 4689 [LG-3-1] DEBUG .grpc.netty.NettyServerHandler - [id: 0xed01e3fb, L:/127.0.0.1:9999 - R:/127.0.0.1:3994] INBOUND SETTINGS: ack=true
2020-02-29 11:04:51,075 4773 [LG-3-1] DEBUG .grpc.netty.NettyServerHandler - [id: 0xed01e3fb, L:/127.0.0.1:9999 - R:/127.0.0.1:3994] INBOUND HEADERS: streamId=3 headers=GrpcHttp2RequestHeaders[:path: /com.example.grpc.api.RPCDateService/getDate, :authority: localhost:9999, :method: POST, :scheme: http, te: trailers, content-type: application/grpc, user-agent: grpc-java-netty/1.12.0, grpc-accept-encoding: gzip, grpc-trace-bin: ] streamDependency=0 weight=16 exclusive=false padding=0 endStream=false
2020-02-29 11:04:51,125 4823 [LG-3-1] DEBUG .grpc.netty.NettyServerHandler - [id: 0xed01e3fb, L:/127.0.0.1:9999 - R:/127.0.0.1:3994] INBOUND DATA: streamId=3 padding=0 endStream=true length=14 bytes=00000000090a07616e74686f6e79
2020-02-29 11:04:51,172 4870 [LG-3-1] DEBUG .grpc.netty.NettyServerHandler - [id: 0xed01e3fb, L:/127.0.0.1:9999 - R:/127.0.0.1:3994] OUTBOUND HEADERS: streamId=3 headers=GrpcHttp2OutboundHeaders[:status: 200, content-type: application/grpc, grpc-encoding: identity, grpc-accept-encoding: gzip] streamDependency=0 weight=16 exclusive=false padding=0 endStream=false
2020-02-29 11:04:51,189 4887 [LG-3-1] DEBUG .grpc.netty.NettyServerHandler - [id: 0xed01e3fb, L:/127.0.0.1:9999 - R:/127.0.0.1:3994] OUTBOUND DATA: streamId=3 padding=0 endStream=false length=44 bytes=00000000270a25e4bda0e5a5bd3a20616e74686f6e792c20e4bb8ae5a4a9e698af323032302d30322d32392e
2020-02-29 11:04:51,190 4888 [LG-3-1] DEBUG .grpc.netty.NettyServerHandler - [id: 0xed01e3fb, L:/127.0.0.1:9999 - R:/127.0.0.1:3994] OUTBOUND HEADERS: streamId=3 headers=GrpcHttp2OutboundHeaders[grpc-status: 0] streamDependency=0 weight=16 exclusive=false padding=0 endStream=true
2020-02-29 11:04:51,204 4902 [LG-3-1] DEBUG .grpc.netty.NettyServerHandler - [id: 0xed01e3fb, L:/127.0.0.1:9999 - R:/127.0.0.1:3994] INBOUND GO_AWAY: lastStreamId=0 errorCode=0 length=0 bytes=
客戶端日志 :
2020-02-29 11:00:43,480 1814 [LG-1-2] DEBUG .grpc.netty.NettyClientHandler - [id: 0xcdbd6064, L:/127.0.0.1:3817 - R:localhost/127.0.0.1:9999] INBOUND HEADERS: streamId=3 headers=GrpcHttp2ResponseHeaders[grpc-status: 0] streamDependency=0 weight=16 exclusive=false padding=0 endStream=true
你好: anthony, 今天是20-02-29.
2020-02-29 11:00:43,487 1821 [LG-1-2] DEBUG .grpc.netty.NettyClientHandler - [id: 0xcdbd6064, L:/127.0.0.1:3817 - R:localhost/127.0.0.1:9999] OUTBOUND GO_AWAY: lastStreamId=0 errorCode=0 length=0 bytes=
這就是一個Grpc的完整流程.
定義都是一個CS模型, GRPC他看到了未來一定是HTTP2的天下(這是必然的趨勢), 所以它沒有制定自己的協議, 這里指的是應用層協議. 類似于我們的RestTemplate 一樣都是基于http協議.
所以它考慮到的是 JSON ,這種序列化比較慢的序列化方式. 采用了自己開發的一種Protobuf.
這里就說明了 GRPC其實只是解決了序列化的方式, 依靠這個Protobuf, 可以解決一系列問題, 比如接口信息的定義, 等等有很多,
最簡單的例子. 比如我Java中寫了一個echo() 接口, golang如何調用 ? . 這就是難點,
我們可以依靠統一的Protobuf文件生成對應的 Golang和Java的接口, 就可以了, 所以說本質上來說他是做了這點.
我們看看Dubbo做了什么 , 他依靠TCP的可靠性, 自己基于TCP實現了一個應用層協議, dubbo協議. 同時也引用了一堆的序列化方式, 所以整個GRPC也是可行的.
?
感興趣的同學可以做一次抓包, 抓取客戶端請求,分析一個GRPC的請求格式.
*請認真填寫需求信息,我們會在24小時內與您取得聯系。