主頁 > 後端開發 > SpringCloud微服務電商系統在Kubernetes集群中上線詳細教程

SpringCloud微服務電商系統在Kubernetes集群中上線詳細教程

2021-12-07 10:30:29 後端開發

Kubernetes集群部署Springcloud微服務商務系統

文章目錄

  • Kubernetes集群部署Springcloud微服務商務系統
    • 1.微服務架構及理論概述
      • 1.1.單體架構與微服務架構的區別
      • 1.2.微服務組件架構圖
      • 1.3.微服務注冊中心
      • 1.4.不同的部署環境對于程式組態檔如何管理
    • 2.微服務遷移至kubernetes平臺流程
      • 2.1.專案遷移到K8S平臺流程
      • 2.2.傳統部署與K8S部署的區別
    • 3.微服務程式前期環境準備(配置、編譯、制作鏡像)
      • 3.1.simple-microservice微服務專案介紹
      • 3.2.simple微服務部署到K8S邏輯架構
      • 3.3.準備微服務各程式的組態檔
        • 3.3.1.創建微服務各個程式的prod組態檔
        • 3.3.2.調整每個微服務的pom檔案增加prod環境
      • 3.4.制作微服務程式所使用的的底層系統鏡像
        • 3.4.1.為程式環境構建底層系統鏡像
        • 3.4.2.為每個微服務程式撰寫Dockerfile
      • 3.5.調整Protal微服務中連接Gateway網關的地址
      • 3.6.部署Ingress用于將微服務程式發布到互聯網
    • 4.在kubernetes集群部署simple微服務專案
      • 4.1.部署simple微服務程式的mysql資料庫環境
      • 4.2.部署eureka微服務注冊中心
        • 4.2.1.修改Eureka組態檔增加各節點地址
        • 4.2.2.調整Eureka的Dockerfile
        • 4.2.3.構建Eureka服務的Docker鏡像
        • 4.2.4.撰寫Eureka部署YAML資源檔案
        • 4.2.5.在K8S集群中部署Eureka注冊中心
      • 4.3.配置各個微服務程式連接Eureka集群的地址
      • 4.4.將各個程式代碼編譯成可部署的程式
      • 4.3.中部署Gateway網關服務
        • 4.3.1.將Gateway程式打包成docker鏡像
        • 4.3.2.在K8S集群中部署Gateway網關服務
        • 4.3.3.在K8S集群中部署Gateway網關服務
      • 4.4.撰寫快速部署微服務到K8S集群的腳本
      • 4.5.使用腳本部署Order訂單服務
        • 4.5.1.撰寫資源部署YAML檔案
        • 4.5.2在K8S集群中部署Order訂單服務
      • 4.6.使用腳本部署Product商品服務
        • 4.6.1.撰寫資源部署YAML檔案
        • 4.6.2.在K8S集群中熟不熟Product商品服務
      • 4.7.使用腳本部署Stock庫存服務
        • 4.7.1.撰寫資源部署YAML檔案
        • 4.7.2.在K8S集群中部署Stock庫存服務
      • 4.8.使用腳本部署Portal前端首頁
        • 4.8.1.撰寫資源部署YAML檔案
        • 4.8.2.在K8S集群中熟不熟Portal存服務
      • 4.9.查看Eureka注冊中心中各個微服務的資訊
      • 4.10.使用simple微服務電商平臺
    • 5.基于K8S集群的微服務的擴容與升級
      • 5.1.微服務的擴容
      • 5.2.微服務的升級
        • 5.2.1.微調Portal前端首頁的代碼
        • 5.2.2.編譯最新代碼
        • 5.2.3.通過腳本將Protal最新代碼打包成鏡像
        • 5.2.4.升級K8S集群中的Protal微服務

1.微服務架構及理論概述

? 程式架構一共經歷了3個階段:單體架構、SOA架構、微服務架構,

? 微服務系統應用由原來的單體變成幾十到幾百個不同的工程,會產生例如包括服務間的依賴,服務如何拆封,內部介面規范,資料傳遞等等問題,尤其是服務拆分,需要團隊熟悉業務流程,懂得取舍,要保證拆分的粒度服務既符合“高內聚,低耦合”的基本原則,還要兼顧業務的發展以及公司的愿景,要還要說服團隊成員為之努力,并且積極投入,在多方中間取得平衡,

? 微服務從概念上講就是將一個大的平臺拆分成幾個獨立的小模塊,這些模塊有自己專門的資料庫服務,即使這個單獨模塊出現了故障,也不會影響整個平臺的使用,例如一個平臺中有訂單模塊、新聞模塊、咨詢模塊,即使新聞模塊宕機了,訂單模塊、新聞模塊依然作業正常,也不會造成整個網站的癱瘓,

? 對于微服務版本迭代而言,只需要針對特定功能所在的子專案上線即可,版本迭代更加靈活,而單體程式版本迭代,哪怕只是一個小小的功能也需要對整個系統進行更新,

? 目前主流的程式架構就是微服務系統,運用的技術堆疊更加豐富,例如kubernetes、CI/CD、Devops等等,

? 微服務專案在kubernetes環境部署主要有兩種實作方式:無狀態的部署、istio微服務網格部署,

? 可以把微服務理解為是一個大的框架,在這個框架里面內嵌各個子系統,

1.1.單體架構與微服務架構的區別

微服務的特點:

  • 系統服務獨立化
    • 每個子專案系統都會獨立開發、部署,有效的避免一個服務的bug影響整個系統的使用
  • 技術堆疊靈活
    • 每個子系統之間約定一個通信方式,例如MQ、API等,不再像單體服務那么的局限性
  • 獨立部署
    • 每個微服務系統都獨立部署,都有單獨的war包,即使其中一個服務例外宕機,也不會對整個平臺產生影響
  • 擴展性強
    • 每個微服務都可以部署多套,配合注冊中心實作負載均衡能力
  • 獨立資料
    • 每個微服務都有獨立的存盤組件,比如資料庫、快取等,互不影響

單體服務的特點

  • 易于部署
    • 單體服務只有一個程式包,只需要部署一個服務即可完成整個系統的建設
  • 易于測驗
    • 測驗用例也只需要設計一個即可

單體服務的不足

  • 代碼量級巨大,難以維護,如果系統中存在bug,修復起來牽扯功能太多,故障百出
  • 構建、部署的成本巨大,服務都集成在一起,啟動的時間也會非常緩慢
  • 新人上手較難,如果整個服務也沒有注釋的情況下,新的開發人員上手會非常難

微服務與單體服務架構上的不同

單體服務:程式包只有一個,開發團隊可能有一群人,用戶之間訪問程式包即可獲取系統資訊,后端對應一個資料庫

微服務:程式包有多個,每個程式包都是不同的功能結合,且每個微服務程式都有自己的單獨資料庫存盤資料,所有的微服務資訊都會存盤到注冊中心,網關程式在最前面,當用戶有請求進來后,首先發送給網關服務,然后網關根據注冊中心的資料,將不同功能的請求轉發給不同的微服務程式

在這里插入圖片描述

1.2.微服務組件架構圖

以電商平臺為例,描述一個購買商品的微服務之間呼叫流程

? 用戶首先訪問到平臺的靜態首頁,發送一個搜索請求從前端頁面提交給微服務的網關服務,網關服務是對外的,也就是不管用戶要操作什么請求,都需要由網關服務轉發給具體的微服務,因為網關服務是入口,因此網關服務一般都是多臺做成的負載均衡,搜索請求到達網關服務后,網關服務會根據請求的功能轉發到搜索服務的程式上,搜索出來商品后,會呼叫商品服務程式,查看商品的詳細情況,用戶選擇完商品后,商品服務再呼叫訂單服務,完成訂單的創建,再由訂單服務呼叫支付服務,完成商品的購買,

? 所有的微服務介面資訊都會注冊到注冊中心,當程式啟動成功就會自動注冊到注冊中心,注冊中心也會起到一個負載均衡的作用,根據網關的API請求,在注冊中心上找到特定的微服務程式進行轉發,

? 微服務程式還有自己的一套配置中心,保存著各個微服務的組態檔,所有的微服務程式可能都有自己獨立的后端組件,比如MySQL、Redis、MQ、分布式存盤,

微服務之間的通信可以采用介面API、MQ、RPAC等機制

微服務在kubernetes集群中部署時可以采用無狀態服務的部署,對于資料庫、Redis、MQ、存盤還是建議部署在k8s集群之外,

注冊中心與微服務之間的聯系:發現微服務—>微服務注冊到注冊中心—>進行心跳監測,例外的節點會踢出

微服務程式的門戶網站會配置Gateway網關服務的地址,由門戶網站用戶請求的微服務資訊,轉發給Gateway網關程式,所有的微服務都會注冊在Eureka注冊中心中,Gateway網關會將請求通過注冊中心轉發給對應的微服務程式,
在這里插入圖片描述

1.3.微服務注冊中心

微服務面對著很多問題:

  • 如何記錄一個微服務副本的介面地址,如何對多個微服務節點組成的集群做負載均衡
  • 符合判斷集群中某一個微服務是否可用

微服務面臨的這些問題都可以通過注冊中心去解決,在注冊中心中可用記錄某一個微服務的所有副本節點,當一個副本節點掛掉了,注冊中心也會將其踢出集群,注冊中心會將一個微服務的所有副本節點自動形成一個負載均衡

在微服務中配合注冊中心地址之后,程式一旦啟動,無需配置注冊中心,且能夠自動注冊到注冊中心

微服務接入注冊中心流程:微服務程式---->注冊---->注冊中心服務器

注冊中心呼叫微服務流程:微服務網關程式---->注冊/查詢微服務(呼叫微服務)---->注冊中心---->微服務程式

當然也可以不適用注冊中心,k8s自身的功能就有服務發現自動形成負載均衡,也可以用健康檢查監控服務的運行狀況

目前主流的注冊中心:Eureka、Nacos

1.4.不同的部署環境對于程式組態檔如何管理

可以通過以下四種方式來管理不同環境使用不同的組態檔

  • kubernetes configmap資源
    • 可以根據線上、預發布、測驗環境撰寫不同的configmap資源,然后將其掛載到對應的deployment資源上
  • docker 容器啟動腳本entrypoint.sh
    • 根據環境的不同在entrypoint.sh宣告環境變數,運行特定的組態檔
  • java啟動命令控制
    • java程式可以同時存在多個程式組態檔,可以在組態檔中宣告各自的變數,然后使用java --spring.profiles.active=xxx xxx.jar的方式來指定不同環境的組態檔
  • 使用開源的統一配置中心程式,比如市面上主流的Apollo以及Disconf,這兩款程式都有自己的圖形化管理系統,配置可視化

2.微服務遷移至kubernetes平臺流程

2.1.專案遷移到K8S平臺流程

在這里插入圖片描述
專案遷移到K8S平臺大致流程分為以下幾個階段:

  • 制作程式鏡像

    • 在K8s環境,所有的程式都是以Docker鏡像來運行的,一個鏡像包含了檔案系統、程式的運行環境、程式本身,可以通過Dockerfile的形式制作鏡像
  • 使用資源控制器管理Pod資源

    • 程式鏡像運行需要依靠Pod資源,需要有Pod控制器去管理Pod資源
    • 常見的Pod控制器:Deployment(無狀態程式部署)、Statefulset(有狀態程式部署)、Job/CronJob(批量處理)
  • 將Pod資源使用服務發現對外進行暴露

    • Services資源注意通過label標簽與Pod進行關聯,實作對一組Pod的自動負載均衡以及服務發現
    • Services資源支持Cluster、Nodeport、LoadBalancer三種型別
  • 對外發布應用程式

    • 可以使用單獨的nginx容器去反向代理Cordns決議的services名稱將Pod應用對外發布
    • 也可以使用ingress+services的方式將應用程式對外發布,使用ingress的前提是必須可以通過域名訪問應用
    • 架構圖如下
      在這里插入圖片描述
  • 后期的日志收集與監控

    • 當應用在K8s程式運行后,對于程式的日志比如nginx、tomcat這些日志檔案都不會做持久化,因此就需要考慮對日志進行收集,可以采用Filebeat+ELK方式對程式日志進行收集
    • 使用Prometheus+Grafana對整個K8s平臺進行全方面監控

2.2.傳統部署與K8S部署的區別

傳統方式部署專案方式:

首先由開發人員提交代碼到Gitlab代碼倉庫,Jenkins觸發更新從Gitlab上獲取最新代碼,通過maven將代碼編譯成war包或者jar包,再由Jenkins通過寫好的自動化部署腳本或者Ansible自動化程式將war包部署到程式所在的云主機,云主機一定會是多臺組成的負載均衡集群,將負載均衡VIP與域名進行系結,用戶通過訪問域名由負載均衡轉發至對應的后臺主機,

傳統架構運維環境一般由zabbix監控系統進行監控,日志采集會使用ELK平臺,

在這里插入圖片描述

Kubernetes平臺部署專案方式:

首先由開發人員提交代碼到Gitlab代碼倉庫,Jenkins觸發更新從Gitlab上獲取最新代碼,通過寫好流水線將程式打包成Docker鏡像并推送至Harbor倉庫,再由Jenkins呼叫K8s的Master Api將程式的鏡像采用Deployment控制器部署到K8s集群,再由service資源暴露pod資源,最后由ingress或者nginx資源將程式發布到互聯網,

在這里插入圖片描述

3.微服務程式前期環境準備(配置、編譯、制作鏡像)

3.1.simple-microservice微服務專案介紹

本次使用的微服務為spring cloud的電商平臺專案

專案名稱:simple-microservice

simple-microservice微服務的各個程式:

  • eureka-service(注冊中心)
  • gateway-service(網管服務)
  • order-service(訂單服務)
  • product-service(商品服務)
  • portal-service(門戶網站)
  • stock-service(庫存服務)

用戶請求首先到Protal前端頁面,也就是程式的首頁,在首頁的各項功能操作都會由Gateway網關服務轉發到各自的微服務程式上,比如請求一個訂單服務,訂單服務會事先注冊到Eureka中,由Gateway將請求發送給Eureka,再由Eureka轉發給具體的微服務程式,這些微服務程式都有自己單獨的資料庫服務,

微服務程式的門戶網站會配置Gateway網關服務的地址,由門戶網站用戶請求的微服務資訊,轉發給Gateway網關程式,所有的微服務都會注冊在Eureka注冊中心中,Gateway網關會將請求通過注冊中心轉發給對應的微服務程式,
在這里插入圖片描述

該微服務程式代碼可以托管在gitlab代碼倉庫中,我們可以建立多個分支模擬從開發到上線的流程,理念:分別創建5個分支,在每個分支中增加對應的代碼,最后合并到master分支,也可以直接就在master分支上新增組態檔,我是直接拉取dev1分支,只有程式代碼的分支,然后新增一系列配置,最后上線,

拉取dev1分支,進行一系列配置的話,首先要把master分支里的protal程式代碼同步到dev1分支里,因為dev1的protal程式代碼有點bug,整個微服務運行完畢后,order訂單服務會報錯,

分別有五個分支:

  • dev1:交付代碼
  • dev2:新增程式打包的Dockerfile檔案
  • dev3:新增K8s資源編排Yaml檔案
  • dev4:微服務鏈路監控
  • dev5:新功能代碼更新上線
  • master:上線版本

在這里插入圖片描述

3.2.simple微服務部署到K8S邏輯架構

simple-microservice微服務部署到k8s平臺主要分為如下幾個步驟:

  • 修改程式組態檔,將資料庫等各組件地址修改為當前環境
  • 將各個微服務程式使用Maven編譯成可部署的jar包
  • 撰寫Dockerfile將程式做成docker鏡像

對K8S環境的要求:

一套完整的K8S集群、有cordns可以決議Service地址、Harbor鏡像倉庫、Nginx容器將專案發布到互聯網或者INgress資源將專案發布到互聯網,

微服務部署到K8S環境之后架構是怎樣的

首先用戶訪問網站的域名,請求達到前端頁面,點擊前端頁面中的功能跳轉到不同的微服務,比如商品服務,將商品服務的請求交個Gateway網關服務,由網關服務轉發給商品的微服務程式Product,各個微服務之間的呼叫,都從Eureka注冊中心讀取各個微服務的資訊完成調度,Product(商品)、Order(訂單)、Stock(庫存)都有單獨的資料庫,MySQL資料部署在K8S集群之外,

服務發布到互聯網采用Nginx而不采用Ingress,Nginx可以配置更多的引數,將Nginx容器運行在每一個Node主機上,映射Node主機的80/443埠,通過在hosts檔案里系結node主機ip+程式域名的方式訪問微服務,

在這里插入圖片描述

3.3.準備微服務各程式的組態檔

在使用Maven之前,首先將程式的組態檔進行修改,編譯成功之后再想修改組態檔內容,就需要重新編譯了,將每個微服務的環境地址都修改成自己環境的地址,

拉取dev1分支展開全新配置

3.3.1.創建微服務各個程式的prod組態檔

eureka(注冊中心)、gateway(網關)、order(訂單)、portal(首頁)、product(商品)、stock(庫存)這幾個微服務程式都需要配置,新建一個prod的組態檔,用于線上生產環境

order(訂單)、product(商品)、stock(庫存)這些微服務有兩個包,分別是xxx-biz和xxx-api,只需要部署biz目錄下的jar包即可,api的目錄只是存在一些依賴

order(訂單)、product(商品)、stock(庫存)這些微服務都有自己單獨的資料庫

先將prod的組態檔創建出來,待eureka專案部署完成后,再進行進一步的修改,最后將程式編譯

1.eureka-service組態檔

1.創建一個prod的組態檔
[root@binary-k8s-master1 ~/springcloud/simple-microservice-dev1]# cd eureka-service/src/main/resources/
[root@binary-k8s-master1 ~/springcloud/simple-microservice-dev1/eureka-service/src/main/resources]# cp application-fat.yml application-prod.yml

2.程式使用prod的組態檔運行
[root@binary-k8s-master1 ~/springcloud/simple-microservice-dev1/eureka-service/src/main/resources]# vim application.yml 
server:
  port: 8080				#eureka的埠號
spring:
  application:
    name: legendshop-basic-eureka
  profiles:
    active: prod		#將這里修改為prod就會呼叫prod組態檔

3.配置eureka服務的組態檔
[root@binary-k8s-master1 ~/springcloud/simple-microservice-dev1/eureka-service/src/main/resources]# vim application-prod.yml 
eureka:
  server:
    renewal-percent-threshold: 0.9
    enable-self-preservation: false
    eviction-interval-timer-in-ms: 40000
  instance:
    hostname: 127.0.0.1
    prefer-ip-address: true
  client:
    register-with-eureka: false
    serviceUrl:
      defaultZone: http://127.0.0.1:${server.port}/eureka/
    fetch-registry: false

2.gateway-service組態檔

1.創建一個prod的組態檔
[root@binary-k8s-master1 ~/springcloud/simple-microservice-dev1]# cd gateway-service/src/main/resources/
[root@binary-k8s-master1 ~/springcloud/simple-microservice-dev1/gateway-service/src/main/resources]# cp application-fat.yml application-prod.yml

2.程式使用prod的組態檔運行
[root@binary-k8s-master1 ~/springcloud/simple-microservice-dev1/gateway-service/src/main/resources]# cat application.yml 
server:
  port: 8080
spring:
  profiles:
    active: prod
  application:
    name: @artifactId@
    
3.配置程式組態檔    
[root@binary-k8s-master1 ~/springcloud/simple-microservice-dev1/gateway-service/src/main/resources]# vim application-prod.yml 
······
eureka:
  instance:
    prefer-ip-address: true
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://eureka-0.eureka-service:8080/eureka/			#修改eureka地址

3.order-service組態檔

1.創建一個prod的組態檔
[root@binary-k8s-master1 ~/springcloud/simple-microservice-dev1]# cd order-service/order-service-biz/src/main/resources/
[root@binary-k8s-master1 ~/springcloud/simple-microservice-dev1/order-service/order-service-biz/src/main/resources]# cp application-fat.yml application-prod.yml

2.程式使用prod的組態檔運行
[root@binary-k8s-master1 ~/springcloud/simple-microservice-dev1/order-service/order-service-biz/src/main/resources]# vim application.yml 
server:
  port: 8080
spring:
  profiles:
    active: prod
  application:
    name: order-service

3.配置程式組態檔    
[root@binary-k8s-master1 ~/springcloud/simple-microservice-dev1/order-service/order-service-biz/src/main/resources]# vim application-prod.yml 
spring:
  datasource:
    url: jdbc:mysql://192.168.20.11:3306/tb_order?characterEncoding=utf-8			#mysql資料庫地址
    username: root	
    password: 123456
    driver-class-name: com.mysql.jdbc.Driver

eureka:
  instance:
    prefer-ip-address: true
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://eureka-0.eureka-service:8080/eureka/			#eureka地址

5.product-service組態檔

1.創建一個prod的組態檔
[root@binary-k8s-master1 ~/springcloud/simple-microservice-dev1]# cd product-service/product-service-biz/src/main/resources/
[root@binary-k8s-master1 ~/springcloud/simple-microservice-dev1/product-service/product-service-biz/src/main/resources]# cp application-fat.yml application-prod.yml

2.程式使用prod的組態檔運行
[root@binary-k8s-master1 ~/springcloud/simple-microservice-dev1/product-service/product-service-biz/src/main/resources]# vim application.yml 
server:
  port: 8080
spring:
  profiles:
    active: prod
  application:
    name: product-service

3.配置程式組態檔
[root@binary-k8s-master1 ~/springcloud/simple-microservice-dev1/product-service/product-service-biz/src/main/resources]# vim application-prod.yml 
spring:
  datasource:
    url: jdbc:mysql://192.168.20.11:3306/tb_product?characterEncoding=utf-8			#資料庫地址
    username: root
    password: 123456
    driver-class-name: com.mysql.jdbc.Driver

eureka:
  instance:
    prefer-ip-address: true
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://eureka-0.eureka-service:8080/eureka/			#eureka地址

6.stock-service組態檔

1.創建一個prod的組態檔
[root@binary-k8s-master1 ~/springcloud/simple-microservice-dev1]# cd stock-service/stock-service-biz/src/main/resources/
[root@binary-k8s-master1 ~/springcloud/simple-microservice-dev1/stock-service/stock-service-biz/src/main/resources]# cp application-fat.yml application-prod.yml

2.程式使用prod的組態檔運行
[root@binary-k8s-master1 ~/springcloud/simple-microservice-dev1/stock-service/stock-service-biz/src/main/resources]# vim application.yml 
server:
  port: 8080
spring:
  profiles:
    active: prod
  application:
    name: stock-service

3.配置程式組態檔
[root@binary-k8s-master1 ~/springcloud/simple-microservice-dev1/stock-service/stock-service-biz/src/main/resources]# vim application-prod.yml 
spring:
  datasource:
    url: jdbc:mysql://192.168.20.11:3306/tb_stock?characterEncoding=utf-8		#資料庫地址
    username: root
    password: 123456
    driver-class-name: com.mysql.jdbc.Driver

eureka:
  instance:
    prefer-ip-address: true
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://eureka-service.eureka:8080/eureka/			#eureka地址                            

4.portal-service組態檔

1.創建一個prod的組態檔
[root@binary-k8s-master1 ~/springcloud/simple-microservice-dev1]# cd portal-service/src/main/resources/
[root@binary-k8s-master1 ~/springcloud/simple-microservice-dev1/portal-service/src/main/resources]# cp application-fat.yml application-prod.yml

2.程式使用prod的組態檔運行
[root@binary-k8s-master1 ~/springcloud/simple-microservice-dev1/portal-service/src/main/resources]# vim application.yml 
server:
  port: 8080
  undertow:
    io-threads: 16
    worker-threads: 256
    buffer-size: 1024
    direct-buffers: true
spring:
  application:
    name: portal-service
  profiles:
    active: prod

3.配置程式組態檔
[root@binary-k8s-master1 ~/springcloud/simple-microservice-dev1/portal-service/src/main/resources]# vim application-prod.yml 
eureka:
  instance:
    prefer-ip-address: true
  client:
    service-url:
      defaultZone: http://eureka-0.eureka-service:8080/eureka/			#指定eureka地址
    register-with-eureka: true
    fetch-registry: true
······

3.3.2.調整每個微服務的pom檔案增加prod環境

由于我們新加了一個prod線上環境的組態檔,因此也需要在pom.xml中配置,配置完成后可以編譯一下,看看是否可以做成可部署的程式包

1.安裝maven
[root@binary-k8s-master1 ~]# yum -y install java-1.8.0-openjdk maven

2.調整pom.xml增加prod環境配置
[root@binary-k8s-master1 simple-microservice-dev1]# vim pom.xml 
······			#65行左右
    <profile>
      <id>prod</id>
      <properties>
        <profileActive>prod</profileActive>
      </properties>
    </profile>

  </profiles>
······

2.編譯程式
[root@binary-k8s-master1 ~/springcloud/simple-microservice-dev1]# mvn clean package -D maven.test.skip=true -P prod

3.查看編譯成功的war包
[root@binary-k8s-master1 ~/springcloud/simple-microservice-dev1]# find . -name "*.jar"
./basic-common/basic-common-core/target/basic-common-core.jar
./eureka-service/target/eureka-service.jar
./gateway-service/target/gateway-service.jar
./order-service/order-service-api/target/order-service-api.jar
./order-service/order-service-biz/target/order-service-biz.jar
./portal-service/target/portal-service.jar
./product-service/product-service-api/target/product-service-api.jar
./product-service/product-service-biz/target/product-service-biz.jar
./stock-service/stock-service-api/target/stock-service-api.jar
./stock-service/stock-service-biz/target/stock-service-biz.jar

3.4.制作微服務程式所使用的的底層系統鏡像

3.4.1.為程式環境構建底層系統鏡像

由于是SpringCloud微服務系統,SpringCloud屬于JAVA語言開發的專案,因此要有JAVA啟動環境,

1.拉取centos7.5作為底層容器
[root@binary-k8s-master1 ~]# docker pull centos:7.5.1804

2.啟動容器
[root@binary-k8s-master1 ~]# docker run -itd centos:7.5.1804

3.進入系統容器進行環境配置
[root@binary-k8s-master1 ~]# docker exec -it 462237f9a0a bash
#安裝java環境
[root@2fcfb51f04e0 /]# yum -y install java-1.8.0-openjdk net-tools
[root@2fcfb51f04e0 /]# java  -version
openjdk version "1.8.0_302"
OpenJDK Runtime Environment (build 1.8.0_302-b08)
OpenJDK 64-Bit Server VM (build 25.302-b08, mixed mode)
[root@2fcfb51f04e0 /]# mkdir /data/simple-microservice -p
#調整系統時區
[root@2fcfb51f04e0 /]# yum -y intall tzdata
[root@2fcfb51f04e0 /]# ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 

4.將容器提交為鏡像
[root@binary-k8s-master1 ~]# docker commit 2fcfb51f04e0 centos-java:v1

5.配置Harbor鏡像倉庫
[root@binary-k8s-master1 ~]# vim /etc/docker/daemon.json 
{
  "registry-mirrors": ["https://9wn5tbfh.mirror.aliyuncs.com"],
  "insecure-registries": ["192.168.20.10"]
}
[root@binary-k8s-master1 ~]# systemctl restart docker

6.提交鏡像到Harbor倉庫
[root@binary-k8s-master1 ~]# docker login -u admin -p Harbor12345 192.168.20.10
[root@binary-k8s-master1 ~]# docker tag centos-java:v1 192.168.20.11/base/centos-java:v1
[root@binary-k8s-master1 ~]# docker push 192.168.20.11/base/centos-java:v1

3.4.2.為每個微服務程式撰寫Dockerfile

設計概念:

采用3.3.1中制作的底層鏡像

第一步:在鏡像里面創建/data/simple-microservice/微服務名稱這樣的目錄用于存放程式的jar包

第二步:將程式的jar包拷貝至鏡像中

第三步:生成一個啟動腳本,由于服務名稱都不一樣也就是每個程式的路徑都不同,想要做到一個底層鏡像多個程式復用,那么就需要在啟動腳本里手動指定程式的路徑,在腳本中指定程式的部署路徑以及日志路徑

第四步:暴露8080埠

將Dockerfile放到程式編譯的目錄也就是與src在同一目錄

1.eureka-service服務

在4.2.2.會寫

2.gateway-service服務

[root@binary-k8s-master1 ~/springcloud/simple-microservice-dev1/gateway-service]# vim Dockerfile 
FROM 192.168.20.11/base/centos-java:v1
RUN mkdir /data/simple-microservice/gateway-service -p
COPY ./target/gateway-service.jar /data/simple-microservice/gateway-service/
RUN echo -e "#!/bin/bash \njava -jar /data/simple-microservice/gateway-service/gateway-service.jar > /data/simple-microservice/gateway-service/gateway-service.log & \ntail -f /data/simple-microservice/gateway-service/gateway-service.log" > /data/entrypoint.sh && chmod a+x /data/entrypoint.sh
EXPOSE 8080
ENTRYPOINT /data/entrypoint.sh

3.order-service服務

[root@binary-k8s-master1 ~/springcloud/simple-microservice-dev1/order-service/order-service-biz]# vim Dockerfile 
FROM 192.168.20.11/base/centos-java:v1
RUN mkdir /data/simple-microservice/order-service -p
COPY ./target/order-service-biz.jar /data/simple-microservice/order-service/
RUN echo -e "#!/bin/bash \njava -jar /data/simple-microservice/order-service/order-service-biz.jar > /data/simple-microservice/order-service/order-service-biz.log & \ntail -f /data/simple-microservice/order-service/order-service-biz.log" > /data/entrypoint.sh && chmod a+x /data/entrypoint.sh
EXPOSE 8080
ENTRYPOINT /data/entrypoint.sh

4.portal-service服務

[root@binary-k8s-master1 ~/springcloud/simple-microservice-dev1/portal-service]# vim Dockerfile 
FROM 192.168.20.11/base/centos-java:v1
RUN mkdir /data/simple-microservice/portal-service -p
COPY ./target/portal-service.jar /data/simple-microservice/portal-service/
RUN echo -e "#!/bin/bash \njava -jar /data/simple-microservice/portal-service/portal-service.jar > /data/simple-microservice/portal-service/portal-service.log & \ntail -f /data/simple-microservice/portal-service/portal-service.log" > /data/entrypoint.sh && chmod a+x /data/entrypoint.sh
EXPOSE 8080
ENTRYPOINT /data/entrypoint.sh

5.product-service服務

[root@binary-k8s-master1 ~/springcloud/simple-microservice-dev1/product-service/product-service-biz]# vim Dockerfile
FROM 192.168.20.11/base/centos-java:v1
RUN mkdir /data/simple-microservice/product-service -p
COPY ./target/product-service-biz.jar /data/simple-microservice/product-service/
RUN echo -e "#!/bin/bash \njava -jar /data/simple-microservice/product-service/product-service-biz.jar > /data/simple-microservice/product-service/product-service-biz.log & \ntail -f /data/simple-microservice/product-service/product-service-biz.log" > /data/entrypoint.sh && chmod a+x /data/entrypoint.sh
EXPOSE 8080
ENTRYPOINT /data/entrypoint.sh

6.stock-service服務

[root@binary-k8s-master1 ~/springcloud/simple-microservice-dev1/stock-service/stock-service-biz]# cat Dockerfile
FROM 192.168.20.11/base/centos-java:v1
RUN mkdir /data/simple-microservice/stock-service -p
COPY ./target/stock-service-biz.jar /data/simple-microservice/stock-service/
RUN echo -e "#!/bin/bash \njava -jar /data/simple-microservice/stock-service/stock-service-biz.jar > /data/simple-microservice/stock-service/stock-service-biz.log & \ntail -f /data/simple-microservice/stock-service/stock-service-biz.log" > /data/entrypoint.sh && chmod a+x /data/entrypoint.sh
EXPOSE 8080
ENTRYPOINT /data/entrypoint.sh

3.5.調整Protal微服務中連接Gateway網關的地址

Protal是我們電商平臺的門戶網站,也就是前端首頁,在Protal微服務中會填寫好其他微服務程式的地址,Gateway網關程式的地址就是寫死在Protal專案的js里,在我們定義好Gateway網關服務的域名后,就要將域名寫入到對應的js檔案里,否則當專案啟動之后是無法調通的,

需要修改下列這四個檔案

portal-service/src/main/resources/static/js/orderList.js

portal-service/src/main/resources/static/js/productList.js
在這里插入圖片描述

打開這四個檔案,將里面的gateway.ctnrs.com域名修改為gateway.jiangxl.com域名

vim修改命令:%s/gateway.ctnrs.com/gateway.jiangxl.com/g

3.6.部署Ingress用于將微服務程式發布到互聯網

1.下載ingress部署的yaml檔案
[root@binary-k8s-master1 ~]# wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/mandatory.yaml
[root@binary-k8s-master1 ~]# wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/nginx-0.30.0/deploy/static/provider/baremetal/service-nodeport.yaml

2.調整ingress nodeport埠
[root@binary-k8s-master1 ~/springcloud/ingress]# vim service-nodeport.yaml
······
  ports:
    - name: http
      port: 80
      targetPort: 80
      nodePort: 80
      protocol: TCP
    - name: https
      port: 443
      targetPort: 443
      nodePort: 443
      protocol: TCP
······

3.部署ingress
[root@binary-k8s-master1 ~/springcloud/ingress]# kubectl apply -f mandatory.yaml

4.查看ingress部署的結果
[root@binary-k8s-master1 ~]# kubectl get all -n ingress-nginx
NAME                                            READY   STATUS    RESTARTS   AGE
pod/nginx-ingress-controller-766867958b-n7dwj   1/1     Running   0          49m

NAME                    TYPE       CLUSTER-IP   EXTERNAL-IP   PORT(S)                 AGE
service/ingress-nginx   NodePort   10.0.0.107   <none>        80:80/TCP,443:443/TCP   49m

NAME                                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx-ingress-controller   1/1     1            1           49m

NAME                                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-ingress-controller-766867958b   1         1         1       49m

4.在kubernetes集群部署simple微服務專案

simple微服務專案在K8S集群中部署,只有eureka服務采用statefulset控制器部署,其余所有微服務均采用deployment控制器部署,所有的微服務通過ingress發布在互聯網,

simple微服務電商專案在K8S集群部署流程

1)部署simple電商微服務專案的資料庫環境

2)在K8S中部署Eureka注冊中心

3)修改每個微服務的組態檔,指定eureka注冊中心集群的地址

4)使用maven將每個微服務構建成可部署的jar包

5)部署Gateway關服務

6)部署protal、order、product、stock服務

4.1.部署simple微服務程式的mysql資料庫環境

1.安裝MySQL資料庫
[root@harbor-mysql ~]# rpm -ivh http://repo.mysql.com/yum/mysql-5.6-community/el/7/x86_64/mysql-community-release-el7-5.noarch.rpm
[root@harbor-mysql ~]#  yum install mysql-community-server 

2.啟動MySQL
[root@harbor-mysql ~]# systemctl start mysqld
[root@harbor-mysql ~]# systemctl enable mysqld

3.設定資料庫密碼
[root@harbor-mysql ~]# mysqladmin -u root password '123456'

4.創建order(訂單)、product(商品)、stock(庫存)微服務的資料庫
[root@harbor-mysql ~]# mysql -uroot -p123456
mysql> create database tb_order;
Query OK, 1 row affected (0.00 sec)

mysql> create database tb_product;
Query OK, 1 row affected (0.01 sec)

mysql> create database tb_stock;
Query OK, 1 row affected (0.00 sec)

5.匯入資料庫資料
#將資料庫檔案傳到資料庫服務器
[root@binary-k8s-master1 simple-microservice-dev1]# scp -r db root@192.168.20.11:/root
#匯入order資料庫的資料
mysql> use tb_order
mysql> source /root/db/order.sql
#匯入product資料庫的資料
mysql> use tb_product
mysql> source /root/db/product.sql
#匯入stock資料庫的資料
mysql> use tb_stock;
mysql> source /root/db/stock.sql

6.允許資料庫遠程訪問
mysql> grant all privileges on *.* to 'root'@'%' identified by '123456' with grant option;
Query OK, 0 rows affected (0.00 sec)

4.2.部署eureka微服務注冊中心

Eureka在整個微服務架構中起到至關重要的的作用,必須保證Eureka服務高可用,

Eureka服務采用statefulset有狀態應用部署方式再K8S集群中進行部署,

Eureka本身就可以利用自身的服務發現來實作集群的高可用,只需要在Eureka組態檔中指定各個Eureka節點的地址就可以實作,

將程式部署在K8S之后,如何能夠保證每個Eureka Pod的地址唯一不變,就需要用到Statefulset控制器采用有狀態的應用部署,使用Statefulset控制器之后,每個Pod的名稱都是唯一不變的,并且每個Pod都有一個DNS服務發現地址,通過這個DNS地址就可以請求到Pod中的服務,主要是coredns組件來實作的,因此集群還需要安裝有coredns服務,我們可以將每一個Eureka Pod的DNS服務發現地址寫入到Eureka的組態檔中,每個Eureka節點相互注冊,最終形成高可用集群,

Statefulset+Headless部署的程式DNS名格式:<statefulsetName-index>.<service-name>.<namespace-name>.svc.cluster.local后面的.svc.cluster.local可以去掉,K8S默認就是.svc.cluster.local,

<statefulsetName-index>就是Pod的名稱,-index是每一個Pod名稱后面的數字編號,Statefulset控制器部署好的Pod,會在每一個Pod名稱后面加上一個數字編號,從0開始,一次累加,保證所有的Pod都有一個獨立的訪問入口

<service-name>是程式的service資源的名稱

<namespace-name>是程式所在的namespace名稱

我們的Eureka規定的節點數為3個,也就是最終statefulset會啟動3個Pod副本組成Eureka集群,

4.2.1.修改Eureka組態檔增加各節點地址

Eureka集群節點每個Pod副本服務發現地址如下,需要將其配置在eureka中

http://eureka-0.eureka-service.simple-ms
http://eureka-0.eureka-service.simple-ms
http://eureka-0.eureka-service.simple-ms

修改Eureka的組態檔,采用Dns服務發現地址的形式將每個節點的地址都寫在組態檔中,當Eureka啟動之后,每個節點都會相互發現最終形成高可用集群,

1.修改Eureka組態檔中的節點地址
[root@binary-k8s-master1 eureka-service]# vim src/main/resources/application-prod.yml
eureka:
  server:
    renewal-percent-threshold: 0.9
    enable-self-preservation: false
    eviction-interval-timer-in-simple-ms: 40000
  instance:
    hostname: 127.0.0.1
    prefer-ip-address: false
  client:
    register-with-eureka: true
    serviceUrl:
      defaultZone: http://eureka-0.eureka.simple-ms:${server.port}/eureka/,http://eureka-1.eureka.simple-ms:${server.port}/eureka/,http://eureka-2.eureka.simple-ms:${server.port}/eureka/
    fetch-registry: true

2.使用maven將最新的Eureka編譯
[root@binary-k8s-master1 simple-microservice-dev1]# mvn clean package -D maven.test.skip=true -P prod

注意:只能在專案最外層的目錄中執行mvn clean package

4.2.2.調整Eureka的Dockerfile

由于我們在Eureka組態檔中配置的是以dns名稱來互相發現對方,并不是以IP地址形式發現,因此我們需要配置Dockerfile,在啟動程式時將組態檔中的hostname欄位值修改為當前Pod的dns名稱,

因為我們的Eureka是多Pod組成的高可用集群,因此不能將dns名稱寫死在組態檔中,不然每個Pod都是同樣的地址,集群是組件不成功的,所以就需要在Dockerfile中定義程式啟動命令時,將dns名稱地址設定成變數,由Pod資源將變數值傳入到啟動命令中,程式啟動時就會用Pod的dns名稱地址替換掉組態檔中的IP地址,

1.修改DOckerfile檔案內容
[root@binary-k8s-master1 eureka-service]# vim Dockerfile 
FROM 192.168.20.11/base/centos-java:v1
RUN mkdir /data/simple-microservice/eureka-service -p
COPY ./target/eureka-service.jar /data/simple-microservice/eureka-service/
RUN echo -e "#!/bin/bash \njava -jar -Deureka.instance.hostname=${MY_POD_NAME}.eureka.simple-ms /data/simple-microservice/eureka-service/eureka-service.jar > /data/simple-microservice/eureka-service/eureka-service.log & \ntail -f /data/simple-microservice/eureka-service/eureka-service.log" > /data/entrypoint.sh && chmod a+x /data/entrypoint.sh
EXPOSE 8080
ENTRYPOINT /data/entrypoint.sh

啟動命令單獨拉出來看一下,-Deureka.instance.hostname這個引數表示修改組態檔中hostname引數的值,${MY_POD_NAME}這個變數使從deployment資源檔案中定義的env變數,將Pod的名稱賦給MY_POD_NAME變數,最后引入到啟動命令中,最后在組態檔中hostname欄位的值應該是eureka-0.eureka-service.simple-ms

java -jar -Deureka.instance.hostname=${MY_POD_NAME}.eureka-service.simple-ms /data/simple-microservice/eureka-service/eureka-service.jar

4.2.3.構建Eureka服務的Docker鏡像

[root@binary-k8s-master1 eureka-service]# docker build -t  192.168.20.11/simple-microservice/eureka-service:v1 .

[root@binary-k8s-master1 eureka-service]# docker images | grep eureka
192.168.20.11/simp-microservice/eureka-service        v1                  1dc64fc9ba09        About a minute ago   800MB

[root@binary-k8s-master1 eureka-service]# docker push 192.168.20.11/simple-microservice/eureka-service:v1

4.2.4.撰寫Eureka部署YAML資源檔案

1)創建命名空間

1.創建命名空間
# kubectl create ns simple-ms
namespace/simple-ms created

2.創建資源編排YAML檔案存放路徑
[root@binary-k8s-master1 ~]# mkdir springcloud/simple-microservice-dev1/k8s/

2)登錄Harbor

可以不在每一個Node節點使用docker login登陸Harbor倉庫,可以將Harbor倉庫的認證資訊做成secret,通過使用secret的方式連接Harbor,

[root@binary-k8s-master1 ~]# kubectl create secret docker-registry registry-pull-secret --docker-server=192.168.20.11 --docker-username=admin --docker-password=Harbor12345 --docker-email=admin@ctnrs.com -n simple-ms

3)撰寫資源YAML檔案

eureka要做成集群式的服務,所以要采用statefulset控制器部署,并采用headless service保證statefulset創建的pod名稱唯一性,最后通過ingress將eureka服務發布在互聯網環境,

[root@binary-k8s-master1 k8s]# vim eureka-deploy.yaml 
---
#ingress資源
apiVersion: extensions/v1beta1
kind: Ingress						#型別為ingress
metadata:							#定義元資料資訊:資源名稱、資源所在的命名空間
  name: eureka 
  namespace: simple-ms
spec:
  rules:									#定義ingress規則
    - host: eureka.jiangxl.com					#定義eureka使用的域名
      http:										#采用http型別的訪問方式
        paths:									#定義程式的url路徑
        - path: /
          backend:								#針對定義的程式路徑關于對應的后端service資源
            serviceName: eureka
            servicePort: 8080
            
---
#headless service資源
apiVersion: v1					
kind: Service
metadata:
  name: eureka
  namespace: simple-ms
spec:
  clusterIP: None				#ClusterIP資源設定為Node就代表headless型別的service
  ports:						#定義暴露的eureka埠號
  - port: 8080
    name: eureka 
  selector:						#標簽選擇器,關聯后端pod
    project: simple
    app: eureka

---
#statefulset資源
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: eureka
  namespace: simple-ms
spec:
  replicas: 3								#副本數
  selector:									#標簽選擇器
    matchLabels:
      project: simple					
      app: eureka
  serviceName: "eureka"						#service的名稱,也就是將來的pod名稱
  template:									
    metadata:
      labels:
        project: simple
        app: eureka
    spec:
      imagePullSecrets:						#harbor鏡像倉庫的憑據資訊
      - name: registry-pull-secret
      containers:
      - name: eureka
        image: 192.168.20.11/simple-microservice/eureka-service:v1
        ports:
          - protocol: TCP
            containerPort: 8080
        env:							#增加一個環境變數,變數名為MY_POD_NAME,值為pod的名稱,這個變數資訊會傳入dockerfile中
          - name: MY_POD_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.name
        resources:						#資源配額
          requests:						#最小資源限制,cpu為0.5,記憶體為256M
            cpu: 0.5
            memory: 256Mi
          limits:						#最大資源限制,cpu為1,記憶體為1G
            cpu: 1 					
            memory: 1Gi
        readinessProbe:					#就緒性健康檢查
          tcpSocket:					#以tcp 8080埠作為健康檢查的機制
            port: 8080	
          initialDelaySeconds: 60			#容器啟動60秒后進行檢測
          periodSeconds: 10					#探測的頻率
        livenessProbe:						#存活性健康檢查
          tcpSocket:						#以tcp 8080埠作為健康檢查的機制
            port: 8080	
          initialDelaySeconds: 60				#容器啟動60秒后進行檢查
          periodSeconds: 10						#探測的頻率為10秒一次

4.2.5.在K8S集群中部署Eureka注冊中心

1.部署eureka服務
[root@binary-k8s-master1 k8s]# kubectl apply -f eureka-deploy.yaml 

2.查看部署的資源狀態
[root@binary-k8s-master1 k8s]# kubectl get all -n simple-ms
NAME           READY   STATUS    RESTARTS   AGE
pod/eureka-0   1/1     Running   1          12h
pod/eureka-1   1/1     Running   0          12h
pod/eureka-2   1/1     Running   0          12h

NAME             TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
service/eureka   ClusterIP   None         <none>        8080/TCP   13h

NAME                      READY   AGE
statefulset.apps/eureka   3/3     13h

3.查看eureka的ingress狀態
[root@binary-k8s-master1 k8s]# kubectl get ingress -n simple-ms
NAME     CLASS    HOSTS                ADDRESS      PORTS   AGE
eureka   <none>   eureka.jiangxl.com   10.0.0.107   80      13h

首先在本地hosts檔案中系結eureka域名決議,然后在瀏覽器中輸入eureka.jiangxl.com訪問eureka服務,

在這里插入圖片描述

4.3.配置各個微服務程式連接Eureka集群的地址

在程式的組態檔中填寫eureka集群所有節點的服務發現地址

1.gateway-service組態檔

# vim gateway-service/src/main/resources/application-prod.yml 
······
eureka:
  instance:
    prefer-ip-address: true
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://eureka-0.eureka.simple-ms:8080/eureka,http://eureka-1.eureka.simple-ms:8080/eureka,http://eureka-2.eureka.simple-ms:8080/eureka

2.order-service組態檔

# vim order-service/order-service-biz/src/main/resources/application-prod.yml 
spring:
  datasource:
    url: jdbc:mysql://192.168.20.11:3306/tb_order?characterEncoding=utf-8
    username: root
    password: 123456
    driver-class-name: com.mysql.jdbc.Driver

eureka:
  instance:
    prefer-ip-address: true
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://eureka-0.eureka.simple-ms:8080/eureka,http://eureka-1.eureka.simple-ms:8080/eureka,http://eureka-2.eureka.simple-ms:8080/eureka

3.product-service組態檔

# vim product-service/product-service-biz/src/main/resources/application-prod.yml 
spring:
  datasource:
    url: jdbc:mysql://192.168.20.11:3306/tb_product?characterEncoding=utf-8
    username: root
    password: 123456
    driver-class-name: com.mysql.jdbc.Driver

eureka:
  instance:
    prefer-ip-address: true
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://eureka-0.eureka.simple-ms:8080/eureka,http://eureka-1.eureka.simple-ms:8080/eureka,http://eureka-2.eureka.simple-ms:8080/eureka

4.stock-service組態檔

# vim stock-service/stock-service-biz/src/main/resources/application-prod.yml 
spring:
  datasource:
    url: jdbc:mysql://192.168.20.11:3306/tb_stock?characterEncoding=utf-8
    username: root
    password: 123456
    driver-class-name: com.mysql.jdbc.Driver

eureka:
  instance:
    prefer-ip-address: true
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://eureka-0.eureka.simple-ms:8080/eureka,http://eureka-1.eureka.simple-ms:8080/eureka,http://eureka-2.eureka.simple-ms:8080/eureka

5.portal-service組態檔

# vim portal-service/src/main/resources/application-prod.yml 
eureka:
  instance:
    prefer-ip-address: true
  client:
    service-url:
      defaultZone: http://eureka-0.eureka.simple-ms:8080/eureka,http://eureka-1.eureka.simple-ms:8080/eureka,http://eureka-2.eureka.simple-ms:8080/eureka
    register-with-eureka: true
    fetch-registry: true
······

4.4.將各個程式代碼編譯成可部署的程式

[root@binary-k8s-master1 simple-microservice-dev1]# mvn clean package -D maven.test.skip=true -P prod

4.3.中部署Gateway網關服務

4.3.1.將Gateway程式打包成docker鏡像

[root@binary-k8s-master1 gateway-service]# docker build -t 192.168.20.11/simple-microservice/gateway-service:v1 .

4.3.2.在K8S集群中部署Gateway網關服務

所有程式的資源YAML檔案都存放在/root/springcloud/simple-microservice-dev1/k8s路徑,

微服務程式的話就不需要有狀態應用部署了,直接采用deployment無狀態應用部署的控制器,欄位配置和eureka服務的statefulset配置引數幾乎是一樣的,微服務的各個程式也都采用有deployment控制器去部署,每個程式的yaml檔案也只有名字、使用的鏡像不同,其余所有引數均一致,

gateway是網關服務,需要配置一個ingress和service資源,將其發布在集群之外,

欄位配置和statefulset的一致,不再做注釋資訊

# vim gateway-deploy.yaml
---
#ingress資源YAML
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: gateway 
  namespace: simple-ms 
spec:
  rules:
    - host: gateway.jiangxl.com 
      http:
        paths:
        - path: /
          backend:
            serviceName: gateway
            servicePort: 8080

---
#service資源YAML
apiVersion: v1
kind: Service
metadata:
  name: gateway
  namespace: simple-ms
spec:
  ports:
  - port: 8080
    name: gateway
  selector:
    project: simple
    app: gateway

---
#deployment資源YAML
apiVersion: apps/v1
kind: Deployment 
metadata:
  name: gateway
  namespace: simple-ms 
spec:
  replicas: 1					#副本數設定1個,后續再加
  selector:
    matchLabels:
      project: simple
      app: gateway
  template:
    metadata:
      labels:
        project: simple 
        app: gateway
    spec:
      imagePullSecrets:
      - name: registry-pull-secret
      containers:
      - name: gateway
        image: 192.168.20.11/simple-microservice/gateway-service:v1
        imagePullPolicy: Always
        ports:
          - protocol: TCP
            containerPort: 8080 
        resources:
          requests:
            cpu: 0.5
            memory: 256Mi
          limits:
            cpu: 1
            memory: 1Gi
        readinessProbe:
          tcpSocket:
            port: 8080
          initialDelaySeconds: 60
          periodSeconds: 10
        livenessProbe:
          tcpSocket:
            port: 8080
          initialDelaySeconds: 60
          periodSeconds: 10

4.3.3.在K8S集群中部署Gateway網關服務

1.部署網關服務
[root@binary-k8s-master1 k8s]# kubectl apply -f gateway-deploy.yaml

2.查看gateway pod資源的狀態
[root@binary-k8s-master1 k8s]# kubectl get pod -n simple-ms
NAME                       READY   STATUS    RESTARTS   AGE
eureka-0                   1/1     Running   1          2d12h
eureka-1                   1/1     Running   0          2d12h
eureka-2                   1/1     Running   0          2d12h
gateway-7c687f6c45-mcwpf   1/1     Running   0          2m2s

3.查看deployment和svc的資源狀態
[root@binary-k8s-master1 k8s]# kubectl get deploy,svc -n simple-ms
NAME                      READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/gateway   1/1     1            1           17h

NAME              TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
service/eureka    ClusterIP   None         <none>        8080/TCP   2d13h
service/gateway   ClusterIP   10.0.0.188   <none>        8080/TCP   17h

4.查看gateway ingress資源狀態
[root@binary-k8s-master1 k8s]# kubectl get ingress -n simple-ms
NAME      CLASS    HOSTS                 ADDRESS      PORTS   AGE
eureka    <none>   eureka.jiangxl.com    10.0.0.107   80      2d13h
gateway   <none>   gateway.jiangxl.com   10.0.0.107   80      17h

4.4.撰寫快速部署微服務到K8S集群的腳本

由于微服務程式眾多,并且每個程式在K8S集群部署的流程也基本一樣,因此我們撰寫一個部署腳本,只要準備好程式的jar包以及資源YAML檔案就可以將其一鍵部署到K8S集群,當前也可以通過Helm來實作,

1.腳本內容

實作邏輯:

1.將harbor倉庫的地址、所有微服務的名稱、k8s yaml檔案的路徑、微服務代碼所在的路徑都定義成環境變數,

2.如果只想部署其中一個微服務的話,通過位置傳參的方式來實作,也就是再定義一個微服務名稱的變數,變數值為KaTeX parse error: Expected '}', got 'EOF' at end of input: {1:-{service_list}},將要部署的微服務名稱通過位置傳參的方式,將值傳入到service_list變數名里,覆寫原service_list變數值,實作單個微服務的部署,如果沒有使用位置引數,那么默認部署全部的微服務,

3.進入微服務代碼所在的路徑,然后通過for回圈的方式,遍歷service_list變數中的各個微服務,然后本次回圈的微服務代碼路徑,判斷是否有包含biz的目錄,如果有biz目錄則切入到biz目錄,然后通過變數的形式定義鏡像名稱,構建鏡像、推送至鏡像倉庫,

4.將最新打包好的docker進在yaml檔案中通過sed命令替換,最后在k8s集群中部署這個微服務,

${1:-${service_list}}:這個的意思就是如果$1位置引數沒有傳入值,那么service_list變數的值就是$service_list變數的值,相當于一個判斷,

本腳本可以自動化完成微服務到K8S集群的一個部署,包括程式的編譯、打包成docker鏡像、推薦鏡像到Harbor倉庫,最后將程式部署到K8S集群

#!/bin/bash
registry_addr=192.168.20.11
service_list="eureka-service gateway-service order-service product-service stock-service portal-service"
service_list=${1:-${service_list}}      
current_dir=/root/springcloud/simple-microservice-dev1/k8s
service_dir=$(dirname $current_dir)

cd $service_dir
#mvn clean package -Dmaven.test.skip=true

for service in $service_list; do
   cd $service_dir/$service
   biz_count=`ls | grep biz | wc -l`
   if [ $biz_count -eq 1 ];then
      cd ${service}-biz
   fi
   service_name=`echo $service | awk -F- '{print $1}'`
   image_name=${registry_addr}/simple-microservice/${service}:v1
   yaml_name=${service_name}-deploy.yaml
   docker build -t ${image_name} .
   docker push ${image_name}
   sed -i -r "s#(image: )(.*)#\1$image_name#" ${current_dir}/${yaml_name}
   kubectl apply -f ${current_dir}/${yaml_name}
done

2.腳本使用方式

執行本腳本前提是必須先將程式部署的YAML檔案準備好,放在/root/springcloud/simple-microservice-dev1/k8s路徑

腳本的用法:
sh deploy_k8s.sh 微服務名稱

4.5.使用腳本部署Order訂單服務

4.5.1.撰寫資源部署YAML檔案

# vim order-deploy.yaml 
apiVersion: apps/v1
kind: Deployment 
metadata:
  name: order
  namespace: simple-ms 
spec:
  replicas: 1
  selector:
    matchLabels:
      project: simple
      app: order
  template:
    metadata:
      labels:
        project: simple 
        app: order
    spec:
      imagePullSecrets:
      - name: registry-pull-secret
      containers:
      - name: order
        image: 192.168.20.11/simple-microservice/order-service:v1
        imagePullPolicy: Always
        ports:
          - protocol: TCP
            containerPort: 8080 
        resources:
          requests:
            cpu: 0.5
            memory: 256Mi
          limits:
            cpu: 1
            memory: 1Gi
        readinessProbe:
          tcpSocket:
            port: 8080
          initialDelaySeconds: 60
          periodSeconds: 10
        livenessProbe:
          tcpSocket:
            port: 8080
          initialDelaySeconds: 60
          periodSeconds: 10

4.5.2在K8S集群中部署Order訂單服務

1.使用腳本將Order服務部署到K8S集群

[root@binary-k8s-master1 k8s]# sh deploy_k8s.sh order-service

執行完腳本,order程式的docker鏡像已經制作好并且推送到了harbor倉庫,已經使用sed命令將鏡像的名稱在yaml中替換成了最新的鏡像,部署到了K8S集群

在這里插入圖片描述

2.查看程式資源的狀態

1.查看pod的狀態
[root@binary-k8s-master1 k8s]# kubectl get all -n simple-ms
NAME                          READY   STATUS    RESTARTS   AGE
pod/eureka-0                  1/1     Running   1          2d15h
pod/eureka-1                  1/1     Running   0          2d15h
pod/eureka-2                  1/1     Running   0          2d15h
pod/gateway-8665d5d56-tx2m8   1/1     Running   0          39m
pod/order-6694f4c474-cp5d6    1/1     Running   0          35m

2.查看deployment資源的狀態
[root@binary-k8s-master1 k8s]# kubectl get deploy -n simple-ms
NAME      READY   UP-TO-DATE   AVAILABLE   AGE
gateway   1/1     1            1           21h
order     1/1     1            1           36m

4.6.使用腳本部署Product商品服務

4.6.1.撰寫資源部署YAML檔案

# vim product-deploy.yaml 
apiVersion: apps/v1
kind: Deployment 
metadata:
  name: product
  namespace: simple-ms 
spec:
  replicas: 1
  selector:
    matchLabels:
      project: simple
      app: product
  template:
    metadata:
      labels:
        project: simple 
        app: product
    spec:
      imagePullSecrets:
      - name: registry-pull-secret
      containers:
      - name: product
        image: 192.168.20.11/simple-microservice/product-service:v1
        imagePullPolicy: Always
        ports:
          - protocol: TCP
            containerPort: 8080 
        resources:
          requests:
            cpu: 0.5
            memory: 256Mi
          limits:
            cpu: 1
            memory: 1Gi
        readinessProbe:
          tcpSocket:
            port: 8080
          initialDelaySeconds: 60
          periodSeconds: 10
        livenessProbe:
          tcpSocket:
            port: 8080
          initialDelaySeconds: 60
          periodSeconds: 10

4.6.2.在K8S集群中熟不熟Product商品服務

1.使用腳本在K8S集群中部署product服務

[root@binary-k8s-master1 k8s]# sh deploy_k8s.sh product-service

在這里插入圖片描述

2.查看程式資源的狀態

1.查看pod的狀態
[root@binary-k8s-master1 k8s]# kubectl get pod -n simple-ms
NAME                       READY   STATUS    RESTARTS   AGE
eureka-1                   1/1     Running   3          2d16h
eureka-2                   1/1     Running   2          2d16h
gateway-8665d5d56-tx2m8    1/1     Running   2          74m
order-6694f4c474-cp5d6     1/1     Running   4          69m
product-77c8bb6847-vbxnr   1/1     Running   2          21m

2.查看deployment資源的狀態
[root@binary-k8s-master1 k8s]# kubectl get deploy -n simple-ms
NAME      READY   UP-TO-DATE   AVAILABLE   AGE
gateway   1/1     1            1           21h
order     1/1     1            1           72m
product   1/1     1            1           24m

4.7.使用腳本部署Stock庫存服務

4.7.1.撰寫資源部署YAML檔案

# vim product-deploy.yaml 
apiVersion: apps/v1
kind: Deployment 
metadata:
  name: product
  namespace: simple-ms 
spec:
  replicas: 1
  selector:
    matchLabels:
      project: simple
      app: product
  template:
    metadata:
      labels:
        project: simple 
        app: product
    spec:
      imagePullSecrets:
      - name: registry-pull-secret
      containers:
      - name: product
        image: 192.168.20.11/simple-microservice/product-service:v1
        imagePullPolicy: Always
        ports:
          - protocol: TCP
            containerPort: 8080 
        resources:
          requests:
            cpu: 0.5
            memory: 256Mi
          limits:
            cpu: 1
            memory: 1Gi
        readinessProbe:
          tcpSocket:
            port: 8080
          initialDelaySeconds: 60
          periodSeconds: 10
        livenessProbe:
          tcpSocket:
            port: 8080
          initialDelaySeconds: 60
          periodSeconds: 10

4.7.2.在K8S集群中部署Stock庫存服務

1.使用腳本在K8S集群中部署stock服務

[root@binary-k8s-master1 k8s]# sh deploy_k8s.sh stock-service

在這里插入圖片描述

2.查看程式資源的狀態

1.查看pod的狀態
[root@binary-k8s-master1 ~]# kubectl get pod -n simple-ms
NAME                       READY   STATUS    RESTARTS   AGE
eureka-0                   1/1     Running   5          2d16h
eureka-1                   1/1     Running   3          2d16h
eureka-2                   1/1     Running   2          2d16h
gateway-8665d5d56-tx2m8    1/1     Running   2          112m
order-6694f4c474-cp5d6     1/1     Running   4          107m
product-77c8bb6847-vbxnr   1/1     Running   2          59m
stock-6cf98bb445-mxf7b     1/1     Running   0          30m

2.查看deployment資源的狀態
[root@binary-k8s-master1 ~]# kubectl get deploy -n simple-ms
NAME      READY   UP-TO-DATE   AVAILABLE   AGE
gateway   1/1     1            1           22h
order     1/1     1            1           108m
product   1/1     1            1           60m
stock     2/2     2            2           31m

4.8.使用腳本部署Portal前端首頁

4.8.1.撰寫資源部署YAML檔案

# vim portal-deploy.yaml 
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: portal 
  namespace: simple-ms 
spec:
  rules:
    - host: portal.jiangxl.com 
      http:
        paths:
        - path: /
          backend:
            serviceName: portal 
            servicePort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: portal
  namespace: simple-ms
spec:
  ports:
  - port: 8080
    name: portal 
  selector:
    project: simple
    app: portal
---
apiVersion: apps/v1
kind: Deployment 
metadata:
  name: portal
  namespace: simple-ms 
spec:
  replicas: 1
  selector:
    matchLabels:
      project: simple
      app: portal
  template:
    metadata:
      labels:
        project: simple 
        app: portal
    spec:
      imagePullSecrets:
      - name: registry-pull-secret
      containers:
      - name: portal
        image: 192.168.20.11/simple-microservice/portal-service:v1
        imagePullPolicy: Always
        ports:
          - protocol: TCP
            containerPort: 8080 
        resources:
          requests:
            cpu: 0.5
            memory: 256Mi
          limits:
            cpu: 1
            memory: 1Gi
        readinessProbe:
          tcpSocket:
            port: 8080
          initialDelaySeconds: 60
          periodSeconds: 10
        livenessProbe:
          tcpSocket:
            port: 8080
          initialDelaySeconds: 60
          periodSeconds: 10

4.8.2.在K8S集群中熟不熟Portal存服務

1.使用腳本在K8S集群中部署portal服務

[root@binary-k8s-master1 k8s]# sh deploy_k8s.sh portal-service

在這里插入圖片描述

2.查看程式資源的狀態

到此為止,所有的simple電商平臺的微服務程式以及全部部署完畢,

1.查看所有微服務的程式
[root@binary-k8s-master1 k8s]# kubectl get all -n simple-ms
NAME                           READY   STATUS    RESTARTS   AGE
pod/eureka-0                   1/1     Running   5          2d16h
pod/eureka-1                   1/1     Running   3          2d16h
pod/eureka-2                   1/1     Running   2          2d16h
pod/gateway-8665d5d56-tx2m8    1/1     Running   2          117m
pod/order-6694f4c474-cp5d6     1/1     Running   4          112m
pod/portal-d5d55b784-7kntp     1/1     Running   0          2m53s
pod/product-77c8bb6847-vbxnr   1/1     Running   2          64m
pod/stock-6cf98bb445-mxf7b     1/1     Running   0          35m

NAME              TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
service/eureka    ClusterIP   None         <none>        8080/TCP   2d18h
service/gateway   ClusterIP   10.0.0.188   <none>        8080/TCP   22h
service/portal    ClusterIP   10.0.0.190   <none>        8080/TCP   2m53s

NAME                      READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/gateway   1/1     1            1           22h
deployment.apps/order     1/1     1            1           112m
deployment.apps/portal    1/1     1            1           2m53s
deployment.apps/product   1/1     1            1           65m
deployment.apps/stock     1/1     1            1           35m

NAME                                 DESIRED   CURRENT   READY   AGE
replicaset.apps/gateway-8665d5d56    1         1         1       117m
replicaset.apps/order-6694f4c474     1         1         1       112m
replicaset.apps/portal-d5d55b784     1         1         1       2m53s
replicaset.apps/product-77c8bb6847   1         1         1       64m
replicaset.apps/stock-6cf98bb445     1         1         1       35m

NAME                      READY   AGE
statefulset.apps/eureka   3/3     2d18h

2.查看所有微服務的ingress資源
[root@binary-k8s-master1 k8s]# kubectl get ingress -n simple-ms
NAME      CLASS    HOSTS                 ADDRESS      PORTS   AGE
eureka    <none>   eureka.jiangxl.com    10.0.0.107   80      2d18h
gateway   <none>   gateway.jiangxl.com   10.0.0.107   80      22h
portal    <none>   portal.jiangxl.com    10.0.0.107   80      3m16s

4.9.查看Eureka注冊中心中各個微服務的資訊

每個微服務程式均在Eureka注冊中心中注冊完成,

在這里插入圖片描述

4.10.使用simple微服務電商平臺

到4.8步驟之后,我們的simple微服務電商平臺已經全部部署在K8S集群了,可以在本機hosts里系結simple微服務的域名,操作電商平臺,

在這里插入圖片描述

這個微服務平臺的背景圖其實是京東的一張圖而已,是不可以點的,

在這里插入圖片描述

只能在商品服務中查詢能購買的商品,然后進行購買,最后在訂單服務中查詢,

搜索商品時會呼叫product商品微服務,下單后,查詢訂單服務時會呼叫order訂單服務,

點擊查詢商品服務,我們來下單一個美女觀察一下效果,下單后會提示下單成功,

在這里插入圖片描述

點擊查詢訂單服務就可以看到我嗎下的訂單了

在這里插入圖片描述

5.基于K8S集群的微服務的擴容與升級

5.1.微服務的擴容

微服務在物理機環境運行時,網站并發量高的情況下,擴容只能去購買云服務器,然后搭建一套一模一樣的服務,手動組成負載均衡集群,增加一臺其實還好,如果要增加幾十臺,太費人工成本了,

當微服務遷移到K8S集群之后,擴容其實變得非常簡單,只需要增加程式Pod的副本數就可以完成程式的擴容,

命令如下,以擴展order商品微服務為例,

將order商品服務的副本數調整為3個,原本是1個,現在擴容到3個
[root@binary-k8s-master1 k8s]# kubectl scale deploy order --replicas=3 -n simple-ms
deployment.apps/order scaled

可以看到order訂單服務目前已經有3個pod副本了
[root@binary-k8s-master1 ~]# kubectl get pod -n simple-ms
NAME                       READY   STATUS    RESTARTS   AGE
eureka-0                   1/1     Running   1          6m15s
eureka-1                   1/1     Running   0          7m59s
eureka-2                   1/1     Running   1          9m40s
gateway-848874fc9d-pwp9w   1/1     Running   0          48m
order-6694f4c474-cp5d6     1/1     Running   4          3h29m
order-6694f4c474-kh8hm     1/1     Running   0          96s
order-6694f4c474-rg7kw     1/1     Running   0          96s
portal-6fdcd765bd-mtq68    1/1     Running   1          24m
product-784d9f77b5-rxsf2   1/1     Running   0          64m
stock-6cf98bb445-l8gxb     1/1     Running   0          133m

縮容也很簡單,將order的副本數縮減成1個
[root@binary-k8s-master1 k8s]# kubectl scale deploy order --replicas=1 -n simple-ms
deployment.apps/order scaled

成功縮減到1個副本
[root@binary-k8s-master1 ~]# kubectl get pod -n simple-ms
NAME                       READY   STATUS    RESTARTS   AGE
eureka-0                   1/1     Running   1          9m24s
eureka-1                   1/1     Running   0          11m
eureka-2                   1/1     Running   1          12m
gateway-848874fc9d-pwp9w   1/1     Running   0          51m
order-6694f4c474-rg7kw     1/1     Running   0          4m45s
portal-6fdcd765bd-mtq68    1/1     Running   1          27m
product-784d9f77b5-rxsf2   1/1     Running   0          67m
stock-6cf98bb445-l8gxb     1/1     Running   0          136m

5.2.微服務的升級

微服務在物理機環境更新時只需要拉取最新的代碼,編譯成jar包,在服務器上部署就可以了,但是微服務遷移到K8S集群之后,更新程序就變得比較復雜了,首先更新的代碼,然后編譯成jar包,再通過Dockerfile將jar包做成docker鏡像,然后在k8s集群中部署,當然這些流程可以通過Jenkins實作自動化上線,

5.2.1.微調Portal前端首頁的代碼

將平臺的這些檔案修改成jiangxl.com的內容完成一次portal前端首頁的升級

在這里插入圖片描述

首先找到記錄這些文字的檔案

在這里插入圖片描述

# vim templates/index.ftl
# vim templates/orderList.ftl 
# vim templates/productList.ftl

進入檔案后在末行模式輸入:
%s/容器學院 www.ctnrs.com/jiangxl.com/g
%s/www.ctnrs.com/jiangxl.com/g
然后將所有的容器學院的文字洗掉

5.2.2.編譯最新代碼

[root@binary-k8s-master1 simple-microservice-dev1]# mvn clean package -D maven.test.skip=true -P prod

5.2.3.通過腳本將Protal最新代碼打包成鏡像

直接使用前面部署程式的腳本即可

[root@binary-k8s-master1 k8s]# sh deploy_k8s.sh portal-service

5.2.4.升級K8S集群中的Protal微服務

[root@binary-k8s-master1 k8s]# kubectl -n simple-ms set image deployment portal portal=192.168.20.11/simple-microservice/portal-service:v1 --record

程式更新完成后重繪頁面就可以看到我們更新的頁面內容
在這里插入圖片描述

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/374749.html

標籤:java

上一篇:SpringBoot整合阿里云視頻點播

下一篇:面試官:說說你了解幾種限流演算法,手寫個demo?

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more