spring cloud 微服務
服務註冊 ( Eureka )
服務端:
需要jar
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
spring cloud 啓動文件上配置
@EnableEurekaServer
application.yml 配置
server:
port: 8786
eureka:
instance:
hostname: localhost
client:
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
spring:
application:
name: eurka-server
客戶端:
需要jar:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
spring boot啓動文件:
@EnableEurekaClient
application.yml配置:
server:
port: 8762
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8786/eureka/ //對應服務端的defaultZone
spring:
application:
name: eurka-client
此時,8082端口的應用就被註冊到了8081服務註冊中心。就可以通過http://localhost:8081查看服務註冊情況
負載均衡(ribbon)
需要jar
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
application.yml配置:
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8786/eureka/ //對應服務端的defaultZone
server:
port: 8764
spring:
application:
name: service-ribbon
spring boot啓動文件 :
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
public class ServiceRibbonApplication {
public static void main(String[] args) {
SpringApplication.run( ServiceRibbonApplication.class, args );
}
@Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
}
}
測試類:
@Service
public class HelloService {
@Autowired
RestTemplate restTemplate;
public String hiService(String name) {
return restTemplate.getForObject("http://SERVICE-HI/hi?name="+name,String.class);
}
}
斷路器(Hystrix)
需要jar:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
在原來的 8764 服務的啓動類上加:
@EnableHystrix
修改其測試類:
@Service
public class HelloService {
@Autowired
RestTemplate restTemplate;
@HystrixCommand(fallbackMethod = "hiError")
public String hiService(String name) {
return restTemplate.getForObject("http://SERVICE-HI/hi?name="+name,String.class);
}
public String hiError(String name) {
return "hi,"+name+",sorry,error!";
}
}
路由(Zuul)
需要jar:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
application.yml配置:
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
server:
port: 8769
spring:
application:
name: service-zuul
zuul:
routes:
api-a:
path: /api-a/**
serviceId: service-ribbon
api-b:
path: /api-b/**
serviceId: service-feign
啓動類:
@SpringBootApplication
@EnableZuulProxy
@EnableEurekaClient
@EnableDiscoveryClient
public class ServiceZuulApplication {
public static void main(String[] args) {
SpringApplication.run( ServiceZuulApplication.class, args );
}
}
依次運行打開瀏覽器訪問:http://localhost:8769/api-a/hi?name=forezp ;
zuul還可以進行路由過濾:
@Component
public class MyFilter extends ZuulFilter {
private static Logger log = LoggerFactory.getLogger(MyFilter.class);
@Override
public String filterType() {
return "pre";
}
@Override
public int filterOrder() {
return 0;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
log.info(String.format("%s >>> %s", request.getMethod(), request.getRequestURL().toString()));
Object accessToken = request.getParameter("token");
if(accessToken == null) {
log.warn("token is empty");
ctx.setSendZuulResponse(false);
ctx.setResponseStatusCode(401);
try {
ctx.getResponse().getWriter().write("token is empty");
}catch (Exception e){}
return null;
}
log.info("ok");
return null;
}
}
filterType:返回一個字符串代表過濾器的類型,在zuul中定義了四種不同生命週期的過濾器類型,具體如下:
pre:路由之前
routing:路由之時
post: 路由之後
error:發送錯誤調用
filterOrder:過濾的順序
shouldFilter:這裏可以寫邏輯判斷,是否要過濾,本文true,永遠過濾。
run:過濾器的具體邏輯。可用很複雜,包括查sql,nosql去判斷該請求到底有沒有權限訪問。
配置中心()
服務端:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
application.yml配置:
spring:
cloud:
config:
server:
git:
password: //遠程git的密碼
searchPaths: respo //配置倉庫路徑
uri: https://github.com/forezp/SpringcloudConfig/ //遠程git的地址
username: //遠程git的用戶名
label: master //配置倉庫的分支
application:
name: config-server
server:
port: 8888
springboot的啓動類配置:@EnableConfigServer
http請求地址和資源文件映射如下:
/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
根據我們自己的配置,我們可以這樣訪問:http://127.0.0.1:8888/eureka-server/default/master
application -> eureka-server (應用名)
profile -> default (啓用的配置,通常是後綴,下面解釋)
label -> master (分支)
profile比較重要,可以理解成讀取哪些配置文件,假如我不止一個配置文件,可能會有:
eureka-server.properties(這個是通用配置文件,默認都會加載),
eureka-server-mysql.properties,
eureka-server-oracle.properties,
eureka-server-jpa.properties,
eureka-server-mysql.properties......
我們可能會選擇性的加載其中的部分properties配置文件,那我們可以這樣寫:http://127.0.0.1:8888/eureka-server/default,mysql,jpa/master
客戶端:<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
application.yml配置:
spring:
cloud:
config:
profile: dev
label: master
uri: http://localhost:8888/
application:
name: config-client
server:
port: 8881
springboot啓動類:
@SpringBootApplication
@RestController
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Value("${foo}")
String foo; //對應配置文件中的key
@RequestMapping(value = "/hi")
public String hi(){
return foo;
}
}
同時客戶端的項目名必須和git的配置文件保持一致否則找不到,如果客戶端項目名是config-client 對應git配置文件是config-client-*.*的形式
可以把服務端和客戶端都註冊到註冊中心,配置方法如上配置中心,配置的客戶端就可以通過
spring.cloud.config.discovery.enabled=true
spring.cloud.config.discovery.serviceId=config-server
來代替spring.cloud.config.uri= http://localhost:8888/ 執行配置服務器
消息總線