【springcloud】springcloud Greenwich SR4版本筆記


springcloud Greenwich SR4版本筆記

  本文只記錄實際版本,配置,pom,代碼以及注意事項。別的在其他springcloud 的F版本中已有詳述。

  示例代碼地址:https://github.com/wjqhuaxia/springcloud-greenwich-sr4.git

目錄:

  1、 eureka server

  2、feign調用

  3、網關zuul

    3.1、過濾器實現權限校驗

    3.2、智能路由

    3.3、跨域處理

  4、hystrix服務降級、熔斷、限流

    4.1、feign-hystrix服務降級

    4.2、zuul-hystrix服務降級

    4.3、hystrix服務熔斷

  5、ribbon客戶端負載勻衡

  6、config

    6.1、config server

    6.2、config client

 

1. eureka server

  詳細描述請查看另一文章。路徑【springcloud】Eureka服務注冊中心搭建

1.1 版本選擇

jdk:    1.8
springcloud:    Greenwich.SR4
springboot:    2.1.9.RELEASE

1.2 pom

1.2.1 項目父pom

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.9.RELEASE</version>
  </parent>
   
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
  </properties>
   
  <dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Greenwich.SR4</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
  </dependencyManagement>
  
  <dependencies>
  	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-netflix-eureka-client</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
	</dependency>
  </dependencies>
   
    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/libs-milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>  

1.2.2 eureka server pom

<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-security</artifactId>
  	</dependency>
</dependencies>

1.3 配置

1.3.1 單節點配置

application.yml中配置如下:

server:
  port: 8761
eureka:
  instance:
    hostname: localhost
  client:
    registerWithEureka: false
    fetchRegistry: false
    serviceUrl:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

1.4 代碼

eureka server 中起動類代類如下:

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

1.5 安全校驗

1.5.1 pom增加項

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

1.5.2 eureka server

配置修改如下

server:
  port: 8761
  
user: huaxia
password: huaxia 
  
spring:
  security:
    user:
      name: ${user}
      password: ${password}
  
eureka:
  instance:
    hostname: localhost
  client:
    registerWithEureka: false
    fetchRegistry: false
    serviceUrl:
      defaultZone: http://${user}:${password}@{eureka.instance.hostname}:${server.port}/eureka/

1.5.3 eureka client 

配置時修改如下

eureka:
  client:
    service-url:
      defaultZone:http://${user}:${password}@{eureka.instance.hostname}:${server.port}/eureka/

1.5.4 注意項

  A、由於默認是開啟CSRF,所以需要將其關閉,不然會出現如下錯誤:

javax.ws.rs.WebApplicationException: com.fasterxml.jackson.databind.exc.MismatchedInputException: 
Root name 'timestamp' does not match expected ('instance') for type [simple type, class com.netflix.appinfo.InstanceInfo]

  在eureka服務端,創建一個WebSecurityConfig類,代碼如下:

// WebSecurityConfig.java
 
@EnableWebSecurity
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable(); //關閉csrf
        super.configure(http); //開啟認證
    }
}
 

  B、spring-boot-starter-security包只能放在eureka server項目的pom中,如果放在其他服務的pom中,在調用接口時會報401,Unauthorized

 

 

1.5.5 總結

  1、如果在eureka服務端增加上安全認證,客戶端無法注冊成功,先看看有沒有WebSecurityConfig。

  2、客戶端也需要用戶名和密碼認證注冊的,服務端改成安全認證,客戶端不要忘了改。

  3、如果服務端是安全認證的集群服務,客戶端注冊時每個地址都需要用戶名和密碼安全認證

  

安全配置參考:https://blog.csdn.net/wgh100817/article/details/101719042

 

2、feign調用

  詳細請查看另一文章:【springcloud】模擬RPC調用(Feign)

2.1 pom文件修改

添加feign依賴

<!-- Feign 依賴 -->
     <dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-starter-openfeign</artifactId>
     </dependency>

2.2 feign代碼實現

2.2.1 feign接口

@FeignClient(name = "stock-service", fallback = StockMsgClientFallback.class)
public interface StockMsgClient {

	@GetMapping("/stock/getStockMsg")
	public String getStockMsg();
}

2.2.2 feign接口調用

@RestController
public class HelloOrderController {
	
	@Autowired
	private StockMsgClient stockMsgClient;
	@Autowired
	private IntegralMsgClient integralMsgClient;
	
	@GetMapping("/testStockRequest")
	@ResponseBody
	public String testStockRequest(){
		return "order service: " + stockMsgClient.getStockMsg();
	}
	
	@GetMapping("/testIntegralRequest")
	@ResponseBody
	public String testIntegralRequest(){
		return "order service: " + integralMsgClient.getIntegralMsg();
	}
	
	@RequestMapping(value = "/hello")
	@ResponseBody
	public String hello(){
		return "Hello Order Controller!";
	}
}

2.3 feign-hystrix服務降級

2.3.1 feignclient調用

 

 

 2.3.2 fallback實現

@Component
public class StockMsgClientFallback implements StockMsgClient{

	@Override
	public String getStockMsg() {
		return "getStockMsg 服務異常,請稍后再試!";
	}

}

3、網關zuul

  zuul相關詳細描述請移步:

    【springcloud】API Gateway 的路由和過濾(Zuul--1) 

    【springcloud】Zuul高級配置(zuul--2) 

    【springcloud】Zuul高級配置(zuul--3) 

3.1 pom配置

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

  

3.2 智能路由實現

配置即可

zuul:
  prefix: /api  #zuul.prefix 配置項可以為所有的路由地址都添加一個前綴
  routes:
    order-service: /order-service/**
    stock-service: /stock-service/**

3.3 zuul-hystrix服務降級  

訂單服務-服務降級處理

@Component
public class OrderServiceFallbackProvider implements FallbackProvider {
  
    @Override
    public String getRoute() {
        return "order-service";
    }
  
    @Override
    public ClientHttpResponse fallbackResponse(String route, final Throwable cause) {
        if (cause instanceof HystrixTimeoutException) {
            return response(HttpStatus.GATEWAY_TIMEOUT);
        } else {
            return response(HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }
  
    private ClientHttpResponse response(final HttpStatus status) {
        return new ClientHttpResponse() {
            @Override
            public HttpStatus getStatusCode() throws IOException {
                return status;
            }
  
            @Override
            public int getRawStatusCode() throws IOException {
                return status.value();
            }
  
            @Override
            public String getStatusText() throws IOException {
                return status.getReasonPhrase();
            }
  
            @Override
            public void close() {
            }
  
            @Override
            public InputStream getBody() throws IOException {
                return new ByteArrayInputStream("訂單服務暫時不可用,請稍后重試!".getBytes());
            }
  
            @Override
            public HttpHeaders getHeaders() {
                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.APPLICATION_JSON);
                return headers;
            }
        };
    }
}

3.4 過濾器實現權限校驗

本示例中使用的是spring security安全框架實現安全管理。spring security的springboot集成可參考:springboot集成security

具體代碼已上傳github。以下記錄簡略步驟:

3.4.1 pom修改

       <!-- security依賴 -->
       <dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-security</artifactId>
	</dependency>

3.4.2 配置項 

package cn.com.wjqhuaxia.config;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

import cn.com.wjqhuaxia.service.impl.UserServiceImpl;
/**
 * spring-security權限管理的核心配置
 * @author wjqhuaxia
 *
 */
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true) //全局
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
	
	private final Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private UserServiceImpl userService;//實現了UserDetailsService接口
    @Autowired
    private MyFilterInvocationSecurityMetadataSource myFilterInvocationSecurityMetadataSource;//權限過濾器(當前url所需要的訪問權限)
    @Autowired
    private MyAccessDecisionManager myAccessDecisionManager;//權限決策器
    @Autowired
    private AuthenticationAccessDeniedHandler authenticationAccessDeniedHandler;//自定義錯誤(403)返回數據

    /**
     * 自定義的加密算法
     * @return
     */
    @Bean
    public PasswordEncoder myPasswordEncoder() {
    	return new MyPasswordEncoder(); 
    }
    /**
     *  配置userDetails的數據源,密碼加密格式
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService).passwordEncoder(myPasswordEncoder());
    }
    /**
     * 配置放行的資源
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring()
           .antMatchers("/index.html", "/static/**","/loginPage","/register")
           // 給 swagger 放行;不需要權限能訪問的資源
           .antMatchers("/swagger-ui.html", "/swagger-resources/**", "/images/**", "/webjars/**", "/v2/api-docs",
        		   "/configuration/ui", "/configuration/security", "/swagger-ui.html#!");
    }
    
    /**
     * 這段配置,我認為就是配置Security的認證策略, 每個模塊配置使用and結尾。
		authorizeRequests()配置路徑攔截,表明路徑訪問所對應的權限,角色,認證信息。
		formLogin()對應表單認證相關的配置
		logout()對應了注銷相關的配置
		httpBasic()可以配置basic登錄
     */
    /**
     * HttpSecurity包含了原數據(主要是url)
     * 1.通過withObjectPostProcessor將MyFilterInvocationSecurityMetadataSource和MyAccessDecisionManager注入進來
     * 2.此url先被MyFilterInvocationSecurityMetadataSource處理,然后 丟給 MyAccessDecisionManager處理
     * 3.如果不匹配,返回 MyAccessDeniedHandler
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
    		// authorizeRequests()配置路徑攔截,表明路徑訪問所對應的權限,角色,認證信息
        	http.authorizeRequests()
                .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
                    @Override
                    public <O extends FilterSecurityInterceptor> O postProcess(O o) {
                        o.setSecurityMetadataSource(myFilterInvocationSecurityMetadataSource);
                        o.setAccessDecisionManager(myAccessDecisionManager);
                        return o;
                    }
                })
                .and()
            // formLogin()對應表單認證相關的配置
            .formLogin()
            	//.loginPage("/loginPage.html")
            	.loginProcessingUrl("/login")
            	.usernameParameter("username")
            	.passwordParameter("password")
            	.permitAll()
            .failureHandler(new AuthenticationFailureHandler() {
	            @Override
	            public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
	            	logger.error("onAuthenticationFailure error. e: {}", e);
	            	httpServletResponse.setContentType("application/json;charset=utf-8");
	                PrintWriter out = httpServletResponse.getWriter();
	                StringBuffer sb = new StringBuffer();
	                sb.append("{\"status\":\"error\",\"msg\":\"");
	                if (e instanceof UsernameNotFoundException || e instanceof BadCredentialsException) {
	                    sb.append("用戶名或密碼輸入錯誤,登錄失敗!");
	                } else {
	                    sb.append("登錄失敗!");
	                }
	                sb.append("\"}");
	                out.write(sb.toString());
	                out.flush();
	                out.close();
	            }
            }).successHandler(new AuthenticationSuccessHandler() {
            @Override
	            public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
	                httpServletResponse.setContentType("application/json;charset=utf-8");
	                PrintWriter out = httpServletResponse.getWriter();
	                String s = "{\"status\":\"success\",\"msg\":\"登陸成功\"}";
	                out.write(s);
	                out.flush();
	                out.close();
	            }
            }).and()
            // logout()對應了注銷相關的配置
            .logout()
            	.permitAll()
            	.and()
            	.csrf()
            	.disable()
        	.exceptionHandling()
        		.accessDeniedHandler(authenticationAccessDeniedHandler);
    }
}

3.4.3 權限數據源信息

詳細信息見github代碼以及springboot集成security,此處僅做簡略記錄。

4、springcloud config

4.1 config server

4.1.1 pom

  添加 spring-cloud-config-server 依賴。

  <parent>
    <groupId>cn.com.wjqhuaxia</groupId>
    <artifactId>greenwich-sr4-master</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <artifactId>greenwich-sr4-config</artifactId>
  
  <dependencies>
  	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-config-server</artifactId>
	</dependency>
  </dependencies>

4.1.2 啟動類

  添加 @EnableConfigServer 注解。

package cn.com.wjqhuaxia;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
  
@SpringBootApplication
@EnableConfigServer
@EnableEurekaClient
public class ConfigServerApplication {
  
    public static void main(String[] args) {
    	SpringApplication.run(ConfigServerApplication.class, args);
    }
}

4.1.3 配置項

  application.yml,其中uri為git遠程庫地址。

spring:
  application:
    name: config-center
  cloud:
    config:
      server:
        git:
          uri: https://github.com/wjqhuaxia/config.git
          username: xx
          password: xx

server:
  port: 8000  # 端口號默認8080
# 服務注冊 
eureka:
  client:
    serviceUrl:
      defaultZone: http://huaxia:huaxia@localhost:8761/eureka/

4.2 config client

示例代碼中order項目,修改application.yml文件,並添加bootstrap.yml文件

  

 

4.2.1 pom

  添加config-client依賴

        <dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-config-client</artifactId>
	</dependency>

4.2.2 配置文件內容

spring:
  application:
    name: order-service
  cloud:
    config:
      discovery:
        enabled: true
        service-id: config-center  # 指定用於獲取配置的配置中心服務(應用)名稱
      profile: test
      label: master
eureka:
  client:
    serviceUrl:
      defaultZone: http://huaxia:huaxia@localhost:8761/eureka/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM