README.md 53.5 KB
Newer Older
1
# SpringCloud2020学习笔记
L
lcry 已提交
2

3
## 技术选型
L
lcry 已提交
4

5 6 7 8 9
| 依赖                | 版本          |
| ------------------- | ------------- |
| SpringCloud         | Hoxton.SR1    |
| SpringBoot          | 2.2.2.RELEASE |
| SpringCloud Alibaba | 2.1.0.RELEASE |
L
lcry 已提交
10 11 12



13
## 工具汇总
L
lcry 已提交
14

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| 名称          | 版本     | 备注                 | 下载地址                                                     |
| ------------- | -------- | -------------------- | ------------------------------------------------------------ |
| Java          | 8        |                      | [官网下载](https://www.oracle.com/java/technologies/javase-jdk8-downloads.html) |
| Maven         | 3.5+     |                      | [官网下载](http://maven.apache.org/download.cgi)             |
| MySQL         | 5.7+     |                      | [官网下载](https://dev.mysql.com/downloads/mysql/5.7.html)   |
| IntelliJ IDEA | 2019.3.3 |                      | [官网下载](https://www.jetbrains.com/idea/download/)         |
| zookeeper     | 3.4.14   |                      | [官网下载](https://zookeeper.apache.org/releases.html)       |
| nacos-server  | 1.2.0    | nacos服务端          | [Github下载](https://github.com/alibaba/nacos/releases/tag/1.2.0) |
| consul-server | 1.7.2    | consul服务端         | [官网下载](https://www.consul.io/downloads.html)             |
| zipkin-server | 2.12.9   | zipkin链路监控服务端 | [第三方下载](https://dl.bintray.com/openzipkin/maven/io/zipkin/java/zipkin-server/) |
| postman       | 7.20.1   | 接口请求测试         | [官网下载](https://www.postman.com/downloads/)               |
| Seata         | 0.9.0    | 分布式事务服务端     | [官网下载](https://seata.io/zh-cn/blog/download.html)        |

> 项目中使用的数据库文件在项目根目录resouces/SQL/下,阶段代码直接查看提交记录
>
> 配套视频:https://www.bilibili.com/video/av93813318

## 项目结构说明
L
lcry 已提交
33

34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| 项目名                                  | 用途                                            | 所用技术                                                     |
| --------------------------------------- | :---------------------------------------------- | ------------------------------------------------------------ |
| cloud-api-commons                       | 公共代码部分(返回结果集、实体等)              | \                                                            |
| cloud-consumer-consul-order80           | 消费方通过Consul调用服务方                      | 注册中心(Consul)、远程调用(RestTemplate)                 |
| cloud-consumer-feign-order80            | 消费方通过feign远程调用服务方                   | 服务调用(Openfeign)、注册中心(EurekaClient)              |
| cloud-consumer-order80                  | 消费方通过Eureka调用服务方等示例                | 注册中心(Eureka)、远程调用(RestTemplate)、链路追踪(Sleuth) |
| cloud-consumer-zk-order80               | 消费方通过Zk调用服务方                          | 注册中心(Zk)、远程调用(RestTemplate)                     |
| cloud-eureka-server7001                 | Eureka服务端1                                   | 注册中心(EurekaServer)                                     |
| cloud-eureka-server7002                 | Eureka服务端2                                   | 注册中心(EurekaServer)                                     |
| cloud-provider-consul-payment8006       | 服务方通过Consul注册服务                        | 注册中心(Consul)                                           |
| cloud-provider-payment8001              | 服务方通过Eureka注册服务                        | 注册中心(Euraka)、链路追踪(Sleuth)                       |
| cloud-provider-payment8002              | 服务方通过Eureka注册服务                        | 注册中心(Euraka)                                           |
| cloud-provider-zk-payment8004           | 服务方通过Zk注册服务                            | 注册中心(Zk)                                               |
| cloud-provider-hystrix-payment8001      | 服务方通过Hystrix服务降级和熔断                 | 服务降级和熔断(Hystrix)、服务监控(Actuator)              |
| cloud-consumer-feign-hystrix-order80    | 消费方消费方通过feign远程调用服务方带降级和服务 | 服务降级和熔断(Hystrix)、服务调用(Openfeign)             |
| cloud-consumer-hystrix-dashboard9001    | Hystrix监控仪表盘                               | 服务监控(Hystrix)                                          |
| cloud-gateway-gateway9527               | 网关服务GateWay                                 | 网关(GateWay)                                              |
| cloud-config-center-3344                | 配置中心服务端                                  | 配置中心(Config-Server)、服务总线(BUS)                   |
| cloud-config-client-3355                | 配置中心客户端1                                 | 配置中心(Config)、服务总线(BUS)                          |
| cloud-config-client-3356                | 配置中心客户端1                                 | 配置中心(Config)、服务总线(BUS)                          |
| cloud-stream-provider-rabbitmq8801      | 消息驱动发送方                                  | 消息驱动(Stream)                                           |
| cloud-stream-provider-rabbitmq8802      | 消息驱动接受方1                                 | 消息驱动(Stream)                                           |
| cloud-stream-consumer-rabbitmq8803      | 消息驱动接受方2                                 | 消息驱动(Stream)                                           |
| cloudalibaba-config-nacos-client3377    | 配置中心客户端Nacos                             | 配置中心(Nacos)、服务注册(Nacos)                         |
58 59 60 61 62 63
| cloudalibaba-provider-nacos-payment9001 | 服务方通过Nacos注册服务1                        | 服务注册(Nacos)                                            |
| cloudalibaba-provider-nacos-payment9002 | 服务方通过Nacos注册服务2                        | 服务注册(Nacos)                                            |
| cloudalibaba-provider-nacos-payment9003 | 服务方通过Nacos注册服务模拟查询1                | 服务注册(Nacos)                                            |
| cloudalibaba-provider-nacos-payment9004 | 服务方通过Nacos注册服务模拟查询2                | 服务注册(Nacos)                                            |
| cloudalibaba-sentinel-service8401       | 服务限流和熔断Sentinel示例                      | 服务注册(Nacos)、服务限流和熔断(Sentinel)                |
| cloudalibaba-consumer-nacos-order84     | 消费方通过整合Feign和Sentinel                   | 服务注册(Nacos)、服务限流和熔断(Sentinel)、服务调用(Openfeign)、负载均衡(Rabbin) |
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727
| cloudalibaba-seata-order-service12001   | 分布式事务商品下单微服务                        | 分布式事务(Seata)、服务注册(Nacos)、服务调用(Openfeign)、负载均衡(Rabbin) |
| cloudalibaba-seata-storage-service12002 | 分布式事务库存微服务                            | 分布式事务(Seata)、服务注册(Nacos)、服务调用(Openfeign)、负载均衡(Rabbin) |
| cloudalibaba-seata-account-service12003 | 分布式事务账户微服务                            | 分布式事务(Seata)、服务注册(Nacos)、服务调用(Openfeign)、负载均衡(Rabbin) |



## 知识点整理

### 一、服务注册与发现

#### 1、使用Eureka服务端

1)导入依赖

```xml
        <!--eureka-server-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
        <!--热部署推荐一起-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
```

2)application.yml示例

```yaml
server:
  port: 7001

eureka:
  instance:
    hostname: eureka7001.com #Eureka服务端的实例名称
  client:
    #false表示不向注册中心中注册自己
    register-with-eureka: false
    #false表示自己就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
    fetch-registry: false
    service-url:
      #设置与Eureka Server之间交互的地址,查询服务和注册服务都需要依赖这个地址
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #单机版,指向自己
      #defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka #集群版
  server:
    #关闭Eureka自我保护机制,保证不可用服务被及时剔除
    enable-self-preservation: false
    eviction-interval-timer-in-ms: 2000
```

3)启动类添加注解@EnableEurekaServer

```java
@SpringBootApplication
@EnableEurekaServer
public class EurekaMain7001 {
    public static void main(String[] args) {
        SpringApplication.run(EurekaMain7001.class, args);
    }
}
```

4)验证

访问:http://localhost:7001

> 对应项目:cloud-eureka-server7001、cloud-eureka-server7002



#### 2、使用Eureka客户端

1)导入依赖  

```xml        &lt;!--引入eureka客户端eureka-client --&gt;
        <!--引入eureka客户端eureka-client -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
```

2)application.yml示例

```yaml
server:
  port: 8001

spring:
  application:
    name: cloud-payment-service
    
eureka:
  client:
    #表示是否将自己注册进EurekaServer,默认为true
    register-with-eureka: true
    #是否从EurekaServer中抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
    fetchRegistry: true
    service-url:
      defaultZone: http://localhost:7001/eureka #单机版
      #defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka #集群版
  instance:
    instance-id: payment8001 #修改Status名称
    prefer-ip-address: true
    #Eureka客户端向服务端发送心跳的时间间隔,单位为秒(默认30)
    lease-renewal-interval-in-seconds: 10
    #Eureka服务端在收到最后一次心跳后等待的时间上限,单位为秒(默认90),超时剔除服务
    lease-expiration-duration-in-seconds: 60
```

3)启动类添加注解@EnableDiscoveryClient(推荐)或者@EnableEurekaClient

```java
@SpringBootApplication
@EnableDiscoveryClient //Discovery服务发现
public class PaymentMain8001 {
    public static void main(String[] args) {
        SpringApplication.run(PaymentMain8001.class, args);
    }
}
```

> 对应项目:cloud-provider-payment8001、cloud-provider-payment8002等



#### 3、使用Zookeeper注册服务

1)导入依赖

```xml
        <!-- SpringBoot整合zookeeper客户端 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
            <!-- 先排除自带的zookeeper -->
            <exclusions>
                <exclusion>
                    <groupId>org.apache.zookeeper</groupId>
                    <artifactId>zookeeper</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!-- 添加本机zookeeper3.4.14版本 -->
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.14</version>
        </dependency>
```

2)application.yml示例

```yaml
server:
  port: 8004

#服务别名——注册到zookeeper注册中心的名称
spring:
  application:
    name: cloud-provider-payment
  cloud:
    zookeeper:
      connect-string: 127.0.0.1:2181
```

3)启动类添加注解@EnableDiscoveryClient

```java
@SpringBootApplication
@EnableDiscoveryClient  //该注解用于向使用zookeeper作为注册中心时注册服务
public class ZkPaymentMain8004 {
    public static void main(String[] args) {
        SpringApplication.run(ZkPaymentMain8004.class, args);
    }
}
```

>  对应项目:cloud-provider-zk-payment8004



#### 4、使用Consul注册服务

1)导入依赖

```xml
    <!--    consul软件官方下载:https://www.consul.io/downloads.html
    开发模式启动:consul agent -dev
    验证:浏览器访问 http://localhost:8500
    若提示:
Consul returned an error. You may have visited a URL that is loading an unknown resource,so you can try going back to the root or try re-submitting your ACL Token/SecretID by going back to ACLs.
    错误请使用其他浏览器访问试试
    -->
    <!--consul版服务提供方-->

		<!--SpringCloud consul-server -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>
```

2)application.yml示例

```yaml
server:
  port: 8006

spring:
  application:
    name: consul-provider-payment
  #consul注册中心地址
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        #hostname: 127.0.0.1
        service-name: ${spring.application.name}
```

3)启动类添加注解@EnableDiscoveryClient

```java
@SpringBootApplication
@EnableDiscoveryClient
public class ConsulPaymentMain8006 {
    public static void main(String[] args) {
        SpringApplication.run(ConsulPaymentMain8006.class, args);
    }
}
```

> 对应项目:cloud-provider-consul-payment8006



### 二、负载均衡调用

#### 1、使用Ribbon负载均衡

默认eureka集成了rabbin,配置即可使用,默认是轮训策略。

1)新建规则类MySelfRule.java

```java
/**
 * MySelfRule
 *
 * @author lcry
 * 自定义Ribbon默认轮训规则类
 */
@Configuration
public class MySelfRule {
    @Bean
    public IRule myRule() {
        return new RandomRule();//定义为随机
    }
}
```

> IRule实现类有如下:
>
> com.netflix.loadbalancer.RoundRobinRule:轮询
>
> com.netflix.loadbalancer.RandomRule:随机
>
> com.netflix.loadbalancer.RetryRule:先按照RoundRobinRule的策略获取服务,如果获取服务失败则在指定时间内进行重试,获取可用的服务
>
> WeightedResponseTimeRule:对RoundRobinRule的扩展,响应速度越快的实例选择权重越多大,越容易被选择
>
> BestAvailableRule:会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务
>
> AvailabilityFilteringRule:先过滤掉故障实例,再选择并发较小的实例
>
> ZoneAvoidanceRule:默认规则,复合判断server所在区域的性能和server的可用性选择服务器

2)启动类添加注解`@RibbonClient(name = "CLOUD-PAYMENT-SERVICE", configuration = MySelfRule.class)//启用Ribbon`

```java
@SpringBootApplication
@EnableDiscoveryClient
@RibbonClient(name = "CLOUD-PAYMENT-SERVICE", configuration = MySelfRule.class)//启用Ribbon
public class OrderMain80 {
    public static void main(String[] args) {
        SpringApplication.run(OrderMain80.class, args);
    }
}
```

若使用restTemplate直接使用轮训规则,可以直接在配置类上@LoadBalanced注解

```java
/**
 * ApplicationContextConfig
 *
 * @author lcry
 * @date 2020/03/14 12:05
 * 配置RestTemplate
 */
@Configuration
public class ApplicationContextConfig {
    @Bean //相当于Spring中applicationContext.xml中<bean id="" class="">
    @LoadBalanced //使用此注解赋予RestTemplate负载均衡的能力,测试自定义算法注释掉
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }
}
```

> 对应项目:cloud-consumer-order80



#### 2、使用OpenFeign

1)导入依赖

```xml
        <!-- openfeign -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
```

2)application.yml示例

```yaml
server:
  port: 80

eureka:
  client:
    register-with-eureka: false
    service-url:
      defaultZone: http://localhost:7001/eureka #单机版
      #defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka #集群版

#OpenFeign的超时控制配置:默认只等待1秒,超时则报错
#设置Feign客户端超时时间(OpenFeign默认支持Ribbon)
ribbon:
  #指的是建立连接所用的时间,适用于网络状况正常的情况下,两端连接所用的时间
  ReadTimeout: 5000
  #指的是建立连接后从服务器读取到可用资源所用的时间
  connectTimeout: 5000

#开启Feign的日志客户端
logging:
  level:
    #Feign日志以什么级别监听哪个接口
    com.lcry.springcloud.service.PaymentFeignService: debug
```

3)启动类添加注解@EnableFeignClients

```java
@SpringBootApplication
//启用Feign
@EnableFeignClients
public class FeignOrderMain80 {
    public static void main(String[] args) {
        SpringApplication.run(FeignOrderMain80.class, args);
    }
}
```

4)配置日志打印信息 FeignConfig.java

```java
/**
 * FeignConfig
 *
 * @author lcry
 * @date 2020/03/14 22:04
 * Feign日志控制
 */
@Configuration
public class FeignConfig {
    @Bean
    Logger.Level feignLoggerLevel() {
        /**
         * 日志级别:
         * NONE :不记录任何日志(默认)
         * BASIC:仅记录请求方法、URL、响应状态代码以及执行时间
         * HEADERS:记录BASIC级别的基础上,记录请求和响应的header
         * FULL:记录请求和响应的header,body和元数据
         */
        return Logger.Level.FULL;
    }
}
```

5)远程调用服务

```java
/**
 * PaymentFeignService
 *
 * @author lcry
 */
@Component
@FeignClient(value = "CLOUD-PAYMENT-SERVICE") //需要调用的目标微服务应用名称
public interface PaymentFeignService {
    //Feign接口中的方法要与目标服务中的Controller中的方法完全一致,可以直接copy
    @GetMapping(value = "/payment/get/{id}")
    public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id);

    @GetMapping(value = "/payment/feign/timeout")
    public String paymentFeignTimeout();
}

```

> 对应项目:cloud-consumer-feign-order80



### 三、服务熔断与降级

#### 1、使用HyStrix熔断和降级

1)导入依赖

```xml
        <!--hystrix-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
```

2)application.yml示例

```yaml
server:
  port: 8001

spring:
  application:
    name: cloud-provider-hystrix-payment

eureka:
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://127.0.0.1:7001/eureka
      #defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
```

3)启动类添加注解@EnableHystrix

```java
@SpringBootApplication
@EnableEurekaClient
@EnableHystrix  //服务端开启Hystrix或者使用@EnableCircuitBreaker
public class HystrixPaymentMain8001 {
    public static void main(String[] args) {
        SpringApplication.run(HystrixPaymentMain8001.class, args);
    }
}
```

4)服务降级示例代码,@HystrixCommand注解实现

```java
/**
     * 模拟超时3s
     *
     * @param id
     * @return
     */
    @Override
    @HystrixCommand(fallbackMethod = "paymentInfo_TimeOutHandler", commandProperties = {
            //超时5s或者异常直接降级
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000")
    })
    public String paymentInfo_TimeOut(Integer id) {
        //int age = 10/0;
        int timenum = 3;
        try {
            TimeUnit.SECONDS.sleep(timenum);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "线程池:  " + Thread.currentThread().getName() + " id:  " + id + "\t" + "O(∩_∩)O哈哈~" + "  耗时(秒): " + timenum;
    }

    public String paymentInfo_TimeOutHandler(Integer id) {
        return "线程池:  " + Thread.currentThread().getName() + "  8001系统繁忙或者运行报错,请稍后再试,id:  " + id + "\t" + "o(╥﹏╥)o";
    }
```

5)服务熔断示例代码

```java
    /**
     * 以下内容属于服务熔断
     *
     * @param id
     * @return
     */
    @Override
    @HystrixCommand(fallbackMethod = "paymentCircuitBreaker_fallback", commandProperties = {
            @HystrixProperty(name = "circuitBreaker.enabled", value = "true"),// 是否开启断路器
            @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),// 请求次数
            @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"), // 时间窗口期
            @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60"),// 失败率达到多少后跳闸
    })
    public String paymentCircuitBreaker(@PathVariable("id") Integer id) {
        if (id < 0) {
            throw new RuntimeException("id 不能负数");
        }
        String serialNumber = IdUtil.simpleUUID();

        return Thread.currentThread().getName() + "\t" + "调用成功,流水号: " + serialNumber;
    }

    public String paymentCircuitBreaker_fallback(@PathVariable("id") Integer id) {
        return "id 不能负数,请稍后再试,/(ㄒoㄒ)/~~   id: " + id;
    }
```

> 对应项目:cloud-provider-hystrix-payment8001、cloud-consumer-feign-order80



#### 2、使用HystrixDashboard监控仪表盘

1)导入依赖

```xml
    <!--  hystrix服务监控平台dashboard  -->
    <!-- 被监控服务一定要引入web和actuator两个依赖   -->
    <!--
    监控地址:http://ip:端口/hystrix
    被监控填写:http://ip:端口/hystrix.stream

    -->
 <!--     hystrix-dashboard   -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
```

2)application.yml示例

```yaml
server:
  port: 9001
```

3)启动类添加注解@EnableHystrixDashboard

```java
/**
 * HystrixDashboardMain9001
 *
 * @author lcry
 */
@SpringBootApplication
@EnableHystrixDashboard  //启用注解
public class HystrixDashboardMain9001 {
    public static void main(String[] args) {
        SpringApplication.run(HystrixDashboardMain9001.class, args);
    }
}
```

4)被监控端配置

- 引入依赖

  ```xml
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-web</artifactId>
          </dependency>
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-actuator</artifactId>
          </dependency>
  ```

- 启动类注入

  ```java
      /**
       * 此配置是为了服务监控而配置,与服务容错本身无关,springcloud升级后的坑
       * ServletRegistrationBean因为springboot的默认路径不是"/hystrix.stream",
       * 只要在自己的项目里配置上下面的servlet就可以了
       */
      @Bean
      public ServletRegistrationBean getServlet() {
          HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
          ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
          registrationBean.setLoadOnStartup(1);
          registrationBean.addUrlMappings("/hystrix.stream");
          registrationBean.setName("HystrixMetricsStreamServlet");
          return registrationBean;
      }
  ```

5)验证

访问hystrix服务监控平台http://localhost:9001,被监控填写:http:// ip:端口/hystrix.stream

> 对应项目:cloud-consumer-hystrix-dashboard9001、cloud-provider-hystrix-payment8001



### 四、路由网关

#### 1、使用Zuul

忽略,直接使用Gateway新一代网关

#### 2、使用SpringCloud Gateway

1)导入依赖

```xml
        <!--gateway-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <!--eureka-client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--引入自己定义的api调用包,可以使用Payment支付Entity-->
        <dependency>
            <groupId>com.lcry</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
```

2)通过application.yml配置路由网关示例(推荐)

```java
server:
  port: 9527

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true #开启从注册中心动态创建路由的功能利用微服务名进行路由
      routes:
        - id: payment_route #payment_route    #路由的ID没有固定规则但要求唯一建议配合服务名
          #uri: http://localhost:8001          #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service #匹配后提供服务的路由地址
          predicates:
            - Path=/payment/get/**         # 断言路径相匹配的进行路由

        - id: payment_route2 #payment_route    #路由的ID没有固定规则但要求唯一建议配合服务名
          #uri: http://localhost:8001          #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service #匹配后提供服务的路由地址
          predicates:
            - Path=/payment/lb/**         # 断言路径相匹配的进行路由
            #- After=2020-02-21T15:51:37.485+08:00[Asia/Shanghai]
            #- Cookie=username,zzyy
            #- Header=X-Request-Id, \d+  # 请求头要有X-Request-Id属性并且值为整数的正则表达式

eureka:
  instance:
    hostname: cloud-gateway-service
  client: #服务提供者provider注册进eureka服务列表内
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://localhost:7001/eureka
```

3)通过编码方式实现路由网关

```java
/**
 * 通过编码方式实现路由
 */
@Configuration
public class GateWayConfig {
    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder) {
        RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();

        routes.route("path_route_baidunews",
                r -> r.path("/guonei")
                        .uri("http://news.baidu.com/guonei")).build();

        return routes.build();
    }
}
```

4)自定义过滤逻辑示例 MyLogGateWayFilter.java

```java
/**
 * 自定义过滤器示例-一般用于鉴权或者全局日志
 */
@Component
@Slf4j
public class MyLogGateWayFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("***********come in MyLogGateWayFilter:  " + new Date());

        //请求参数必须带username,并且不能为空
        String uname = exchange.getRequest().getQueryParams().getFirst("username");

        if (StrUtil.isEmpty(uname)) {
            log.info("*******用户名为空,非法用户,o(╥﹏╥)o");
            exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
            return exchange.getResponse().setComplete();
        }

        return chain.filter(exchange);  //放行给下一条过滤链
    }

    @Override
    public int getOrder() {
        //执行顺序,越小越先执行
        return 0;
    }
}
```

> 对应项目:cloud-gateway-gateway9527





### 五、分布式配置中心

#### 1、使用SpringCloud Config服务端

1)导入依赖

```xml
        <!-- config-server依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
        </dependency>
```

2)application.yml示例

```yaml
server:
  port: 3344

spring:
  application:
    name:  cloud-config-center #注册进Eureka服务器的微服务名
  cloud:
    config:
      server:
        git:
          uri: git@gitee.com:lcry/springcloud-config.git #git仓库地址
          ####搜索目录
          search-paths:
            - springcloud-config
      ####读取分支
      label: master
#服务注册到eureka地址
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka
```

3)启动类添加注解@EnableConfigServer

```java
@SpringBootApplication
@EnableConfigServer  //启用注册中心服务端
public class ConfigCenterMain3344 {
    public static void main(String[] args) {
        SpringApplication.run(ConfigCenterMain3344.class, args);
    }
}
```

> 对应项目:cloud-config-center-3344



#### 2、使用SpringCloud Config客户端

1)导入依赖

```xml
        <!--        spring-config客户端依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
```

2)application.yml示例

```yaml
server:
  port: 3355

spring:
  application:
    name: config-client
  cloud:
    #Config客户端配置
    config:
      label: master #分支名称
      name: config #配置文件名称
      profile: dev #读取后缀名称   上述3个综合:master分支上config-dev.yml的配置文件被读取http://config-3344.com:3344/master/config-dev.yml
      uri: http://localhost:3344 #配置中心地址server:
  port: 3355

spring:
  application:
    name: config-client
  cloud:
    #Config客户端配置
    config:
      label: master #分支名称
      name: config #配置文件名称
      profile: dev #读取后缀名称   上述3个综合:master分支上config-dev.yml的配置文件被读取http://config-3344.com:3344/master/config-dev.yml
      uri: http://localhost:3344 #配置中心地址
```

> 对应项目:cloud-config-client-3355、cloud-config-client-3356



### 六、消息总线

#### 1、使用SpringCloud Bus刷新配置

1)导入依赖

```xml
        <!--添加消息总线RabbitMQ支持-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bus-amqp</artifactId>
        </dependency>
```

2)SpringCloud Config服务端application.yml示例

```yaml
#rabbitmq相关配置
  rabbitmq:
    host: 192.168.179.150
    port: 5672
    username: admin
    password: admin

#全局刷新POST请求 http://注册中心地址/actuator/bus-refresh
#定点通知:(只通知部分)http://注册中心地址/actuator/refresh/{服务名称:端口}
#如:http://localhost:3344/actuator/bus-refresh/config-client:3355
##rabbitmq相关配置,暴露bus刷新配置的端点
management:
  endpoints: #暴露bus刷新配置的端点
    web:
      exposure:
        include: 'bus-refresh'
```

3)SpringCloud Config客户端application.yml示例

```yaml
#rabbitmq相关配置 15672是Web管理界面的端口;5672是MQ访问的端口
  rabbitmq:
    host: 192.168.179.150
    port: 5672
    username: admin
    password: admin

#  手动刷新地址POST http://客户端访问地址/actuator/refresh
# curl -X POST "http://localhost:3355/actuator/refresh"
# 暴露监控端点
management:
  endpoints:
    web:
      exposure:
        include: "*"
```

4)刷新配置注解@RefreshScope 

```java
@RestController
@RefreshScope //刷新配置生效
public class ConfigClientController {

    @Value("${server.port}")
    private String serverport;

    @Value("${config.info}")
    private String configInfo;

    //    直接获取配置文件
    @GetMapping("/configInfo")
    public String getConfigInfo() {
        return configInfo + "服务端口:"+serverport;
    }

}
```

> 对应项目:cloud-config-center-3344、cloud-config-center-3355、cloud-config-center-3356



### 七、消息驱动

#### 1、使用Stream发送方

1)导入依赖

```xml
        <!--        引入stream-rabbit-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
        </dependency>
```

2)application.yml示例

```yaml
server:
  port: 8801

spring:
  application:
    name: cloud-stream-provider
  cloud:
      stream:
        binders: # 在此处配置要绑定的rabbitmq的服务信息;
          defaultRabbit: # 表示定义的名称,用于于binding整合
            type: rabbit # 消息组件类型
            environment: # 设置rabbitmq的相关的环境配置
              spring:
                rabbitmq:
                  host: 192.168.179.150
                  port: 5672
                  username: admin
                  password: admin
        bindings: # 服务的整合处理
          output: # 这个名字是一个通道的名称
            destination: studyExchange # 表示要使用的Exchange名称定义
            content-type: application/json # 设置消息类型,本次为json,文本则设置“text/plain”
            binder: defaultRabbit # 设置要绑定的消息服务的具体设置

eureka:
  client: # 客户端进行Eureka注册的配置
    service-url:
      defaultZone: http://localhost:7001/eureka
  instance:
    lease-renewal-interval-in-seconds: 2 # 设置心跳的时间间隔(默认是30秒)
    lease-expiration-duration-in-seconds: 5 # 如果现在超过了5秒的间隔(默认是90秒)
    instance-id: cloud-stream-provider8801  # 在信息列表时显示主机名称
    prefer-ip-address: true     # 访问的路径变为IP地址
```

3)定义推送管道

```java
/**
 * //定义消息的推送管道
 */
@EnableBinding(Source.class) //定义消息的推送管道,生产者固定写法
@Slf4j
public class MessageProviderImpl implements IMessageProvider {
    @Resource
    private MessageChannel output; // 消息发送管道

    @Override
    public String send() {
        String serial = UUID.randomUUID().toString();
        output.send(MessageBuilder.withPayload(serial).build());
        log.info(String.format("生成的流水号:{%s}", serial));
        return serial;
    }
}
```

> 对应项目:cloud-stream-provider-rabbitmq8801



#### 2、使用Stream接受方

1)导入依赖

```xml
        <!--      stream-rabbit  -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
        </dependency>
```

2)application.yml示例

```yaml
server:
  port: 8802

spring:
  application:
    name: cloud-stream-consumer
  cloud:
      stream:
        binders: # 在此处配置要绑定的rabbitmq的服务信息;
          defaultRabbit: # 表示定义的名称,用于于binding整合
            type: rabbit # 消息组件类型
            environment: # 设置rabbitmq的相关的环境配置
              spring:
                rabbitmq:
                  host: 192.168.179.150
                  port: 5672
                  username: admin
                  password: admin
        bindings: # 服务的整合处理
          input: # 这个名字是一个通道的名称
            destination: studyExchange # 表示要使用的Exchange名称定义
            content-type: application/json # 设置消息类型,本次为对象json,如果是文本则设置“text/plain”
            binder: defaultRabbit # 设置要绑定的消息服务的具体设置
            group: receiveclientA  #分组避免重复消费和持久化问题

eureka:
  client: # 客户端进行Eureka注册的配置
    service-url:
      defaultZone: http://localhost:7001/eureka
  instance:
    lease-renewal-interval-in-seconds: 2 # 设置心跳的时间间隔(默认是30秒)
    lease-expiration-duration-in-seconds: 5 # 如果现在超过了5秒的间隔(默认是90秒)
    instance-id: cloud-stream-consumer8802  # 在信息列表时显示主机名称
    prefer-ip-address: true     # 访问的路径变为IP地址
```

3)接收消息逻辑代码

```java
@Component
@EnableBinding(Sink.class)
public class ReceiveMessageListenerController {
    @Value("${server.port}")
    private String serverPort;


    @StreamListener(Sink.INPUT)  //固定的写法,对应yml配置的通道名称
    public void input(Message<String> message) {
        System.out.println("消费者1号,----->接受到的消息: " + message.getPayload() + "\t  port: " + serverPort);
    }
}
```

> 对应项目:cloud-stream-consumer-rabbitmq8802、cloud-stream-consumer-rabbitmq8802



### 八、分布式链路追踪

#### 1、使用sleuth客户端

1)导入依赖

```xml
        <!--链路监控包含了sleuth+zipkin-->
        <!--服务端下载地址:https://dl.bintray.com/openzipkin/maven/io/zipkin/java/zipkin-server/-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>
        </dependency>
        <!--引入eureka客户端eureka-client -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
```

2)application.yml示例

```yaml
spring:
  application:
    name: cloud-payment-service
  #链路监控配置,配置链路监控服务端地址
  zipkin:
    base-url: http://localhost:9411
  sleuth:
    sampler:
    #采样率值介于 0 到 1 之间,1 则表示全部采集
    probability: 1
```

> 对应项目:cloud-provider-payment8001、cloud-consumer-order80



### 九、SpringCloud alibaba

#### 1、使用Nacos服务注册

1)导入依赖

```xml
        <!--SpringCloud ailibaba nacos -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
```

2)application.yml示例

```yaml
server:
  port: 9001

spring:
  application:
    name: nacos-payment-provider
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #配置Nacos地址,注册服务到Nacos

management:
  endpoints:
    web:
      exposure:
        include: '*'
```

3)启动类添加注解@EnableDiscoveryClient

```java
/**
 * NacosPaymentMain9001
 *
 * @author lcry
 * @date 2020/03/16 18:03
 */
@EnableDiscoveryClient
@SpringBootApplication
public class NacosPaymentMain9001 {
    public static void main(String[] args) {
        SpringApplication.run(NacosPaymentMain9001.class,args);
    }

}
```

> 对应项目:cloudalibaba-provider-nacos-payment9001、cloudalibaba-provider-nacos-payment9002



#### 2、使用Nacos注册中心

1)导入依赖

```xml
<!--    nacos服务直接到官网下载以jar运行即可-->
		<!--nacos-config-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
        <!--nacos-discovery-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--web + actuator-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
```

2)application.yml示例

```yaml
#激活配置文件选项
spring:
  profiles:
    active: dev # 表示开发环境
    #active: test # 表示测试环境
    #active: prod # 表示生产环境

# nacos配置
server:
  port: 3377

spring:
  application:
    name: nacos-config-client
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #Nacos服务注册中心地址
      config:
        server-addr: localhost:8848 #Nacos作为配置中心地址
        namespace: Test-NameSpace-HA1   #命名空间ID,nacos1.2可以自定义
        group: DEV_GROUP   #分组ID
        file-extension: yaml #指定yaml格式的配置
#
#命名规范:
# ${spring.application.name}-${spring.profile.active}.${spring.cloud.nacos.config.file-extension}
# nacos-config-client-dev.yaml
```

3)启动类添加注解@EnableDiscoveryClient

```java
/**
 * ConfigNacosMain3344
 *
 * @author lcry
 * @date 2020/03/16 17:49
 */
@SpringBootApplication
@EnableDiscoveryClient
public class ConfigNacosMain3377 {
    public static void main(String[] args) {
        SpringApplication.run(ConfigNacosMain3377.class, args);
    }
}
```

4)业务类添加注解@RefreshScope

```java
/**
 * NacosClientController
 *
 * @author lcry
 */
@RestController
@RefreshScope //支持Nacos的动态刷新功能。
public class NacosClientController {
    @Value("${config.info}")  //通过nacos配置中心获取文件
    private String configInfo;

    @GetMapping("/config/info")
    public String getConfigInfo() {
        return configInfo;
    }
}
```

> 对应项目:cloudalibaba-config-nacos-client3377



#### 3、使用Sentiel限流

1)导入依赖 

```xml
        <!--SpringCloud ailibaba nacos -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--SpringCloud ailibaba sentinel-datasource-nacos 后续做持久化用到-->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>
        <!--SpringCloud ailibaba sentinel -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        <!--openfeign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
```

2)application.yml配置示例

```yaml
#测试端口
server:
  port: 8401

spring:
  application:
    name: cloudalibaba-sentinel-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #Nacos服务注册中心地址
    sentinel:
      transport:
        dashboard: localhost:8080 #配置Sentinel dashboard地址
        port: 8719  #随机找一个地址,如果冲突就往后+1
        #持久化配置
#      datasource:
#        ds1:
#          nacos:
#            server-addr: localhost:8848
#            dataId: cloudalibaba-sentinel-service
#            groupId: DEFAULT_GROUP
#            data-type: json
#            rule-type: flow

management:
  endpoints:
    web:
      exposure:
        include: '*'

feign:
  sentinel:
    enabled: true # 激活Sentinel对Feign的支持
```

3)接口先请求一次,然后在sentinel控制台进行相应限流模式操作



4)自定义限流异常页面等,使用注解@SentinelResource

```java
    @GetMapping("/testHotKey")
    @SentinelResource(value = "testHotKey", blockHandler = "deal_testHotKey")
    public String testHotKey(@RequestParam(value = "p1", required = false) String p1,
                             @RequestParam(value = "p2", required = false) String p2) {
        //int age = 10/0;
        return "------testHotKey";
    }

    public String deal_testHotKey(String p1, String p2, BlockException exception) {
        //sentinel系统默认的提示:Blocked by Sentinel (flow limiting)
        return "------deal_testHotKey,o(╥﹏╥)o";

    }


	    @GetMapping("/rateLimit/byResource")
    @SentinelResource(value = "byResource", blockHandler = "handleException")
    public CommonResult byResource() {
        return new CommonResult(200, "按资源名称限流测试OK", new Payment(2020L, "serial001"));
    }

    public CommonResult handleException(BlockException exception) {
        return new CommonResult(444, exception.getClass().getCanonicalName() + "\t 服务不可用");
    }

    @GetMapping("/rateLimit/byUrl")
    @SentinelResource(value = "byUrl")
    public CommonResult byUrl() {
        return new CommonResult(200, "按url限流测试OK", new Payment(2020L, "serial002"));
    }


    @GetMapping("/rateLimit/customerBlockHandler")
    @SentinelResource(value = "customerBlockHandler",     //资源名称
            blockHandlerClass = CustomerBlockHandler.class,  //异常自定义
            blockHandler = "handlerException1")   //调用自定义类某个方法
    public CommonResult customerBlockHandler() {
        return new CommonResult(200, "按客戶自定义", new Payment(2020L, "serial003"));
    }
```

```java
/**
 * @author lcry
 * @date 2020/03/17 14:51
 * 用户自定义处理异常类
 */
public class CustomerBlockHandler {
    public static CommonResult handlerException1(BlockException exception) {
        return new CommonResult(4444, "按客戶自定义,global handlerException----1");
    }

    public static CommonResult handlerException2(BlockException exception) {
        return new CommonResult(4444, "按客戶自定义,global handlerException----2");
    }
}
```

> 对应项目:cloudalibaba-sentinel-service8401



#### 4、使用Sentinel服务熔断

1)导入依赖

```xml
 <!--    服务消费方,整合rabbin和feign,sentinel限流熔断等-->
		<!--SpringCloud openfeign -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!--SpringCloud ailibaba sentinel-datasource-nacos做持久化用到-->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>
        <!--SpringCloud ailibaba nacos -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--SpringCloud ailibaba sentinel -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
```

2)启动类添加启用Openfeign注解@EnableFeignClients

```java
@EnableDiscoveryClient
@SpringBootApplication
@EnableFeignClients  //整合feign
public class NacosOrderMain84 {
    public static void main(String[] args) {
        SpringApplication.run(NacosOrderMain84.class, args);
    }
}
```

3)熔断和降级示例业务代码

```java
/**
 * CircleBreakerController
 *
 * @author lcry
 * 使用示例:
 */
@RestController
@Slf4j
public class CircleBreakerController {
    public static final String SERVICE_URL = "http://nacos-payment-provider";

    //    整个rabbin - restTemplate
    @Resource
    private RestTemplate restTemplate;

    //    整合sentinel
    @RequestMapping("/consumer/fallback/{id}")
    //@SentinelResource(value = "fallback") //没有配置
    //@SentinelResource(value = "fallback",fallback = "handlerFallback") //fallback只负责业务异常
    //@SentinelResource(value = "fallback",blockHandler = "blockHandler") //blockHandler只负责sentinel控制台配置违规
//    @SentinelResource(value = "fallback",fallback = "handlerFallback",blockHandler = "blockHandler",  //分开自定义
//            exceptionsToIgnore = {IllegalArgumentException.class}//排除异常不限流
//            )
    @SentinelResource(value = "fallback", //,fallback = "handlerFallback",
            blockHandlerClass = CustomerBlockHandler.class,  //异常自定义
            blockHandler = "handlerException1"  //分开自定义
    )
    public CommonResult<Payment> fallback(@PathVariable Long id) {
        CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/" + id, CommonResult.class, id);

        if (id == 4) {
            throw new IllegalArgumentException("IllegalArgumentException,非法参数异常....");
        } else if (result.getData() == null) {
            throw new NullPointerException("NullPointerException,该ID没有对应记录,空指针异常");
        }

        return result;
    }

    //本例是fallback
    public CommonResult handlerFallback(@PathVariable Long id, Throwable e) {
        Payment payment = new Payment(id, "null");
        return new CommonResult<>(444, "兜底异常handlerFallback,exception内容  " + e.getMessage(), payment);
    }

    //本例是blockHandler
    public CommonResult blockHandler(@PathVariable Long id, BlockException blockException) {
        Payment payment = new Payment(id, "null");
        return new CommonResult<>(445, "blockHandler-sentinel限流,无此流水: blockException  " + blockException.getMessage(), payment);
    }

    //OpenFeign调用
    @Resource
    private PaymentService paymentService;

    @GetMapping(value = "/consumer/paymentSQL/{id}")
    public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id) {
        return paymentService.paymentSQL(id);
    }


    /*
   测试自定义限流
     */
    @GetMapping(value = "/consumer/paymentSQL")
    @SentinelResource(value = "customerBlockHandler",     //资源名称
            blockHandlerClass = CustomerBlockHandler.class,  //异常自定义
            blockHandler = "handlerException1")   //调用自定义类某个方法
    public CommonResult<Payment> paymentSQL2() {
        return paymentService.paymentSQL(1L);
    }
}
```

> 对应项目:cloudalibaba-consumer-nacos-order84



#### 5、使用分布式事务Seata

1)引入依赖

```xml
<!--nacos-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--seata-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
            <!--            排除自带的,我们使用0.9.0-->
            <exclusions>
                <exclusion>
                    <artifactId>seata-all</artifactId>
                    <groupId>io.seata</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>io.seata</groupId>
            <artifactId>seata-all</artifactId>
            <version>0.9.0</version>
        </dependency>
        <!--feign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
```

2)application.yml配置示例

```yaml
#微服务端口
server:
  port: 12001

spring:
  application:
    name: seata-order-service
  cloud:
    alibaba:
      seata:
        #自定义事务组名称需要与seata-server中的对应
        tx-service-group: fsp_tx_group
    nacos:
      discovery:
        server-addr: localhost:8848
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/seata_order?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: lcry

#禁用feign
feign:
  hystrix:
    enabled: false
#OpenFeign的超时控制配置:默认只等待1秒,超时则报错
#设置Feign客户端超时时间(OpenFeign默认支持Ribbon)
ribbon:
  #指的是建立连接所用的时间,适用于网络状况正常的情况下,两端连接所用的时间
  ReadTimeout: 5000
  #指的是建立连接后从服务器读取到可用资源所用的时间
  connectTimeout: 5000
#日志级别
logging:
  level:
    io:
      seata: info
#mybatis映射
mybatis:
  mapperLocations: classpath:mapper/*.xml
```

3)配置file.conf和register.conf,可以直接从Seata上直接拷贝到resources目录下做部分改动

4)业务代码添加注解@GlobalTransactional开启全局事务

```java
    /**
     * 创建订单->调用库存服务扣减库存->调用账户服务扣减账户余额->修改订单状态
     * 简单说:下订单->扣库存->减余额->改状态
     */
    @Override
    @GlobalTransactional(name = "tx-create-order", rollbackFor = Exception.class)
    public void create(Order order) {
        log.info("----->开始新建订单");
        //1 新建订单
        orderDao.create(order);

        //2 扣减库存
        log.info("----->订单微服务开始调用库存,做扣减Count");
        storageService.decrease(order.getProductId(), order.getCount());
        log.info("----->订单微服务开始调用库存,做扣减end");

        //3 扣减账户
        log.info("----->订单微服务开始调用账户,做扣减Money");
        accountService.decrease(order.getUserId(), order.getMoney());
        log.info("----->订单微服务开始调用账户,做扣减end");

        //4 修改订单状态,从零到1,1代表已经完成
        log.info("----->修改订单状态开始");
        orderDao.update(order.getUserId(), 0);
        log.info("----->修改订单状态结束");

        log.info("----->下订单结束了,O(∩_∩)O哈哈~");

    }
```

> 对应项目:cloudalibaba-seata-order-service12001、cloudalibaba-seata-storage-service12002、cloudalibaba-seata-account-service12003
1728

1729

L
lcry 已提交
1730 1731 1732



1733
**完结~**
L
lcry 已提交
1734