物理機實時監控UI之grafana(SimpleJson)+gRPC

在時序分析及監控展示領域,Grafana無疑是開源解決方案中的翹楚,其靈活的插件機制,支持各種漂亮的面板、豐富的數據源以及強大的應用。典型的面板有Graph、Text、Singlestat、PieChart、Table、Histogram等,支持的數據源有ES、Graphite、InfluxDB、OpenTSDB、MySQL、Druid 、Prometheus、SimpleJson等,提供的應用有Zabbix、K8s等。但是某公司在分布式集群中物理機監控的數據源為gRPC方式,即連接gRPC即可獲取實時物理機監控信息,如CPU,內存,磁盤,負載等信息,這樣就能使用后臺轉發gRPC的消息,這里使用SSM框架的java后臺為grafana提供的SimpleJson數據源。

作者撰文時,網上幾乎沒有分享SimpleJson數據源的java后臺API,為此分享給大家,初次分享,不便之處請見諒。

整體架構如下所示:

一、WebAPI

如果要支持SimpleJson,后端WebAPI需要實現4個URL:

/:返回200,用于SimpleJson數據源測試連通性;
/search:返回所有可選的指標;
/query:返回對應指標的時間序列點;
/annotations:返回注解。

?

    @RequestMapping(value = "/", method = RequestMethod.GET)@ResponseBodypublic Map ReturnTest(HttpServletResponse response){response.setHeader("Access-Control-Allow-Headers", "accept, content-type");response.setHeader("Access-Control-Allow-Methods", "POST");response.setHeader("Access-Control-Allow-Origin", "*");Map<String, Object> map = new HashMap<String, Object>();map.put("result", "200 ok");return map;}

?

    @RequestMapping(value = "/search", method = RequestMethod.POST)@ResponseBodypublic List Search(HttpServletResponse response) {response.setHeader("Access-Control-Allow-Headers", "accept, content-type");response.setHeader("Access-Control-Allow-Methods", "POST");response.setHeader("Access-Control-Allow-Origin", "*");List<String> result = new ArrayList<String>();result.add("CPU");result.add("RAM");result.add("LOAD");result.add("SWAP");result.add("DISK");result.add("NET");return result;}
`````java@RequestMapping(value = "/query", method = RequestMethod.POST)@ResponseBodypublic List Query(@RequestBody Map<String,Object>  params, HttpServletResponse response) {List<Map> targetList = (List) params.get("targets");List<Map<String, Object>> result = new ArrayList<Map<String, Object>>() ;for (Map targetMap : targetList){String target = (String)targetMap.get("target");Map scopedVars = (Map) params.get("scopedVars");Map IP = (Map) scopedVars.get("IP");String nodeIP = (String) IP.get("text");if (target.equals("CPU")){result.add(nodeMonitorService.getCpuMap(nodeIP));}else if (target.equals("RAM")){result.add(nodeMonitorService.getRamMap(nodeIP));}else if (target.equals("LOAD")) {result.add(nodeMonitorService.getLoadMap(nodeIP));}else if (target.equals("SWAP")){result.add(nodeMonitorService.getSwapMap(nodeIP));}else if(target.equals("DISK")){result = nodeMonitorService.getDiskList(nodeIP);}else if (target.equals("NET")){result = nodeMonitorService.getNetList(nodeIP);}}response.setHeader("Access-Control-Allow-Headers", "accept, content-type");response.setHeader("Access-Control-Allow-Methods", "POST");response.setHeader("Access-Control-Allow-Origin", "*");Collections.sort(result, new Comparator<Map<String, Object>>() {public int compare(Map<String, Object> o1, Map<String, Object> o2) {String name1 = String.valueOf(o1.get("target").toString()) ;String name2 = String.valueOf(o2.get("target").toString()) ; return name1.compareTo(name2);}});return result;}

?

    @RequestMapping(value = "/annotations", method = RequestMethod.POST)@ResponseBodypublic Map Annotations() {Map<String, Object> map = new HashMap<String, Object>();map.put("result", "200 ok");return map;}

具體參數可以用以下函數替換,如getCupMap:

private Map<String, Object> strjson() {//String str = "{\"A\":{\"tables\":[{\"columns\":[{\"text\":\"序列\",\"sort\":true,\"desc\":true,\"title\":\"序列\",\"style\":{\"alias\":\"\",\"colorMode\":null,\"colors\":[\"rgba(245, 54, 54, 0.9)\",\"rgba(237, 129, 40, 0.89)\",\"rgba(50, 172, 45, 0.97)\"],\"decimals\":2,\"pattern\":\"/.*/\",\"thresholds\":[],\"type\":\"number\",\"unit\":\"short\"},\"hidden\":false,\"$$hashKey\":\"object:644\"},{\"text\":\"水果名稱12\",\"title\":\"水果名稱12\",\"style\":{\"alias\":\"\",\"colorMode\":null,\"colors\":[\"rgba(245, 54, 54, 0.9)\",\"rgba(237, 129, 40, 0.89)\",\"rgba(50, 172, 45, 0.97)\"],\"decimals\":2,\"pattern\":\"/.*/\",\"thresholds\":[],\"type\":\"number\",\"unit\":\"short\"},\"hidden\":false,\"$$hashKey\":\"object:645\"},{\"text\":\"價錢\",\"title\":\"價錢\",\"style\":{\"alias\":\"\",\"colorMode\":null,\"colors\":[\"rgba(245, 54, 54, 0.9)\",\"rgba(237, 129, 40, 0.89)\",\"rgba(50, 172, 45, 0.97)\"],\"decimals\":2,\"pattern\":\"/.*/\",\"thresholds\":[],\"type\":\"number\",\"unit\":\"short\"},\"hidden\":false,\"$$hashKey\":\"object:646\"},{\"text\":\"重量(kg)\",\"title\":\"重量(kg)\",\"style\":{\"alias\":\"\",\"colorMode\":null,\"colors\":[\"rgba(245, 54, 54, 0.9)\",\"rgba(237, 129, 40, 0.89)\",\"rgba(50, 172, 45, 0.97)\"],\"decimals\":2,\"pattern\":\"/.*/\",\"thresholds\":[],\"type\":\"number\",\"unit\":\"short\"},\"hidden\":false,\"$$hashKey\":\"object:647\"},{\"text\":\"總價錢\",\"title\":\"總價錢\",\"style\":{\"alias\":\"\",\"colorMode\":null,\"colors\":[\"rgba(245, 54, 54, 0.9)\",\"rgba(237, 129, 40, 0.89)\",\"rgba(50, 172, 45, 0.97)\"],\"decimals\":2,\"pattern\":\"/.*/\",\"thresholds\":[],\"type\":\"number\",\"unit\":\"short\"},\"hidden\":false,\"$$hashKey\":\"object:648\"}],\"rows\":[[1,\"水果01\",4,2,8],[2,\"水果02\",5,2,10],[3,\"水果03\",6,2,12],[4,\"水果04\",7,2,14],[5,\"水果05\",8,2,16]]}]}}";Map<String, Object> map = new HashMap<>();JSONArray ja = new JSONArray();for (int i = 0; i < 10; i++) {JSONObject jb = new JSONObject();jb.put("num", 10*i);jb.put("createTime", "2019-05-09T"+(11+i)+":01:01");ja.add(jb);}map.put("reasult", ja);return map;}

?

注意header里面加上這3條:

?

        response.setHeader("Access-Control-Allow-Headers", "accept, content-type");response.setHeader("Access-Control-Allow-Methods", "POST");response.setHeader("Access-Control-Allow-Origin", "*");

?

二、grafana配置

安裝grafana,安裝SimpleJson插件,在grafana官網,有詳細說明。
啟動訪問,使用admin賬戶登錄,

1、創建數據源:DataSources

type選擇SimpleJson類型,URL填入后臺服務的API地址,

2、創建面板dashboard

這個面板我已經分享到grafana網站了,可以前去下載:https://grafana.com/dashboards/5075

綜上所述,基于SimpleJson數據源,只要配置數據源之后,按正確的方式添加API即可將數據靈活展現在Grafana中,當然SimpleJson只是一個數據源協議載體,理論上可以對接任何類型的后臺數據,只要組裝成它支持的格式即可。

面板源代碼,擴展名成 .json就行,然后import即可:?

{"__inputs": [{"name": "DS_DATA-PUBLIC","label": "data-public","description": "由java后臺提供物理機信息,java連接物理機上的grpc接口,用于采集傳送物理機信息","type": "datasource","pluginId": "grafana-simple-json-datasource","pluginName": "SimpleJson"},{"name": "DS_IP-PUBLIC","label": "ip-public","description": "提供物理機IP","type": "datasource","pluginId": "grafana-simple-json-datasource","pluginName": "SimpleJson"}],"__requires": [{"type": "grafana","id": "grafana","name": "Grafana","version": "5.0.0"},{"type": "datasource","id": "grafana-simple-json-datasource","name": "SimpleJson","version": "1.3.5"},{"type": "panel","id": "graph","name": "Graph","version": "5.0.0"},{"type": "panel","id": "singlestat","name": "Singlestat","version": "5.0.0"},{"type": "panel","id": "text","name": "Text","version": "5.0.0"}],"annotations": {"list": [{"builtIn": 1,"datasource": "-- Grafana --","enable": true,"hide": true,"iconColor": "rgba(0, 211, 255, 1)","name": "Annotations & Alerts","type": "dashboard"}]},"description": "物理機秒級監控頁面","editable": true,"gnetId": 5075,"graphTooltip": 2,"id": null,"iteration": 1520931758719,"links": [],"panels": [{"collapsed": false,"gridPos": {"h": 1,"w": 24,"x": 0,"y": 0},"id": 6,"panels": [],"title": "指標","type": "row"},{"content": "# $IP","gridPos": {"h": 3,"w": 3,"x": 0,"y": 1},"id": 4,"links": [],"mode": "markdown","repeat": "IP","repeatDirection": "v","title": "物理機","transparent": false,"type": "text"},{"cacheTimeout": null,"colorBackground": false,"colorValue": true,"colors": ["rgba(0, 190, 250, 0.97)","rgba(237, 129, 40, 0.89)","rgba(245, 54, 54, 0.9)"],"datasource": "${DS_DATA-PUBLIC}","decimals": 2,"format": "percent","gauge": {"maxValue": 100,"minValue": 0,"show": false,"thresholdLabels": false,"thresholdMarkers": true},"gridPos": {"h": 3,"w": 4,"x": 3,"y": 1},"height": "100px","id": 12,"interval": null,"links": [],"mappingType": 1,"mappingTypes": [{"name": "value to text","value": 1},{"name": "range to text","value": 2}],"maxDataPoints": 100,"minSpan": 6,"nullPointMode": "connected","nullText": null,"postfix": "","postfixFontSize": "50%","prefix": "","prefixFontSize": "50%","rangeMaps": [{"from": "null","text": "N/A","to": "null"}],"repeat": "IP","repeatDirection": "v","span": 3,"sparkline": {"fillColor": "rgba(0, 141, 255, 0.1)","full": false,"lineColor": "rgb(0, 133, 253)","show": true},"tableColumn": "","targets": [{"bucketAggs": [{"field": "create_time","id": "2","settings": {"interval": "auto","min_doc_count": 0,"trimEdges": 0},"type": "date_histogram"}],"dsType": "elasticsearch","metrics": [{"field": "value","id": "1","inlineScript": "100-_value","meta": {},"settings": {"script": {"inline": "100-_value"}},"type": "avg"}],"query": "mib:ssCpuIdle AND ip:\"$ip\"","refId": "A","target": "CPU","timeField": "create_time","type": "timeserie"}],"thresholds": "50,80","title": "CPU使用率","type": "singlestat","valueFontSize": "80%","valueMaps": [{"op": "=","text": "N/A","value": "null"}],"valueName": "current"},{"cacheTimeout": null,"colorBackground": false,"colorValue": true,"colors": ["rgba(0, 162, 238, 0.97)","rgba(237, 129, 40, 0.89)","rgba(245, 54, 54, 0.9)"],"datasource": "${DS_DATA-PUBLIC}","format": "percent","gauge": {"maxValue": 100,"minValue": 0,"show": true,"thresholdLabels": false,"thresholdMarkers": true},"gridPos": {"h": 3,"w": 6,"x": 7,"y": 1},"height": "100px","id": 10,"interval": null,"links": [],"mappingType": 1,"mappingTypes": [{"name": "value to text","value": 1},{"name": "range to text","value": 2}],"maxDataPoints": 100,"nullPointMode": "connected","nullText": null,"postfix": "","postfixFontSize": "50%","prefix": "","prefixFontSize": "50%","rangeMaps": [{"from": "null","text": "N/A","to": "null"}],"repeat": "IP","repeatDirection": "v","span": 3,"sparkline": {"fillColor": "rgba(31, 118, 189, 0.18)","full": false,"lineColor": "rgb(31, 120, 193)","show": false},"tableColumn": "","targets": [{"bucketAggs": [{"field": "@timestamp","id": "2","settings": {"interval": "auto","min_doc_count": 0,"trimEdges": 0},"type": "date_histogram"}],"dsType": "elasticsearch","metrics": [{"field": "value","id": "1","inlineScript": "_value*100","meta": {},"settings": {"script": {"inline": "_value*100"}},"type": "avg"}],"query": "mib:disk_percent AND ip:\"$ip\"","refId": "A","target": "RAM","timeField": "create_time","type": "timeserie"}],"thresholds": "70,90","title": "內存使用率","type": "singlestat","valueFontSize": "100%","valueMaps": [{"op": "=","text": "N/A","value": "null"}],"valueName": "avg"},{"aliasColors": {},"bars": false,"dashLength": 10,"dashes": false,"datasource": "${DS_DATA-PUBLIC}","fill": 1,"gridPos": {"h": 9,"w": 12,"x": 0,"y": 4},"hideTimeOverride": false,"id": 2,"legend": {"alignAsTable": true,"avg": true,"current": true,"max": true,"min": true,"rightSide": false,"show": true,"total": false,"values": true},"lines": true,"linewidth": 1,"links": [],"nullPointMode": "null","percentage": false,"pointradius": 5,"points": false,"renderer": "flot","repeat": "IP","repeatDirection": "v","seriesOverrides": [],"spaceLength": 10,"stack": false,"steppedLine": false,"targets": [{"hide": false,"rawQuery": false,"refId": "A","target": "CPU","type": "timeserie"}],"thresholds": [],"timeFrom": null,"timeShift": null,"title": "CPU使用率","tooltip": {"shared": true,"sort": 0,"value_type": "individual"},"transparent": false,"type": "graph","xaxis": {"buckets": null,"mode": "time","name": null,"show": true,"values": []},"yaxes": [{"format": "percent","label": "","logBase": 1,"max": "100","min": "0","show": true},{"format": "percent","label": null,"logBase": 1,"max": "100","min": "0","show": true}]},{"aliasColors": {},"bars": false,"dashLength": 10,"dashes": false,"datasource": "${DS_DATA-PUBLIC}","fill": 1,"gridPos": {"h": 9,"w": 12,"x": 12,"y": 4},"hideTimeOverride": false,"id": 14,"legend": {"alignAsTable": true,"avg": true,"current": true,"max": true,"min": true,"rightSide": false,"show": true,"total": false,"values": true},"lines": true,"linewidth": 1,"links": [],"nullPointMode": "null","percentage": false,"pointradius": 5,"points": false,"renderer": "flot","repeat": "IP","repeatDirection": "v","seriesOverrides": [],"spaceLength": 10,"stack": false,"steppedLine": false,"targets": [{"hide": false,"rawQuery": false,"refId": "A","target": "RAM","type": "timeserie"}],"thresholds": [],"timeFrom": null,"timeShift": null,"title": "RAM使用率","tooltip": {"shared": true,"sort": 0,"value_type": "individual"},"transparent": false,"type": "graph","xaxis": {"buckets": null,"mode": "time","name": null,"show": true,"values": []},"yaxes": [{"format": "percent","label": "","logBase": 1,"max": "100","min": "0","show": true},{"format": "percent","label": null,"logBase": 1,"max": "100","min": "0","show": true}]},{"aliasColors": {},"bars": false,"dashLength": 10,"dashes": false,"datasource": "${DS_DATA-PUBLIC}","fill": 1,"gridPos": {"h": 9,"w": 12,"x": 0,"y": 13},"hideTimeOverride": false,"id": 18,"legend": {"alignAsTable": true,"avg": true,"current": true,"max": true,"min": true,"rightSide": true,"show": true,"total": false,"values": true},"lines": true,"linewidth": 1,"links": [],"nullPointMode": "null","percentage": false,"pointradius": 5,"points": false,"renderer": "flot","repeat": "IP","repeatDirection": "v","seriesOverrides": [],"spaceLength": 10,"stack": false,"steppedLine": false,"targets": [{"hide": false,"rawQuery": false,"refId": "A","target": "DISK","type": "timeserie"}],"thresholds": [],"timeFrom": null,"timeShift": null,"title": "磁盤使用率","tooltip": {"shared": true,"sort": 0,"value_type": "individual"},"transparent": false,"type": "graph","xaxis": {"buckets": null,"mode": "time","name": null,"show": true,"values": []},"yaxes": [{"format": "percent","label": "","logBase": 1,"max": "100","min": "0","show": true},{"format": "percent","label": null,"logBase": 1,"max": "100","min": "0","show": true}]},{"aliasColors": {},"bars": false,"dashLength": 10,"dashes": false,"datasource": "${DS_DATA-PUBLIC}","fill": 1,"gridPos": {"h": 9,"w": 12,"x": 12,"y": 13},"hideTimeOverride": false,"id": 20,"legend": {"alignAsTable": true,"avg": true,"current": true,"max": true,"min": true,"rightSide": true,"show": true,"total": false,"values": true},"lines": true,"linewidth": 1,"links": [],"nullPointMode": "null","percentage": false,"pointradius": 5,"points": false,"renderer": "flot","repeat": "IP","repeatDirection": "v","seriesOverrides": [],"spaceLength": 10,"stack": false,"steppedLine": false,"targets": [{"hide": false,"rawQuery": false,"refId": "A","target": "NET","type": "timeserie"}],"thresholds": [],"timeFrom": null,"timeShift": null,"title": "網絡指標","tooltip": {"shared": true,"sort": 0,"value_type": "individual"},"transparent": false,"type": "graph","xaxis": {"buckets": null,"mode": "time","name": null,"show": true,"values": []},"yaxes": [{"format": "bytes","label": "","logBase": 1,"max": null,"min": null,"show": true},{"format": "percent","label": null,"logBase": 1,"max": "100","min": "0","show": true}]},{"aliasColors": {},"bars": false,"dashLength": 10,"dashes": false,"datasource": "${DS_DATA-PUBLIC}","fill": 1,"gridPos": {"h": 9,"w": 12,"x": 0,"y": 22},"hideTimeOverride": false,"id": 16,"legend": {"alignAsTable": true,"avg": true,"current": true,"max": true,"min": true,"rightSide": false,"show": true,"total": false,"values": true},"lines": true,"linewidth": 1,"links": [],"nullPointMode": "null","percentage": false,"pointradius": 5,"points": false,"renderer": "flot","repeat": "IP","repeatDirection": "v","seriesOverrides": [],"spaceLength": 10,"stack": false,"steppedLine": false,"targets": [{"hide": false,"rawQuery": false,"refId": "A","target": "SWAP","type": "timeserie"}],"thresholds": [],"timeFrom": null,"timeShift": null,"title": "虛擬內存(SWAP)使用率","tooltip": {"shared": true,"sort": 0,"value_type": "individual"},"transparent": false,"type": "graph","xaxis": {"buckets": null,"mode": "time","name": null,"show": true,"values": []},"yaxes": [{"format": "percent","label": "","logBase": 1,"max": "100","min": "0","show": true},{"format": "percent","label": null,"logBase": 1,"max": "100","min": "0","show": true}]},{"aliasColors": {},"bars": false,"dashLength": 10,"dashes": false,"datasource": "${DS_DATA-PUBLIC}","fill": 1,"gridPos": {"h": 9,"w": 12,"x": 12,"y": 22},"hideTimeOverride": false,"id": 15,"legend": {"alignAsTable": true,"avg": true,"current": true,"max": true,"min": true,"rightSide": false,"show": true,"total": false,"values": true},"lines": true,"linewidth": 1,"links": [],"nullPointMode": "null","percentage": false,"pointradius": 5,"points": false,"renderer": "flot","repeat": "IP","repeatDirection": "v","seriesOverrides": [],"spaceLength": 10,"stack": false,"steppedLine": false,"targets": [{"hide": false,"rawQuery": false,"refId": "A","target": "LOAD","type": "timeserie"}],"thresholds": [],"timeFrom": null,"timeShift": null,"title": "系統負載","tooltip": {"shared": true,"sort": 0,"value_type": "individual"},"transparent": false,"type": "graph","xaxis": {"buckets": null,"mode": "time","name": null,"show": true,"values": []},"yaxes": [{"format": "none","label": "","logBase": 1,"max": null,"min": "0","show": true},{"format": "percent","label": null,"logBase": 1,"max": "100","min": "0","show": false}]}],"refresh": "5s","schemaVersion": 16,"style": "dark","tags": ["node-panlei"],"templating": {"list": [{"allValue": null,"current": {},"datasource": "${DS_IP-PUBLIC}","hide": 0,"includeAll": false,"label": null,"multi": false,"name": "IP","options": [],"query": "show IP","refresh": 1,"regex": "","sort": 0,"tagValuesQuery": "","tags": [],"tagsQuery": "","type": "query","useTags": false}]},"time": {"from": "now-15m","to": "now-1s"},"timepicker": {"hidden": true,"nowDelay": "1s","refresh_intervals": ["1s","5s","10s","30s","1m","5m","15m","30m","1h","2h","1d"],"time_options": ["5m","15m","1h","6h","12h","24h","2d","7d","30d"]},"timezone": "browser","title": "node-monitor","uid": "VF00gigiz","version": 109
}



作者:風吹散了的回憶
鏈接:https://www.jianshu.com/p/bbd507a68bb9
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/386678.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/386678.shtml
英文地址,請注明出處:http://en.pswp.cn/news/386678.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Uva679

Dropping Balls UVA - 679 思路&#xff1a;和之前做的開關燈的題類似 只需要看小球的編號奇偶。 找規律就行&#xff0c;一直想推導出這個規律滿足所有情況&#xff0c;但是沒有想出來怎么推。 1 #include<bits/stdc.h>2 #define maxn 1053 #define LL long long4 usi…

面試大廠應該注意哪些問題?算法太TM重要了

前言 很多次小伙伴問到學習方法&#xff0c;我也很想寫這樣的一篇文章來跟大家討論下關于學習方法這件事情。 其實學習方法這個事情&#xff0c;我沒啥發言權&#xff0c;因為我自己本身都是沒啥方法可言的&#xff0c;就瞎折騰那種&#xff0c;但是大家想看這樣的一篇文章&a…

Spring Boot 與 Java 對應版本,以下表格由官方網站總結。

Spring Boot 與 Java 對應版本&#xff0c;以下表格由官方網站總結。 官網&#xff1a;https://spring.io/projects/spring-boot#learn https://docs.spring.io/spring-boot/docs/{verion}/reference/htmlsingle/ Go to [9. System Requirements] Sping BootSpring Framew…

Java開發環境之RabbitMQ

查看更多Java開發環境配置&#xff0c;請點擊《Java開發環境配置大全》 捌章&#xff1a;RabbitMQ安裝教程 1&#xff09;下載安裝Erlang 官網下載&#xff1a;http://www.erlang.org&#xff0c;有時比較難訪問進去 Windows版下載&#xff1a;http://www.erlang.org/download/…

Linux下GitLab的安裝及使用

一、初始GitLab GitLab是利用Ruby on Rails一個開源的版本管理系統&#xff0c;實現一個自托管的Git項目倉庫&#xff0c;可通過Web界面進行訪問公開的或者私人項目。 與Github類似&#xff0c;GitLab能夠瀏覽源代碼&#xff0c;管理缺陷和注釋。可以管理團隊對倉庫的訪問&a…

面試大廠應該注意哪些問題?隔壁都饞哭了

前言 說起程序員人們的第一印象就是工資高、加班兇、話少錢多頭發少。再加上現在科技互聯網公司太吃香&#xff0c;bat、華為小米等公司程序員加班情況被廣泛傳播&#xff0c;程序員用生命在敲代碼的印象刻在了很多人的心里。 與其它行業一樣&#xff0c;凡是有高級和普通&…

元類(metaclass)

目錄 一、引言二、什么是元類三、為什么用元類四、內置函數exec(儲備)五、class創建類5.1 type實現六、自定義元類控制類的創建6.1 應用七、__call__(儲備)八、__new__(儲備)九、自定義元類控制類的實例化一十、自定義元類后類的繼承順序十一、練習一、引言 元類屬于python面向…

Linux環境下使用rpm包安裝GitLab

1.安裝依賴環境 [rootgitlab ~]# yum install curl openssh-server postfix cronie 2.下載安裝GitLab包 我安裝的環境是Red Hat Enterprise Linux Server release 7.4 (Maipo) GitLab下載地址:https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7 以上是清華大學開源…

面試字節跳動Android工程師該怎么準備?深度解析,值得收藏

前言 Android高級架構師需要學習哪些知識呢&#xff1f; 下面總結一下我認為作為一個資深開發者需要掌握的技能點。 1.Android開發的幾個階段 我的10年開發生涯中&#xff0c;有9年都是做Android相關開發&#xff0c;以我個人的經歷來看&#xff0c;Android開發市場分為以下…

以JSONobject形式提交http請求

總結一下設置圖標的三種方式&#xff1a; &#xff08;1&#xff09;button屬性&#xff1a;主要用于圖標大小要求不高&#xff0c;間隔要求也不高的場合。 &#xff08;2&#xff09;background屬性&#xff1a;主要用于能夠以較大空間顯示圖標的場合。 &#xff08;3&#xf…

阿里巴巴Android面試都問些什么?系列篇

Google 為了幫助 Android 開發者更快更好地開發 App&#xff0c;推出了一系列組件&#xff0c;這些組件被打包成了一個整體&#xff0c;稱作 Android Jetpack&#xff0c;它包含的組件如下圖所示&#xff1a; 老的 support 包被整合進了 Jetpack&#xff0c;例如上圖 Foundatio…

安裝容器編排工具 Docker Compose

安裝容器編排工具 Docker Compose curl -L https://get.daocloud.io/docker/compose/releases/download/1.22.0/docker-compose-uname -s-uname -m > /usr/local/bin/docker-compose 授權&#xff1a; chmod x /usr/local/bin/docker-compose 查看安裝結果 docker-com…

docker-compose安裝elk7.1.1版本

在用docker-compose編排elk三個服務時&#xff0c;碰到了很多坑&#xff0c;網上很多資料編排的版本都不是最新的版本&#xff0c;我們這里用的 elasticsearch&#xff0c;logstash&#xff0c;kibana全都是elastic官方提供的目前最新版本7.1.1&#xff0c;高版本和低版本的一些…

阿里P8成長路線!我的頭條面試經歷分享,吊打面試官系列!

正式加入字節跳動&#xff0c;分享一點面試小經驗 今天正式入職了字節跳動。工號超吉利&#xff0c;尾數是3個6。然后辦公環境也很好&#xff0c;這邊一棟樓都是辦公區域。公司內部配備各種小零食、飲料&#xff0c;還有免費的咖啡。15樓還有健身房。而且公司包三餐來著。下午…

實驗十一:圖形界面二

實驗程序如下&#xff1a;import java.awt.*;import java.awt.event.*;import javax.swing.*;public class Example1 extends JFrame { private int add1,sub2,mul3,div4; private int op0; boolean ifOp; private String output"0"; private Button[] jbanew Button…

Docker安裝部署ELK教程 (Elasticsearch+Kibana+Logstash)

Elasticsearch 是個開源分布式搜索引擎&#xff0c;它的特點有&#xff1a;分布式&#xff0c;零配置&#xff0c;自動發現&#xff0c;索引自動分片&#xff0c;索引副本機制&#xff0c;restful風格接口&#xff0c;多數據源&#xff0c;自動搜索負載等。 Logstash 是一個完…

阿里P8面試官都說太詳細了,面試資料分享

背景 知乎客戶端中有一個自己維護的 Hybrid 框架&#xff0c;在此基礎上開發了一些 Hybrid 頁面&#xff0c;當需要前端或者客戶端開發接口的時候&#xff0c;就涉及到聯調的問題。 和一般的 前端 <> 服務端&#xff0c;或者 客戶端 <> 服務端 類似&#xff0c;前…

virtual和override

偶然間看到的題&#xff0c;借此記錄。 class Program{static void Main(string[] args){D d new D(); //第一個D是申明類&#xff0c;第二個D是實例類A a d;B b d;C c d;a.F();b.F();c.F();d.F();}class A{public virtual void F() { Console.WriteLine("A.F")…

阿里內部資料!如何試出一個Android開發者真正的水平?系列教學

前言 馬爸爸總結了一句話&#xff1a;跳槽&#xff0c;要么是錢不到位&#xff0c;要么是受了委屈。 我給自己這次的跳槽經歷做了一個分析&#xff0c;希望能對那些想換工作的朋友有所幫助。 許多朋友想換工作&#xff0c;但是對“換工作”的理解可能僅限于寫簡歷、投簡歷、…

CentOS7 linux下yum安裝redis以及使用

CentOS7 linux下yum安裝redis以及使用 1.安裝redis數據庫 1 yum install redis 2.下載fedora的epel倉庫 yum install epel-release 3.啟動redis服務 systemctl start redis 4.查看redis狀態 systemctl status redis systemctl stop redis 停止服務 systemctl restart r…