天天看點

SpringCloud學習之路1、使用IDEA搭建Eureka服務中心Server端啟動2、降級熔斷Hystrix實戰3、斷路器Dashboard監控儀表盤4、微服務網關zuul5、分布式鍊路追蹤系統Sleuth和ZipKin6、微服務核心知識分布式配置中心Config7、微服務消息總線Bus結合消息隊列RabbitMQ8、安裝Docker倉庫9、SpringCloud和Docker整合部署10、其他

SpringCloud學習之路

  • 1、使用IDEA搭建Eureka服務中心Server端啟動
    • 1.1、建立和配置注冊中心Eureka
    • 1.2、使用Eureka案例
    • 1.3、負載均衡器Ribbon
    • 1.4、負載均衡器Feign
    • 1.5、Feign核心源碼解讀和服務調用方式ribbon和Feign選擇
  • 2、降級熔斷Hystrix實戰
    • 2.1、SpringCloud整合斷路器的使用,使用者服務異常情況(熔斷)
    • 2.2、SpringCloud整合斷路器的使用,使用者服務異常情況(降級)
    • 2.3、熔斷降級服務異常報警通知
    • 2.4、Hystrix降級政策和調整逾時時間
  • 3、斷路器Dashboard監控儀表盤
  • 4、微服務網關zuul
    • 4.1、基本配置
    • 4.2、自定義路由映射
    • 4.3、忽略整個服務對外提供接口
    • 4.4、通過正則的方式忽略整個服務對外提供接口
    • 4.5、處理http請求頭為空的問題
    • 4.6、自定義Zuul過濾器實作登入鑒權
    • 4.7、高并發下接口限流
    • 4.8、Zuul微服務網關叢集搭建
  • 5、分布式鍊路追蹤系統Sleuth和ZipKin
    • 5.1、使用Sleuth
    • 5.2、可視化鍊路追蹤系統ZipKin部署
  • 6、微服務核心知識分布式配置中心Config
    • 6.1、服務端
    • 6.2、用戶端
    • 生産環境部署常見問題,配置中心通路路徑變化
  • 7、微服務消息總線Bus結合消息隊列RabbitMQ
    • 7.1、實戰案例
  • 8、安裝Docker倉庫
    • 8.1、快速掌握Dokcer基礎知識
  • 9、SpringCloud和Docker整合部署
    • 9.1、建構springboot應用
    • 9.2、打包SpringCloud鏡像并上傳私有倉庫并部署
  • 10、其他
    • 10.1、阿裡雲依賴
    • 10.2、虛拟機環境開啟
    • 10.3、生産環境部署常見問題,配置中心通路路徑變化

1、使用IDEA搭建Eureka服務中心Server端啟動

SpringCloud學習之路1、使用IDEA搭建Eureka服務中心Server端啟動2、降級熔斷Hystrix實戰3、斷路器Dashboard監控儀表盤4、微服務網關zuul5、分布式鍊路追蹤系統Sleuth和ZipKin6、微服務核心知識分布式配置中心Config7、微服務消息總線Bus結合消息隊列RabbitMQ8、安裝Docker倉庫9、SpringCloud和Docker整合部署10、其他
SpringCloud學習之路1、使用IDEA搭建Eureka服務中心Server端啟動2、降級熔斷Hystrix實戰3、斷路器Dashboard監控儀表盤4、微服務網關zuul5、分布式鍊路追蹤系統Sleuth和ZipKin6、微服務核心知識分布式配置中心Config7、微服務消息總線Bus結合消息隊列RabbitMQ8、安裝Docker倉庫9、SpringCloud和Docker整合部署10、其他

1.1、建立和配置注冊中心Eureka

添加Eureka Server

第一步:建立項目

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.yuange</groupId>
    <artifactId>eureka_server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>eureka_server</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

           

第二步: 添加注解 @EnableEurekaServer

第三步:增加配置application.yml

server:
  port: 8761
  eureka:
    instance:
      hostname: localhost
    client:
      #聲明自己是個服務端
      registerWithEureka: false
      fetchRegistry: false
      serviceUrl:
        defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
           

1.2、使用Eureka案例

建立product-service(使用的輪詢)

server:
  port: 8771

#指定注冊中心位址
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

#服務的名稱
spring:
  application:
    name: product-service
           

啟動多個節點

1、啟動多個

2、指定端口号

SpringCloud學習之路1、使用IDEA搭建Eureka服務中心Server端啟動2、降級熔斷Hystrix實戰3、斷路器Dashboard監控儀表盤4、微服務網關zuul5、分布式鍊路追蹤系統Sleuth和ZipKin6、微服務核心知識分布式配置中心Config7、微服務消息總線Bus結合消息隊列RabbitMQ8、安裝Docker倉庫9、SpringCloud和Docker整合部署10、其他

1.3、負載均衡器Ribbon

RPC:
		遠端過程調用,像調用本地服務(方法)一樣調用伺服器的服務
		支援同步、異步調用
		用戶端和伺服器之間建立TCP連接配接,可以一次建立一個,也可以多個調用複用一次連結
		PRC資料包小
			protobuf
			thrift
		rpc:編解碼,序列化,連結,丢包,協定
	Rest(Http):
		http請求,支援多種協定和功能
		開發友善成本低
		http資料包大
		java開發:HttpClient,URLConnection
           

Ribbon(軟負載均衡,在用戶端上進行)

使用ribbon. (類似httpClient,URLConnection) 
		啟動類增加注解
		  @Bean
		  @LoadBalanced
		  public RestTemplate restTemplate() {
		       return new RestTemplate();
		  }
           

建立order-server

依賴

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.yuange</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

           

第一種啟動方式(核心代碼)

@Service
public class ProductOrderServiceImpl implements ProductOrderService {


    @Autowired
    private RestTemplate restTemplate;

    @Override
    public ProductOrder save(int userId, int productId) {
        //位址(服務名稱/api),傳回類型
        Object obj = restTemplate.getForObject("http://product-service/api/v1/product/find?id="+productId, Object.class);

        System.out.println(obj);

        ProductOrder productOrder = new ProductOrder();
        productOrder.setCreateTime(new Date());
        productOrder.setUserId(userId);
        productOrder.setTradeNo(UUID.randomUUID().toString());

        return productOrder;
    }
}
           

第二種啟動方式

@Service
public class ProductOrderServiceImpl implements ProductOrderService {


//    @Autowired
//    private RestTemplate restTemplate;

    @Autowired
    private LoadBalancerClient loadBalancerClient;

    @Override
    public ProductOrder save(int userId, int productId) {
        //第一種
        //位址(服務名稱/api),傳回類型
        //Map<String,Object> productMap = restTemplate.getForObject("http://product-service/api/v1/product/find?id="+productId, Map.class);

        //第二種
        ServiceInstance instance = loadBalancerClient.choose("product-service");
        //位址,ip,端口号
        String url=String.format("http://%s:%s/api/v1/product/find?id="+productId,instance.getHost(),instance.getPort());
        RestTemplate restTemplate = new RestTemplate();
        Map<String,Object> productMap = restTemplate.getForObject(url, Map.class);


        ProductOrder productOrder = new ProductOrder();
        productOrder.setCreateTime(new Date());
        productOrder.setUserId(userId);
        productOrder.setTradeNo(UUID.randomUUID().toString());
        productOrder.setProductName(productMap.get("name").toString());
        productOrder.setPrice(Integer.parseInt(productMap.get("price").toString()));

        return productOrder;
    }
}

           

自定義負載均衡,從輪詢到随機

政策選擇:

1、如果每個機器配置一樣,則建議不修改政策 (推薦)

2、如果部分機器配置強,則可以改為 WeightedResponseTimeRule

server:
  port: 8781

#指定注冊中心位址
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

#服務的名稱
spring:
  application:
    name: order-service

#自定義負載均衡政策(從輪詢到随機)
product-service:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
           

1.4、負載均衡器Feign

包含了Feign的調用逾時時間
Feign: 僞RPC用戶端(本質還是用http)
	官方文檔: https://cloud.spring.io/spring-cloud-openfeign/
	1、使用feign步驟講解(新舊版本依賴名稱不一樣)
		加入依賴
			 <dependency>
		        <groupId>org.springframework.cloud</groupId>
		        <artifactId>spring-cloud-starter-openfeign</artifactId>
		    </dependency>
		啟動類增加@EnableFeignClients
		增加一個接口 并@FeignClient(name="product-service")
	2、編碼實戰
	3、注意點:
		1、路徑
		2、Http方法必須對應
		3、使用requestBody,應該使用@PostMapping
		4、多個參數的時候,通過@RequestParam("id") int id)方式調用
           

第一步,引入依賴(新舊版本依賴名稱不一樣)

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

第二步,啟動類增加@EnableFeignClients

第三步,增加一個接口 并@FeignClient(name=“product-service”)

@FeignClient(name = "product-service")
public interface ProductClient {
    /**
     * 通過id查找
     * @param id
     * @return
     */
    @RequestMapping("/api/v1/product/find")
    String findById(@RequestParam(value = "id") int id);
}
           

建立一個JsonUtils

public class JsonUtils {


    private static final ObjectMapper objectMappper = new ObjectMapper();


    /**
     * json字元串轉JsonNode對象的方法
     */
    public static JsonNode str2JsonNode(String str){
        try {
            return  objectMappper.readTree(str);
        } catch (IOException e) {
            return null;
        }
    }

}
           

第四步,調用

@Service
public class ProductOrderServiceImpl implements ProductOrderService {

    @Autowired
    private ProductClient productClient;

    @Override
    public ProductOrder save(int userId, int productId) {

        //使用Feign建立
        String response = productClient.findById(productId);

        JsonNode jsonNode = JsonUtils.str2JsonNode(response);

        ProductOrder productOrder = new ProductOrder();
        productOrder.setCreateTime(new Date());
        productOrder.setUserId(userId);
        productOrder.setTradeNo(UUID.randomUUID().toString());
        productOrder.setProductName(jsonNode.get("name").toString());
        productOrder.setPrice(Integer.parseInt(jsonNode.get("price").toString()));

        return productOrder;
    }
}
           

注意點:

1、路徑

2、Http方法必須對應

3、使用requestBody,應該使用@PostMapping

4、多個參數的時候,通過@RequestParam(“id”) int id)方式調用

1.5、Feign核心源碼解讀和服務調用方式ribbon和Feign選擇

1、ribbon和feign兩個的差別和選擇
		選擇feign
			預設內建了ribbon
			寫起來更加思路清晰和友善
			采用注解方式進行配置,配置熔斷等方式友善
	2、逾時配置
		預設optons readtimeout是60,但是由于hystrix預設是1秒逾時
		#修改調用逾時時間
		feign:
		  client:
		    config:
		      default:
		        connectTimeout: 2000
		        readTimeout: 2000
		模拟接口響應慢,線程睡眠新的方式
		  try {
	            TimeUnit.SECONDS.sleep(1);
	        } catch (InterruptedException e) {
	            e.printStackTrace();
	        }
           

2、降級熔斷Hystrix實戰

1、熔斷:
	保險絲,熔斷服務,為了防止整個系統故障,包含子和下遊服務
	下單服務 -》商品服務
			-》使用者服務 (出現異常-》熔斷)
2、降級:
	抛棄一些非核心的接口和資料
	旅行箱的例子:隻帶核心的物品,抛棄非核心的,等有條件的時候再去攜帶這些物品
3、熔斷和降級互相交集
	相同點:
		1)從可用性和可靠性觸發,為了防止系統崩潰
		2)最終讓使用者體驗到的是某些功能暫時不能用
	不同點
		1)服務熔斷一般是下遊服務故障導緻的,而服務降級一般是從整體系統負荷考慮,由調用方控制
           

2.1、SpringCloud整合斷路器的使用,使用者服務異常情況(熔斷)

第一步導入依賴

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

第二步啟動類上添加注解

@EnableCircuitBreaker

注解越來越多可以使用SpringCloudApplication注解

第三步在api方法上增加 @HystrixCommand(fallbackMethod = “saveOrderFail”)

注意編寫fallback方法實作,方法簽名一定要和api方法簽名一緻

核心代碼

@RestController
@RequestMapping("api/v1/order")
public class OrderController {


    @Autowired
    private ProductOrderService productOrderService;


    @RequestMapping("save")
    @HystrixCommand(fallbackMethod = "saveOrderFail")
    public Object save(@RequestParam("user_id") int userId, @RequestParam("product_id") int productId) {
        Map<String, Object> data = new HashMap<>();
        data.put("code", 0);
        data.put("data", productOrderService.save(userId, productId));
        return data;
    }

    //注意方法簽名一定要和api方法一緻
    private Object saveOrderFail(int userId, int productId) {
        Map<String, Object> msg = new HashMap<>();
        msg.put("code", -1);
        msg.put("msg", "搶購人數太多,您被擠出來了,稍等重試");
        return msg;
    }
    
}
           

PRODUCT-SERVICE當機後

SpringCloud學習之路1、使用IDEA搭建Eureka服務中心Server端啟動2、降級熔斷Hystrix實戰3、斷路器Dashboard監控儀表盤4、微服務網關zuul5、分布式鍊路追蹤系統Sleuth和ZipKin6、微服務核心知識分布式配置中心Config7、微服務消息總線Bus結合消息隊列RabbitMQ8、安裝Docker倉庫9、SpringCloud和Docker整合部署10、其他

補充: 修改maven倉庫位址

pom.xml中修改

<repositories>
    <repository>
        <id>nexus-aliyun</id>
        <name>Nexus aliyun</name>
        <layout>default</layout>
        <url>http://maven.aliyun.com/nexus/content/groups/public</url>
        <snapshots>
            <enabled>false</enabled>
        </snapshots>
        <releases>
            <enabled>true</enabled>
        </releases>
    </repository>
</repositories>
           

2.2、SpringCloud整合斷路器的使用,使用者服務異常情況(降級)

1、feign結合Hystrix
	1)開啟feign支援hystrix  (注意,一定要開啟,舊版本預設支援,新版本預設關閉)
		feign:
		  hystrix:
		    enabled: true
	2)FeignClient(name="xxx", fallback=xxx.class ), class需要繼承目前FeignClient的類
           
@FeignClient(name = "product-service",fallback = ProductClientFallback.class)
public interface ProductClient {
    /**
     * 通過id查找
     * @param id
     * @return
     */
    @RequestMapping("/api/v1/product/find")
    String findById(@RequestParam(value = "id") int id);
}
           
@Component
public class ProductClientFallback implements ProductClient {

    @Override
    public String findById(int id) {
        System.out.println("feign 調用product-service findbyid 異常");
        return null;
    }
}
           

2.3、熔斷降級服務異常報警通知

加入redis依賴

<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
           

配置redis連結資訊

redis:
    database: 0
    host: 127.0.0.1
    port: 6379
    timeout: 2000
           

使用

核心代碼

//監控報警(key-value形式)
        String saveOrderKey = "save-order";

        String sendValue = redisTemplate.opsForValue().get(saveOrderKey);
        //知道那個節點ip資訊
        final String ip = request.getRemoteAddr();

        //發送資訊要異步,開一個子線程(使用了lambda表達式)
        new Thread(() -> {
            if (StringUtils.isBlank(sendValue)) {
                System.out.println("緊急短信,使用者下單失敗,請離開查找原因,ip位址是="+ip);
                //發送一個http請求,調用短信服務 TODO (二十秒)
                redisTemplate.opsForValue().set(saveOrderKey, "save-order-fail", 20, TimeUnit.SECONDS);
            } else {
                System.out.println("已經發送過短信,20秒内不重複發送");
            }
        }).start();
           

舉例

@RestController
@RequestMapping("api/v1/order")
public class OrderController {


    @Autowired
    private ProductOrderService productOrderService;

    @Autowired
    private StringRedisTemplate redisTemplate;


    @RequestMapping("save")
    @HystrixCommand(fallbackMethod = "saveOrderFail")
    public Object save(@RequestParam("user_id") int userId, @RequestParam("product_id") int productId, HttpServletRequest request) {
        Map<String, Object> data = new HashMap<>();
        data.put("code", 0);
        data.put("data", productOrderService.save(userId, productId));
        return data;
    }

    //注意方法簽名一定要和api方法一緻
    private Object saveOrderFail(int userId, int productId, HttpServletRequest request) {

        //監控報警(key-value形式)
        String saveOrderKey = "save-order";

        String sendValue = redisTemplate.opsForValue().get(saveOrderKey);
        //知道那個節點ip資訊
        final String ip = request.getRemoteAddr();

        //發送資訊要異步,開一個子線程(使用了lambda表達式)
        new Thread(() -> {
            if (StringUtils.isBlank(sendValue)) {
                System.out.println("緊急短信,使用者下單失敗,請離開查找原因,ip位址是="+ip);
                //發送一個http請求,調用短信服務 TODO (二十秒)
                redisTemplate.opsForValue().set(saveOrderKey, "save-order-fail", 20, TimeUnit.SECONDS);
            } else {
                System.out.println("已經發送過短信,20秒内不重複發送");
            }
        }).start();

        Map<String, Object> msg = new HashMap<>();
        msg.put("code", -1);
        msg.put("msg", "搶購人數太多,您被擠出來了,稍等重試");
        return msg;
    }

}
           

2.4、Hystrix降級政策和調整逾時時間

第一種注解形式設定commandProperties 屬性(不友好)

@RequestMapping("save")
    @HystrixCommand(fallbackMethod = "saveOrderFail", commandProperties = {
            @HystrixProperty(name = "", value = "")
    })
    public Object save(@RequestParam("user_id") int userId, @RequestParam("product_id") int productId, HttpServletRequest request) {
        Map<String, Object> data = new HashMap<>();
        data.put("code", 0);
        data.put("data", productOrderService.save(userId, productId));
        return data;
    }
           

第二種配置

這裡是Hystrix的逾時
#熔斷器Hystrix逾時時間調整
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 1000
            
#是否開啟逾時限制 (一定不要禁用)
hystrix:
  command:
    default:
     execution:
      timeout:
        enabled: false
           

3、斷路器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>
           

第二步,啟動類型加上注解。

@EnableHystrixDashboard

第三步,配置檔案增加endpoint。

#斷路器Dashboard監控儀表盤(*代表暴露全部的監控資訊)
management:
  endpoints:
    web:
      exposure:
        include: "*"
           

第四步,通路入口。

http://localhost:8781/hystrix

Hystrix Dashboard輸入: http://localhost:8781/actuator/hystrix.stream

SpringCloud學習之路1、使用IDEA搭建Eureka服務中心Server端啟動2、降級熔斷Hystrix實戰3、斷路器Dashboard監控儀表盤4、微服務網關zuul5、分布式鍊路追蹤系統Sleuth和ZipKin6、微服務核心知識分布式配置中心Config7、微服務消息總線Bus結合消息隊列RabbitMQ8、安裝Docker倉庫9、SpringCloud和Docker整合部署10、其他
SpringCloud學習之路1、使用IDEA搭建Eureka服務中心Server端啟動2、降級熔斷Hystrix實戰3、斷路器Dashboard監控儀表盤4、微服務網關zuul5、分布式鍊路追蹤系統Sleuth和ZipKin6、微服務核心知識分布式配置中心Config7、微服務消息總線Bus結合消息隊列RabbitMQ8、安裝Docker倉庫9、SpringCloud和Docker整合部署10、其他

4、微服務網關zuul

攔截作用

什麼是網關
API Gateway,是系統的唯一對外的入口,介于用戶端和伺服器端之間的中間層,處理非業務功能 提供路由請求、鑒權、監控、緩存、限流等功能
		統一接入
			智能路由
			AB測試、灰階測試
			負載均衡、容災處理
			日志埋點(類似Nignx日志)
		流量監控
			限流處理
			服務降級
		安全防護
			鑒權處理
			監控
			機器網絡隔離
主流的網關
	zuul:是Netflix開源的微服務網關,和Eureka,Ribbon,Hystrix等元件配合使用,Zuul 2.0比1.0的性能提高很多
	
	kong: 由Mashape公司開源的,基于Nginx的API gateway
	
	nginx+lua:是一個高性能的HTTP和反向代理伺服器,lua是腳本語言,讓Nginx執行Lua腳本,并且高并發、非阻塞的處理各種請求
           

導入依賴

<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        </dependency>
           

啟動類加入注解 @EnableZuulProxy

4.1、基本配置

server:
  port: 9000


#服務的名稱
spring:
  application:
    name: api-gateway


#指定注冊中心位址
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
           
預設通路規則  
http://gateway:port/service-id/**

不使用網關通路
http://localhost:8781/api/v1/order/save?product_id=6&user_id=2

使用網關通路(網關端口号加服務)
http://localhost:9000/order-service/api/v1/order/save?product_id=6&user_id=2
           

4.2、自定義路由映射

給單獨給服務配置

#自定義路由映射
zuul:
  routes:
    order-service: /apigateway/**
           
http://localhost:9000/order-service/api/v1/order/save?product_id=6&user_id=2
也可以
http://localhost:9000/apigateway/api/v1/order/save?product_id=6&user_id=2
           

4.3、忽略整個服務對外提供接口

拒絕通路商品服務

例如

http://localhost:9000/product-service/api/v1/product/find?id=1
server:
  port: 9000


#服務的名稱
spring:
  application:
    name: api-gateway



#指定注冊中心位址
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

#/order-service/api/v1/order/save?user_id=2&product_id=1
#自定義路由映射
zuul:
  routes:
    order-service: /apigateway/**
    #忽略整個服務,對外提供接口
    ignored-services: product-service
           

4.4、通過正則的方式忽略整個服務對外提供接口

server:
  port: 9000

#服務的名稱
spring:
  application:
    name: api-gateway

#指定注冊中心位址
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

#/order-service/api/v1/order/save?user_id=2&product_id=1
#自定義路由映射
zuul:
  routes:
    product-service: /apigateway1/**
    order-service: /apigateway2/**
  #統一入口為上面的配置,其他入口忽略
  ignored-patterns: /*-service/**
  #忽略整個服務,對外提供接口
  #ignored-services: product-service
  
           

4.5、處理http請求頭為空的問題

#自定義路由映射
zuul:
  #處理http請求頭為空的問題(如Cookies)
  sensitive-headers:
           

其他筆記

過濾器執行順序問題 ,過濾器的order值越小,越先執行

共享RequestContext,上下文對象

4.6、自定義Zuul過濾器實作登入鑒權

zuul流程

SpringCloud學習之路1、使用IDEA搭建Eureka服務中心Server端啟動2、降級熔斷Hystrix實戰3、斷路器Dashboard監控儀表盤4、微服務網關zuul5、分布式鍊路追蹤系統Sleuth和ZipKin6、微服務核心知識分布式配置中心Config7、微服務消息總線Bus結合消息隊列RabbitMQ8、安裝Docker倉庫9、SpringCloud和Docker整合部署10、其他
1、建立一個filter包
2、建立一個類,實作ZuulFilter,重寫裡面的方法
3、在類頂部加注解,@Component,讓Spring掃描
           

核心代碼

package com.yuange.apigateway.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.apache.commons.lang.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;

/**
 * @author lichangyuan
 * @create 2021-04-25 9:47
 */
@Component
public class LoginFilter extends ZuulFilter {
    /**
     * 過濾器類型前置通知
     *
     * @return
     */
    @Override
    public String filterType() {
        return PRE_TYPE;
    }

    /**
     * 過濾器順序,越小越先執行
     *
     * @return
     */
    @Override
    public int filterOrder() {
        return 4;
    }

    /**
     * 過濾器是否生效
     *
     * @return
     */
    @Override
    public boolean shouldFilter() {
        RequestContext currentContext = RequestContext.getCurrentContext();
        HttpServletRequest request = currentContext.getRequest();
//        System.out.println(request.getRequestURI());//     /apigateway/product/api/v1/product/list
//        System.out.println(request.getRequestURL());//     http://localhost:9000/apigateway/product/api/v1/product/list
        
        //ACL,一些權限校驗邏輯
        
        //如果傳回true則進行攔截,執行業務邏輯
        if ("/apigateway/order/api/v1/order/save".equalsIgnoreCase(request.getRequestURI())) {
            return true;
        } else if ("/apigateway/order/api/v1/order/list".equalsIgnoreCase(request.getRequestURI())) {
            return true;
        } else if ("/apigateway/order/api/v1/order/find".equalsIgnoreCase(request.getRequestURI())) {
            return true;
        }
        return false;
    }

    /**
     * 業務邏輯
     *
     * @return
     * @throws ZuulException
     */
    @Override
    public Object run() throws ZuulException {
        //JWT
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();

        //token對象
        String token = request.getHeader("token");

        //如果token為空,則從參數中查找
        if (StringUtils.isBlank((token))) {
            token = request.getParameter("token");
        }

        //登入校驗邏輯  根據公司情況自定義 JWT
        if (StringUtils.isBlank(token)) {
            //這個請求最終不會被zuul轉發到後端伺服器
            requestContext.setSendZuulResponse(false);
            //設定響應資訊       HttpStatus.UNAUTHORIZED.value()   為401未經授權
            requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
        }
        return null;
    }
}
           

當不攜帶token時

SpringCloud學習之路1、使用IDEA搭建Eureka服務中心Server端啟動2、降級熔斷Hystrix實戰3、斷路器Dashboard監控儀表盤4、微服務網關zuul5、分布式鍊路追蹤系統Sleuth和ZipKin6、微服務核心知識分布式配置中心Config7、微服務消息總線Bus結合消息隊列RabbitMQ8、安裝Docker倉庫9、SpringCloud和Docker整合部署10、其他

當攜帶token時,則能正常通路。

SpringCloud學習之路1、使用IDEA搭建Eureka服務中心Server端啟動2、降級熔斷Hystrix實戰3、斷路器Dashboard監控儀表盤4、微服務網關zuul5、分布式鍊路追蹤系統Sleuth和ZipKin6、微服務核心知識分布式配置中心Config7、微服務消息總線Bus結合消息隊列RabbitMQ8、安裝Docker倉庫9、SpringCloud和Docker整合部署10、其他

4.7、高并發下接口限流

1、nginx層限流

2、網關層限流

package com.yuange.apigateway.filter;

import com.google.common.util.concurrent.RateLimiter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.http.HttpStatus;

import javax.servlet.http.HttpServletRequest;

import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;

/**
 * 隻給訂單接口限流
 */
public class OederRateLimiterFilter extends ZuulFilter {

    //每秒産生1000個令牌
    private static final RateLimiter RATE_LIMITER = RateLimiter.create(1000);

    @Override
    public String filterType() {

        return PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        //預設最小-3
        return -4;
    }

    @Override
    public boolean shouldFilter() {
        RequestContext currentContext = RequestContext.getCurrentContext();
        HttpServletRequest request = currentContext.getRequest();
        //隻對訂單接口做限流
        if ("/apigateway/order/api/v1/order/save".equalsIgnoreCase(request.getRequestURI())) {
            return true;
        }
        return false;
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext requestContext = RequestContext.getCurrentContext();
        //如果沒有拿到令牌
        if (!RATE_LIMITER.tryAcquire()) {
            //這個請求最終不會被zuul轉發到後端伺服器
            requestContext.setSendZuulResponse(false);
            requestContext.setResponseStatusCode(HttpStatus.TOO_MANY_REQUESTS.value());
        }

        return null;
    }
}

           

4.8、Zuul微服務網關叢集搭建

SpringCloud學習之路1、使用IDEA搭建Eureka服務中心Server端啟動2、降級熔斷Hystrix實戰3、斷路器Dashboard監控儀表盤4、微服務網關zuul5、分布式鍊路追蹤系統Sleuth和ZipKin6、微服務核心知識分布式配置中心Config7、微服務消息總線Bus結合消息隊列RabbitMQ8、安裝Docker倉庫9、SpringCloud和Docker整合部署10、其他

5、分布式鍊路追蹤系統Sleuth和ZipKin

5.1、使用Sleuth

Sleuth是一個元件,專門用于記錄鍊路資料的開源元件

加入依賴

<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-sleuth</artifactId>
        </dependency>
           

自定義日志(由于第一次測試有,第二次測試沒有說明日志級别問題)

SpringCloud學習之路1、使用IDEA搭建Eureka服務中心Server端啟動2、降級熔斷Hystrix實戰3、斷路器Dashboard監控儀表盤4、微服務網關zuul5、分布式鍊路追蹤系統Sleuth和ZipKin6、微服務核心知識分布式配置中心Config7、微服務消息總線Bus結合消息隊列RabbitMQ8、安裝Docker倉庫9、SpringCloud和Docker整合部署10、其他

核心代碼

import com.yuange.product_server.domain.Product;
import com.yuange.product_server.service.ProductService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;


/**
 * @author lichangyuan
 * @create 2021-04-19 14:57
 */
@Service
public class ProductServiceImpl implements ProductService {

    private final Logger logger= LoggerFactory.getLogger(getClass());
    
    @Override
    public Product findById(int id) {
        //列印日志
        logger.info("service findById product");
        return null;
    }
}
           
SpringCloud學習之路1、使用IDEA搭建Eureka服務中心Server端啟動2、降級熔斷Hystrix實戰3、斷路器Dashboard監控儀表盤4、微服務網關zuul5、分布式鍊路追蹤系統Sleuth和ZipKin6、微服務核心知識分布式配置中心Config7、微服務消息總線Bus結合消息隊列RabbitMQ8、安裝Docker倉庫9、SpringCloud和Docker整合部署10、其他
[order-service,96f95a0dd81fe3ab,852ef4cfcdecabf3,false]
		1、第一個值,spring.application.name的值
		2、第二個值,96f95a0dd81fe3ab ,sleuth生成的一個ID,叫Trace ID,用來辨別一條請求鍊路,一條請求鍊路中包含一個Trace ID,多個Span ID
		3、第三個值,852ef4cfcdecabf3、spanid 基本的工作單元,擷取中繼資料,如發送一個http
		4、第四個值:false,是否要将該資訊輸出到zipkin服務中來收集和展示。
           

5.2、可視化鍊路追蹤系統ZipKin部署

大規模分布式系統的APM工具(Application Performance Management),基于Google Dapper的基礎實作,和sleuth結合可以提供可視化web界面分析調用鍊路耗時情況

知識拓展:OpenTracing

OpenTracing 已進入 CNCF,正在為全球的分布式追蹤,提供統一的概念和資料标準。

通過提供平台無關、廠商無關的 API,使得開發人員能夠友善的添加(或更換)追蹤系統的實作。

使用docker安裝

docker run -d -p 9411:9411 openzipkin/zipkin
           

可視化web界面

http://192.168.8.128:9411/zipkin/
           
SpringCloud學習之路1、使用IDEA搭建Eureka服務中心Server端啟動2、降級熔斷Hystrix實戰3、斷路器Dashboard監控儀表盤4、微服務網關zuul5、分布式鍊路追蹤系統Sleuth和ZipKin6、微服務核心知識分布式配置中心Config7、微服務消息總線Bus結合消息隊列RabbitMQ8、安裝Docker倉庫9、SpringCloud和Docker整合部署10、其他

導入依賴

<dependency>
	    <groupId>org.springframework.cloud</groupId>
	    <artifactId>spring-cloud-starter-zipkin</artifactId>
	</dependency>
           

此依賴包含了兩個依賴

<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-sleuth</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-sleuth-zipkin</artifactId>
		</dependency>
           

配置

#服務的名稱
spring:
  application:
    name: order-service
  redis:
    database: 0
    host: 127.0.0.1
    port: 6379
    timeout: 2000

    #zipkin服務所在位址
  zipkin:
    base-url: http://192.168.8.128:9411/
    #配置采樣百分比,開發環境可以設定為1,表示全部,生産就用預設
  sleuth:
    sampler:
      probability: 1
           
SpringCloud學習之路1、使用IDEA搭建Eureka服務中心Server端啟動2、降級熔斷Hystrix實戰3、斷路器Dashboard監控儀表盤4、微服務網關zuul5、分布式鍊路追蹤系統Sleuth和ZipKin6、微服務核心知識分布式配置中心Config7、微服務消息總線Bus結合消息隊列RabbitMQ8、安裝Docker倉庫9、SpringCloud和Docker整合部署10、其他
SpringCloud學習之路1、使用IDEA搭建Eureka服務中心Server端啟動2、降級熔斷Hystrix實戰3、斷路器Dashboard監控儀表盤4、微服務網關zuul5、分布式鍊路追蹤系統Sleuth和ZipKin6、微服務核心知識分布式配置中心Config7、微服務消息總線Bus結合消息隊列RabbitMQ8、安裝Docker倉庫9、SpringCloud和Docker整合部署10、其他

6、微服務核心知識分布式配置中心Config

6.1、服務端

統一管理配置, 快速切換各個環境的配置

導入依賴和注冊中心

<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
           

啟動類增加注解

@EnableConfigServer

配置

#服務的名稱
spring:
  application:
    name: config-server
    #git配置
  cloud:
    config:
      server:
        git:
          uri: https://gitee.com/lichangyuan/config_cloud
          username: 15888488307
          password: l15888488307cy
          #逾時時間
          timeout: 5
          #分支
          default-label: master

server:
  port: 9100

#指定注冊中心位址
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

           

通路路徑(一定要有‘-’,根據字首比對)

http://localhost:9100/product-service.yml

通路方式(一定要注意文法,如果有問題,會出錯)

多種通路路徑,可以通過啟動日志去檢視
		例子 http://localhost:9100/product-service.yml
		/{name}-{profiles}.properties
		/{name}-{profiles}.yml
		/{name}-{profiles}.json
		/{label}/{name}-{profiles}.yml
		name 伺服器名稱
		profile 環境名稱,開發、測試、生産
		lable 倉庫分支、預設master分支
           

建立兩個環境,兩個分支。

SpringCloud學習之路1、使用IDEA搭建Eureka服務中心Server端啟動2、降級熔斷Hystrix實戰3、斷路器Dashboard監控儀表盤4、微服務網關zuul5、分布式鍊路追蹤系統Sleuth和ZipKin6、微服務核心知識分布式配置中心Config7、微服務消息總線Bus結合消息隊列RabbitMQ8、安裝Docker倉庫9、SpringCloud和Docker整合部署10、其他
server:
  port: 8771

#指定注冊中心位址
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

#服務的名稱
spring:
  application:
    name: product-service
    #zipkin服務所在位址
  zipkin:
    base-url: http://192.168.8.128:9411/
    #配置采樣百分比,開發環境可以設定為1,表示全部,生産就用預設
  sleuth:
    sampler:
      probability: 1

#這個為環境
env: dev
#這個為分支
branch: master
           

http://localhost:9100/master/product-service-dev.yml

SpringCloud學習之路1、使用IDEA搭建Eureka服務中心Server端啟動2、降級熔斷Hystrix實戰3、斷路器Dashboard監控儀表盤4、微服務網關zuul5、分布式鍊路追蹤系統Sleuth和ZipKin6、微服務核心知識分布式配置中心Config7、微服務消息總線Bus結合消息隊列RabbitMQ8、安裝Docker倉庫9、SpringCloud和Docker整合部署10、其他

6.2、用戶端

依賴

<!--配置中心依賴-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-client</artifactId>
        </dependency>
           

配置,要把配置檔案重命名為bootstrap.yml

#指定注冊中心位址
		eureka:
		  client:
		    serviceUrl:
		      defaultZone: http://localhost:8761/eureka/
		#服務的名稱
		spring:
		  application:
		    name: product-service
		  #指定從哪個配置中心讀取
		  cloud:
		    config:
		      discovery:
		        service-id: CONFIG-SERVER
		        #開發發現的功能預設為false
		        enabled: true
		      #指定環境
		      profile: test
		      #建議用lable去區分環境,預設是lable是master分支
		      #label: test
           

最終使用的master分支test環境(預設lable由服務端決定)

生産環境部署常見問題,配置中心通路路徑變化

#指定注冊中心位址
eureka:
  client:
    serviceUrl:
      #一般注冊中心和配置中心不會在同一台伺服器,而且不會對外公布,使用内網ip
      defaultZone: http://localhost:8761/eureka/
  instance:
  instance-id: ${spring.cloud.client.ip-address}:${server.port}
  prefer-ip-address: true
           

7、微服務消息總線Bus結合消息隊列RabbitMQ

1、什麼是消息
		一個事件,需要廣播或者單獨傳遞給某個接口
	2、為什麼使用這個
		配置更新了,但是其他系統不知道是否更新

	安裝步驟
		1)拉取鏡像:docker pull rabbitmq:management
		2)檢視目前鏡像清單:docker images
		3)删除指定鏡像:docker rmi  IMAGE_ID  (如果需要強制删除加 -f)
		
		4)建立容器
		docker run -d --name="myrabbitmq" -p 5671:5671 -p 15672:15672 rabbitmq:management
		 	-d: 背景運作容器,并傳回容器ID
		 	-p: 端口映射,格式為:主機(宿主)端口:容器端口
		 	--name="rabbitmq": 為容器指定一個名稱
	RabbitMQ預設建立了一個 guest 使用者,密碼也是 guest, 如果通路不了記得檢視防火牆,端口或者雲伺服器的安全組
	管理背景:http://127.0.0.1:15672


		伺服器啟動
		 5672是項目中連接配接rabbitmq的端口(我這裡映射的是5672),15672是rabbitmq的web管理界面端口(我映射為15672)
		rabbitmq: docker run -d -p 5672:5672 -p 15672:15672 rabbitmq:management
		rabbitmq預設是5672,是以改為5672端口
           

導入依賴

<!--配置中心結合消息隊列-->
	       
	        <dependency>
	            <groupId>org.springframework.boot</groupId>
	            <artifactId>spring-boot-starter-actuator</artifactId>
	        </dependency>
	        <dependency>
	            <groupId>org.springframework.cloud</groupId>
	            <artifactId>spring-cloud-starter-bus-amqp</artifactId>
	        </dependency>
           

各個服務的配置檔案

spring:
			  rabbitmq:
			    host: localhost
			    port: 5672
			    username: guest
			    password: guest 
			#暴露全部的監控資訊
			management:
			  endpoints:
			    web:
			      exposure:
			        include: "*"
           

通過修改git上的配置再通過手動觸發鈎子函數(post方式通路)

http://localhost:8771/actuator/bus-refresh

會重新整理服務配置(達到應用不重新開機,動态更新配置)

7.1、實戰案例

git裡面新增對應項目的配置檔案,都要添加下面的配置

#服務的名稱
	spring:
	  rabbitmq:
	    host: 192.168.8.128
	    port: 5672
	    username: guest
	    password: guest
	#暴露全部的監控資訊
	management:
	  endpoints:
	    web:
	      exposure:
	        include: "*"
           

依賴

<!--配置中心依賴-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-client</artifactId>
        </dependency>

        <!--配置中心結合消息隊列-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--Bus 消息總線的依賴-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bus-amqp</artifactId>
        </dependency>
           

修改application.properties為bootstrap.yml 并拷貝配置檔案

#指定注冊中心位址
		eureka:
		  client:
		    serviceUrl:
		      defaultZone: http://localhost:8761/eureka/
		#服務的名稱
		spring:
		  application:
		    name: order-service
		  #指定從哪個配置中心讀取
		  cloud:
		    config:
		      discovery:
		        service-id: CONFIG-SERVER
		        enabled: true
		      #指定環境
		      profile: test
           

啟動順序從①注冊中心到②配置中心到③對應的服務到④啟動網關

8、安裝Docker倉庫

阿裡雲部署Docker

1、什麼是Dokcer
		百科:一個開源的應用容器引擎,讓開發者可以打包他們的應用以及依賴包到一個可移植的容器中,然後釋出到任何流行的 Linux 機器上,也可以實作虛拟化。容器是完全使用沙箱機制,互相之間不會有任何接口;
		使用go語言編寫,在LCX(linux容器)基礎上進行的封裝
		簡單來說:
			1)就是可以快速部署啟動應用
			2)實作虛拟化,完整資源隔離
			3)一次編寫,四處運作(有一定的限制,比如Docker是基于Linux 64bit的,無法在32bit的linux/Windows/unix環境下使用)

	2、為什麼要用
		1、提供一次性的環境,假如需要安裝Mysql,則需要安裝很多依賴庫、版本等,如果使用Docker則通過鏡像就可以直接啟動運作   
		2、快速動态擴容,使用docker部署了一個應用,可以制作成鏡像,然後通過Dokcer快速啟動
		3、組建微服務架構,可以在一個機器上模拟出多個微服務,啟動多個應用
		4、更好的資源隔離和共享
		一句話:開箱即用,快速部署,可移植性強,環境隔離
           
systemctl start docker     #運作Docker守護程序
systemctl stop docker      #停止Docker守護程序
systemctl restart docker   #重新開機Docker守護程序
systemctl enable docker    #設定Docker開機自啟動
           

8.1、快速掌握Dokcer基礎知識

鏡像(Image)和容器(Container)的關系,就像是面向對象程式設計中的類和執行個體一樣,鏡像是靜态的定義,容器是鏡像運作時的實體。容器可以被建立、啟動、停止、删除、暫停等。

1、概念:
		Docker 鏡像 - Docker images:
				 容器運作時的隻讀模闆,作業系統+軟體運作環境+使用者程式
				 
				 class User{
					 private String userName;
					 private int age;
				 }
		Docker 容器 - Docker containers:
				容器包含了某個應用運作所需要的全部環境
				
				 User user = new User()
		Docker 倉庫 - Docker registeries: 
				用來儲存鏡像,有公有和私有倉庫,好比Maven的中央倉庫和本地私服
				鏡像倉庫:	
				
				(參考)配置國内鏡像倉庫:https://blog.csdn.net/zzy1078689276/article/details/77371782
		對比面向對象的方式
		Dokcer 裡面的鏡像 : Java裡面的類 Class
		Docker 裡面的容器 : Java裡面的對象 Object
		通過類建立對象,通過鏡像建立容器
4、Docker容器常見指令實戰
簡介:講解Docker在雲服務上的實際應用

	1、 常用指令(安裝部署好Dokcer後,執行的指令是docker開頭),xxx是鏡像名稱
		搜尋鏡像:docker search xxx
		
		列出目前系統存在的鏡像:docker images
		
		拉取鏡像:docker pull xxx
			xxx是具體某個鏡像名稱(格式 REPOSITORY:TAG)
			REPOSITORY:表示鏡像的倉庫源,TAG:鏡像的标簽
		運作一個容器:docker run -d --name "xdclass_mq" -p 5672:5672 -p 15672:15672 rabbitmq:management
			docker run - 運作一個容器
			-d 背景運作
			-p 端口映射
			rabbitmq:management  (格式 REPOSITORY:TAG),如果不指定tag,預設使用最新的
			--name "xxx"
		
		列舉目前運作的容器:docker ps
		檢查容器内部資訊:docker inspect 容器名稱
		删除鏡像:docker rmi IMAGE_NAME
			 強制移除鏡像不管是否有容器使用該鏡像 增加 -f 參數,
		停止某個容器:docker stop 容器名稱
		啟動某個容器:docker start 容器名稱
		移除某個容器: docker rm 容器名稱 (容器必須是停止狀态)
           

9、SpringCloud和Docker整合部署

9.1、建構springboot應用

添加配置pom.xml

<properties>
        <!--變量字首-->
        <docker.image.prefix>yuange</docker.image.prefix>
    </properties>
    <build>
        <!--項目打包的名稱-->
        <finalName>docker-demo</finalName>
        <plugins>
            <!--一個插件,用于打包springboot應用成docker鏡像-->
            <plugin>
                <groupId>com.spotify</groupId>
                <artifactId>dockerfile-maven-plugin</artifactId>
                <version>1.3.6</version>
                <configuration>
                    <!--指定打包成的鏡像名稱-->
                    <repository>${docker.image.prefix}/${project.artifactId}</repository>
                    <buildArgs>
                        <JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
                    </buildArgs>
                </configuration>
            </plugin>
        </plugins>
    </build>


配置講解
	Spotify 的 docker-maven-plugin 插件是用maven插件方式建構docker鏡像的。
	${project.build.finalName} 産出物名稱,預設為${project.artifactId}-${project.version}
           

9.2、打包SpringCloud鏡像并上傳私有倉庫并部署

建立Dockerfile

FROM java:8
VOLUME /tmp
COPY *.jar app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
           

建構鏡像(window的操作)

1.将springboot項目打成jar包

2.建立一個Dockerfile檔案

3.将jar包和Dockerfile檔案放到同一目錄中

4.打成鏡像(結尾有個點):

docker build -t docker-demo .

5.運作鏡像

docker run -d -p 8080:8080 docker-demo

建構鏡像(linux的操作)

mvn install dockerfile:build

10、其他

10.1、阿裡雲依賴

<repositories>
        <repository>
            <id>nexus-aliyun</id>
            <name>Nexus aliyun</name>
            <layout>default</layout>
            <url>http://maven.aliyun.com/nexus/content/groups/public</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
            <releases>
                <enabled>true</enabled>
            </releases>
        </repository>
    </repositories>
           

10.2、虛拟機環境開啟

安裝docker

打開docker

systemctl start docker
           

安裝打開docker的rabbitmq

docker pull rabbitmq:management
docker run -d --name="myrabbitmq" -p 5671:5671 -p 15672:15672 rabbitmq:management
           

安裝打開docker的zipkin

docker pull openzipkin/zipkin
docker run -d -p 9411:9411 openzipkin/zipkin
           

安裝打開docker的nginx

docker pull nginx:latest
docker run --name nginx-test -p 8080:80 -d nginx
           

安裝打開docker的MySQL(MYSQL_ROOT_PASSWORD=123456:設定 MySQL 服務 root 使用者的密碼。)

docker pull mysql:latest
docker run -itd --name mysql-test -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql
進入容器
docker exec -it 62349aa31687 /bin/bash
           

安裝打開docker的redis(接着我們通過 redis-cli 連接配接測試使用 redis 服務)

指令說明:

redis-server --appendonly yes : 在容器執行redis-server啟動指令,并打開redis持久化配置

docker pull redis:latest
docker run -d --name "yuange" -p 6379:6379 redis
docker run -itd --name redis-test -p 6379:6379 redis
通路redis容器裡面,進行操作
docker exec -it 295058d2b92e redis-cli
#常用啟動方式
docker run -d --name "yuange" -p 6379:6379 redis redis-server --appendonly yes
           

安裝打開docker的Jenkins

-d 背景運作鏡像

-p 10240:8080 将鏡像的8080端口映射到伺服器的10240端口。

-p 10241:50000 将鏡像的50000端口映射到伺服器的10241端口

-v /var/jenkins_mount:/var/jenkins_mount /var/jenkins_home目錄為容器jenkins工作目錄,我們将硬碟上的一個目錄挂載到這個位置,友善後續更新鏡像後繼續使用原來的工作目錄。這裡我們設定的就是上面我們建立的 /var/jenkins_mount目錄

-v /etc/localtime:/etc/localtime讓容器使用和伺服器同樣的時間設定。

–name myjenkins 給容器起一個别名

docker pull jenkins/jenkins
mkdir -p /var/jenkins_mount
chmod 777 /var/jenkins_mount
運作
docker run -d -p 10240:8080 -p 10241:50000 -v /var/jenkins_mount:/var/jenkins_home -v /etc/localtime:/etc/localtime --name myjenkins jenkins/jenkins
           

docker常用指令

docker ps [OPTIONS]
-a :顯示所有的容器,包括未運作的。

docker start :啟動一個或多個已經被停止的容器
docker stop :停止一個運作中的容器
docker restart :重新開機容器

強制删除容器 db01、db02:
docker rm -f db01 db02

删除所有已經停止的容器:
docker rm $(docker ps -a -q)

使用鏡像nginx:latest以背景模式啟動一個容器,并将容器的latest端口映射到主機的nginx端口。
docker run -P -d nginx:latest
           

10.3、生産環境部署常見問題,配置中心通路路徑變化

#指定注冊中心位址
eureka:
  client:
    serviceUrl:
      #一般注冊中心和配置中心不會在同一台伺服器,而且不會對外公布,使用内網ip
      defaultZone: http://localhost:8761/eureka/
  instance:
  instance-id: ${spring.cloud.client.ip-address}:${server.port}
  prefer-ip-address: true
           

繼續閱讀