1. 程式人生 > 實用技巧 >【Azure DevOps系列】Azure DevOps使用Docker將.NET應用程式部署在雲伺服器

【Azure DevOps系列】Azure DevOps使用Docker將.NET應用程式部署在雲伺服器

SpringCloud

1.概念

Spring Cloud是一系列框架的有序集合。它利用Spring Boot的開發便利性巧妙地簡化了分散式系統基礎設施的開發,如服務發現註冊配置中心訊息匯流排負載均衡斷路器資料監控等,都可以用Spring Boot的開發風格做到一鍵啟動和部署。Spring並沒有重複製造輪子,它只是將目前各家公司開發的比較成熟、經得起實際考驗的服務框架組合起來,通過Spring Boot風格進行再封裝遮蔽掉了複雜的配置和實現原理,最終給開發者留出了一套簡單易懂、易部署和易維護的分散式系統開發工具包

“微服務架構”在這幾年非常的火熱,以至於關於微服務架構相關的開源產品被反覆的提及(比如:netflix、dubbo),Spring Cloud也因Spring社群的強大知名度和影響力也被廣大架構師與開發者備受關注。

那麼什麼是“微服務架構”呢?簡單的說,微服務架構就是將一個完整的應用從資料儲存開始垂直拆分成多個不同的服務,每個服務都能獨立部署、獨立維護、獨立擴充套件,服務與服務間通過諸如RESTful API的方式互相呼叫。

eureka

建立註冊中心服務

建立SpringBoot工程引入eureka-server

編寫配置application.yml

spring:
  application:
    name: cloud-eureka-registry-center
 
server:
  port: 8761

eureka:
  instance:
    hostname: localhost
  client:
    register-with-eureka: false #自己就是註冊中心,不用註冊自己
    fetch-registry: false #要不要去註冊中心獲取其他服務的地址
    service-url:
       defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

在啟動類上開啟Eureka註冊中心功能;@EnableEurekaServer

訪問http://localhost:8761

建立電影服務

建立springBoot工程引入eureka-Discovery

編寫配置類

spring:
  application:
    name: cloud-provider-movie
    
server:
  port: 8000  
  
# 指定註冊到哪個註冊中心
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true #註冊自己服務使用ip的方式

在啟動程式上將自己自動註冊到註冊中心@EnableDiscoveryClient

新增Controller層,MovieDao. MovieService

檢視註冊中心,訪問服務 http://localhost:8000

建立跟電影服務一樣的 -- 使用者服務

新增UserDao UserService UserController

配置檔案application.yml

spring:
  application:
    name: cloud-consumer-user
    
server:
  port: 9000
  
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true #註冊中心儲存我的ip

Ribbon負載均衡

如何使用Ribbon

1)、引入Ribbon的Starter

2)、配置使用Ribbon功能;底層使用 RestTemplate 的工具來給遠端傳送請求

使用者模組中引入Ribbon

<!-- 引入ribbon實現遠端呼叫和負載均衡功能 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>

給容器注入一個RestTemplate並使用Ribbon進行負載均衡呼叫

@LoadBalanced   //負載均衡
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}

使用RestTemplate 遠端呼叫(UserService)

@Autowired
RestTemplate restTemplate;
/**
 * 購買最新的電影票
 * 傳入使用者id
 */
public Map<String, Object> buyMovie(Integer id){
Map<String, Object>  result = new HashMap<>();
//1、查詢使用者資訊
User user = getUserById(id);
//2、查到最新電影票  restTemplate使用java程式碼來模擬發請求
Movie movie = restTemplate.getForObject("http://CLOUD-PROVIDER-MOVIE/movie", Movie.class);
 
result.put("user", user);
result.put("movie", movie);
return result;
}

Feign - 宣告式呼叫

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

在啟動類中開啟@EnableDiscoveryClient服務發現

開啟Feign功能@EnableFeignClients

/**
 * 1、引入feign的starter
 * 2、寫一個介面,和被呼叫的服務關聯起來
 * 3、開啟Feign功能;@EnableFeignClients
 */
@EnableFeignClients
@EnableDiscoveryClient 
@SpringBootApplication
public class CloudConsumerUserFeignApplication {
	public static void main(String[] args) {
		SpringApplication.run(CloudConsumerUserFeignApplication.class, args);
	}
}

將RestTemplate方式改成Feign方式進行呼叫

/**
 * 呼叫指定服務名稱 “CLOUD-PROVIDER-MOVIE” 的 @GetMapping("/movie") 對映方法
 * 這個方法宣告與電影服務端Controller對映的方法宣告一致即可。
 */
@FeignClient(value="CLOUD-PROVIDER-MOVIE") //與被呼叫端的服務名稱一致
public interface MovieServiceFeign { 
		@GetMapping("/movie")
		public Movie getNewMovie(); //與被呼叫服務端的對映方法一致 
}

Ribbon + Hystrix

引入Hystrix

引入Hystrix
<!--  引入hystrix進行服務熔斷 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

在RestTemplate中寫@HystrixCommand(fallbackMethod="xxx")來指定出錯時呼叫xx方法

@HystrixCommand(fallbackMethod="hystrix")
public Map<String, Object> buyMovie(Integer id){
Map<String, Object>  result = new HashMap<>();
//1、查詢使用者資訊
User userById = getUserById(id);
//2、查到最新電影票  restTemplate使用java程式碼來模擬發請求
Movie movie = restTemplate.getForObject("http://CLOUD-PROVIDER-MOVIE/movie", Movie.class);
 
result.put("user", userById);
result.put("movie", movie);
return result;
}


在同一個類中編寫

public Map<String, Object> hystrix(Integer id){
User user = new User();
user.setId(-1);
user.setUserName("未知使用者");
 
Movie movie = new Movie();
movie.setId(-100);
movie.setMovieName("無此電影");
 
Map<String, Object>  result = new HashMap<>();
result.put("user", user);
result.put("movie", movie);
return result;
}

Feign + Hystrix 組合

在配置中開啟Feign對Hystrix的支援

feign:
  hystrix:
    enabled: true #預設false

/*使用Hystrix進行服務的熔斷
 * 1)、引入Hystrix的starter
 * 2)、開啟xxx功能 :@EnableCircuitBreaker
 * 3)、@FeignClient(value="CLOUD-PROVIDER-MOVIE",fallback=指定這個介面的異常處理類(異常處理類必須實現這個介面))
 */
@FeignClient(value="CLOUD-PROVIDER-MOVIE",fallback=MovieFeignExceptionHandlerService.class)
public interface MovieServiceFeign {
	//  未來這個介面就會呼叫很多方法,定製每一個方法遠端出錯如何返回兜底mock資料;
	@GetMapping("/movie")
	public Movie getNewMovie();
}

fallback="異常處理類"指定的異常處理類實現這個類的介面即可,並且放在容器中

@Component
public class MovieFeignExceptionHandlerService implements MovieServiceFeign{
 
/**
 * 遠端這個方法調用出問題就會呼叫此方法
 */
@Override
public Movie getNewMovie() {
Movie movie = new Movie();
movie.setId(-100);
movie.setMovieName("無此電影呀...");
return movie;
}
}