




- 
動態服務發現
 - 
負載均衡
 - 
TLS 終止
 - 
HTTP / 2 和 gRPC 代理
 - 
斷路器
 - 
健康檢查
 - 
流量分割
 - 
故障註入
 - 
監控指標
 

route:- destination:host: productpageport:number: 9080
spec:host: productpagesubsets:- labels:version: v1name: v1trafficPolicy:connectionPool:http:http1MaxPendingRequests: 1maxRequestsPerConnection: 1tcp:maxConnections: 1tls:
apiVersion: networking.istio.io/v1alpha3kind: ServiceEntrymetadata:name: external-svc-mongoclusterspec:hosts:- mymongodb.somedomain # not usedaddresses:- 192.192.192.192/24 # VIPsports:- number: 27018name: mongodbprotocol: MONGOlocation: MESH_INTERNALresolution: STATICendpoints:- address: 2.2.2.2- address: 3.3.3.3
spec:selector:istio: ingressgatewayservers:- hosts:- '*'port:name: httpnumber: 80protocol: HTTP














- 
分散式事務監控
 - 
服務呼叫問題根因分析
 - 
服務依賴性分析
 - 
效能/延遲最佳化
 



- 
Productpage 使用 Python 開發,負責展示書籍的名稱和書籍的簡介。
 - 
Details 使用 Ruby 開發,負責展示書籍的詳細資訊。
 - 
Reviews 使用 Java 開發,負責顯示書評。
 - 
Ratings 使用 Node.js 開發,負責顯示書籍的評星。
 


- 
書籍的名稱:”The Comedy of Errors”,翻譯成中文是《錯誤的喜劇》。
 - 
書籍的簡介:Summary。翻譯成中文是:《錯誤的喜劇》是威廉·莎士比亞早期劇作之一。這是他最短的、也是他最喜歡的喜劇之一,除了雙關語和文字遊戲之外,幽默的主要部分來自於打鬧和錯誤的身份。
 
Type:paperbackPages:200Publisher:PublisherALanguage:EnglishISBN-10:1234567890ISBN-13:123-1234567890
An extremely entertaining play by Shakespeare. The slapstick humour is refreshing!Absolutely fun and entertaining. The play lacks thematic depth when compared to other plays by Shakespeare.

def getProducts():return [{'id': 0,'title': 'The Comedy of Errors','descriptionHtml': 'Wikipedia Summary: The Comedy of Errors is one of < b>William Shakespeare\'s< /b> early plays. It is his shortest and one of his most farcical comedies, with a major part of the humour coming from slapstick and mistaken identity, in addition to puns and word play.'}
details = {"name" : "http://details{0}:9080".format(servicesDomain),"endpoint" : "details","children" : []}ratings = {"name" : "http://ratings{0}:9080".format(servicesDomain),"endpoint" : "ratings","children" : []}reviews = {"name" : "http://reviews{0}:9080".format(servicesDomain),"endpoint" : "reviews","children" : [ratings]}productpage = {"name" : "http://details{0}:9080".format(servicesDomain),"endpoint" : "details","children" : [details, reviews]}service_dict = {"productpage" : productpage,"details" : details,"reviews" : reviews,}
private String getJsonResponse (String productId, int starsReviewer1, int starsReviewer2) {String result = "{";result += "\"id\": \"" + productId + "\",";result += "\"reviews\": [";// reviewer 1:result += "{";result += " \"reviewer\": \"Reviewer1\",";result += " \"text\": \"An extremely entertaining play by Shakespeare. The slapstick humour is refreshing!\"";if (ratings_enabled) {if (starsReviewer1 != -1) {result += ", \"rating\": {\"stars\": " + starsReviewer1 + ", \"color\": \"" + star_color + "\"}";}else {result += ", \"rating\": {\"error\": \"Ratings service is currently unavailable\"}";}}result += "},";// reviewer 2:result += "{";result += " \"reviewer\": \"Reviewer2\",";result += " \"text\": \"Absolutely fun and entertaining. The play lacks thematic depth when compared to other plays by Shakespeare.\"";if (ratings_enabled) {if (starsReviewer2 != -1) {result += ", \"rating\": {\"stars\": " + starsReviewer2 + ", \"color\": \"" + star_color + "\"}";}else {result += ", \"rating\": {\"error\": \"Ratings service is currently unavailable\"}";}}result += "}";result += "]";result += "}";return result;}
- 
star_color 表示評星的顏色(黑色和紅色)。
 - 
ratings_enabled 表示是否啟用評星。
 
private final static String star_color = System.getenv("STAR_COLOR") == null ? "black" : System.getenv("STAR_COLOR");
- 
如果不指定 STARCOLOR 變數且 ratingsenabled 為 true,那麼評星預設為黑色。
 - 
如果指定 STARCOLOR 變數且 ratingsenabled 為 true,那麼評星顏色為傳入的顏色。
 - 
如果不指定 ratings_enabled 為 true,那麼將不會顯示評星。
 
#java build the app.docker run --rm -v "$(pwd)":/home/gradle/project -w /home/gradle/project gradle:4.8.1 gradle clean buildpushd reviews-wlpcfg#plain build -- no ratingsdocker build -t "istio/examples-bookinfo-reviews-v1:${VERSION}" -t istio/examples-bookinfo-reviews-v1:latest --build-arg service_version=v1 .#with ratings black starsdocker build -t "istio/examples-bookinfo-reviews-v2:${VERSION}" -t istio/examples-bookinfo-reviews-v2:latest --build-arg service_version=v2 \--build-arg enable_ratings=true .#with ratings red starsdocker build -t "istio/examples-bookinfo-reviews-v3:${VERSION}" -t istio/examples-bookinfo-reviews-v3:latest --build-arg service_version=v3 \--build-arg enable_ratings=true --build-arg star_color=red .
- 
V1:沒有評星(未指定 enable_ratings=true)。
 - 
V2:評星為黑色(指定 enableratings=true;未指定 starcolor 的變數,程式碼中預設的顏色為黑色)。
 - 
V3:評星為紅色(指定 enableratings=true;指定 starcolor 的變數為 red)。
 
#!/bin/shset -emongoimport --host localhost --db test --collection ratings --drop --file /app/data/ratings_data.json
{rating: 5}{rating: 4}
# Initialize a mysql db with a 'test' db and be able test productpage with it.# mysql -h 127.0.0.1 -ppassword < mysqldb-init.sqlCREATE DATABASE test;USE test;CREATE TABLE `ratings` (`ReviewID` INT NOT NULL,`Rating` INT,PRIMARY KEY (`ReviewID`));INSERT INTO ratings (ReviewID, Rating) VALUES (1, 5);INSERT INTO ratings (ReviewID, Rating) VALUES (2, 4);
| ReviewID | Rating | 
| 1 | 5 | 
| 2 | 4 | 
* We default to using mongodb, if DB_TYPE is not set to mysql.*/if (process.env.SERVICE_VERSION === 'v2') {if (process.env.DB_TYPE === 'mysql') {var mysql = require('mysql')var hostName = process.env.MYSQL_DB_HOSTvar portNumber = process.env.MYSQL_DB_PORTvar username = process.env.MYSQL_DB_USERvar password = process.env.MYSQL_DB_PASSWORD} else {var MongoClient = require('mongodb').MongoClientvar url = process.env.MONGO_DB_URL}}dispatcher.onGet(/^\/ratings\/[0-9]*/, function (req, res) {var productIdStr = req.url.split('/').pop()var productId = parseInt(productIdStr)if (Number.isNaN(productId)) {res.writeHead(400, {'Content-type': 'application/json'})res.end(JSON.stringify({error: 'please provide numeric product ID'}))} else if (process.env.SERVICE_VERSION === 'v2') {var firstRating = 0var secondRating = 0if (process.env.DB_TYPE === 'mysql') {var connection = mysql.createConnection({host: hostName,port: portNumber,user: username,password: password,database: 'test'})connection.connect()connection.query('SELECT Rating FROM ratings', function (err, results, fields) {if (err) {res.writeHead(500, {'Content-type': 'application/json'})res.end(JSON.stringify({error: 'could not connect to ratings database'}))} else {if (results[0]) {firstRating = results[0].Rating}if (results[1]) {secondRating = results[1].Rating}var result = {id: productId,ratings: {Reviewer1: firstRating,Reviewer2: secondRating}}res.writeHead(200, {'Content-type': 'application/json'})res.end(JSON.stringify(result))}})


- 
第一種:訪問 bookinfo 時(Productpage 呼叫的 Review V1),頁面沒有評星;
 - 
第二種:訪問 bookinfo 時(Productpage 呼叫的 Review V2),頁面是黑色的評星;
 - 
第三種:訪問 bookinfo 時(Productpage 呼叫的 Review V3),頁面是紅色的評星。
 






[root@master networking]# cat virtual-service-reviews-v3.yamlapiVersion: networking.istio.io/v1alpha3kind: VirtualServicemetadata:name: reviewsspec:hosts:- reviewshttp:- route:- destination:host: reviewssubset: v3 version: v3




[root@master networking]# cat virtual-service-reviews-80-20.yamlapiVersion: networking.istio.io/v1alpha3kind: VirtualServicemetadata:name: reviewsspec:hosts:- reviewshttp:- route:- destination:host: reviewssubset: v1weight: 80- destination:host: reviewssubset: v2weight: 20


[root@master ~]# cat speedrule.yamlapiVersion: "config.istio.io/v1alpha2"kind: memquotametadata:name: handlernamespace: myprojectspec:quotas:- name: requestcount.quota.myproject# default rate limit is 5000qpsmaxAmount: 5000validDuration: 1s# The first matching override is applied.# A requestcount instance is checked against override dimensions.overrides:- dimensions:destination: reviewssource: productpagedestinationVersion: v3maxAmount: 1validDuration: 1srecommendation_rate_limit_handler.yml 檔案宣告了 requestcount quota。
[root@master ~]# cat recommendation_rate_limit_handler.ymlapiVersion: "config.istio.io/v1alpha2"kind: quotametadata:name: requestcountnamespace: myprojectspec:dimensions:source: source.labels["app"] | source.service | "unknown"sourceVersion: source.labels["version"] | "unknown"destination: destination.labels["app"] | destination.service | "unknown"destinationVersion: destination.labels["version"] | "unknown"---apiVersion: "config.istio.io/v1alpha2"kind: rulemetadata:name: quotanamespace: myprojectspec:actions:- handler: handler.memquotainstances:- requestcount.quota---apiVersion: config.istio.io/v1alpha2kind: QuotaSpecmetadata:creationTimestamp: nullname: request-countnamespace: myprojectspec:rules:- quotas:- charge: 1quota: RequestCount---apiVersion: config.istio.io/v1alpha2kind: QuotaSpecBindingmetadata:creationTimestamp: nullname: request-countnamespace: myprojectspec:quotaSpecs:- name: request-countnamespace: myprojectservices:- name: productpagenamespace: myproject- name: detailsnamespace: myproject- name: reviewsnamespace: myproject


while true; do curl http://istio-ingressgateway-istio-system.apps.example.com/productpage; sleep .1; done



spec:host: productpagesubsets:- labels:version: v1name: v1trafficPolicy:connectionPool:http:http1MaxPendingRequests: 1maxRequestsPerConnection: 1tcp:maxConnections: 1tls:mode: ISTIO_MUTUAL



[root@master ~]# cat acl-blacklist.ymlapiVersion: "config.istio.io/v1alpha2"kind: deniermetadata:name: denycustomerhandlerspec:status:code: 7message: Not allowed---apiVersion: "config.istio.io/v1alpha2"kind: checknothingmetadata:name: denycustomerrequestsspec:---apiVersion: "config.istio.io/v1alpha2"kind: rulemetadata:name: denycustomerspec:match: destination.labels["app"] == "details" && source.labels["app"]=="productpage"actions:- handler: denycustomerhandler.denierinstances: [ denycustomerrequests.checknothing ]









知識星球
