Analyze the pain points you’re dealing with
In your development work, have you encountered the problem that the microservices module is too finely divided and the base module is too dependent? For example, if you want to do microservice development, you need to start the following basic modules
- Note Centre (Eureka)
- Configuration Center (Spring Cloud Config)
- Gateway (ZUul)
- Certification Center (OAUTH)
- .
As shown above, the service module is highlighted in red, while youAll you need to code or need is one business microservice moduleLocal startup of such microservice modules requires high performance for the development machine and affects the development efficiency.
In order to solve this problem, the team usually putsCommon base module sectionTo provide a unified development environment for everyone to develop. As shown in the figure above, you only need to consider your business modules (serviceA and serviceB) to improve development efficiency.
There are minor issues with this unified development infrastructure. For example, when development A maintains serviceA, development B maintains serviceB, there is no conflict. If development A and B maintain A module at the same time, there will be conflicts as shown in the figure below:A’s local request is routed to the biz-service B is developing instead of the target A’s biz-serviceZuul is routed by a service name
To solve the principle
Rewrite the forwarding rules of the gateway. In fact, rewrite the routing rules of the ribbon. Route the ribbon to the corresponding micro services based on different user requests (which can be distinguished by input parameters). Biz -service A development version, biz-service B development version
Code implementation
- Declare version ownership in the Eureka client of the microservice
Eureka: instance: metadata-map: version: v1.0The development version of # A
Copy the code
- Custom Ribbon assertions
/** * @author lengleng * @date 2018/10/16 * <p> * 1. No metadata is returnedtrue
*/
@Slf4j
public class MetadataCanaryRuleHandler extends ZoneAvoidanceRule {
@Override
public AbstractServerPredicate getPredicate() {
return new AbstractServerPredicate() {
@Override
public boolean apply(PredicateKey predicateKey) {
String targetVersion = RibbonVersionHolder.getContext();
RibbonVersionHolder.clearContext();
if (StrUtil.isBlank(targetVersion)) {
log.debug("Client is not configured with target version direct routing");
return true;
}
DiscoveryEnabledServer server = (DiscoveryEnabledServer) predicateKey.getServer();
final Map<String, String> metadata = server.getInstanceInfo().getMetadata();
if (StrUtil.isBlank(metadata.get(SecurityConstants.VERSION))) {
log.debug("Current microservice {} not configured with version Direct routing");
return true;
}
if (metadata.get(SecurityConstants.VERSION).equals(targetVersion)) {
return true;
} else {
log.debug("Current microservice {} version is {}, target version {} failed to match", server.getInstanceInfo().getAppName()
, metadata.get(SecurityConstants.VERSION), targetVersion);
return false; }}}; }}Copy the code
- Version context TTL
public class RibbonVersionHolder {
private static final ThreadLocal<String> context = new TransmittableThreadLocal<>();
public static String getContext() {
return context.get();
}
public static void setContext(String value) {
context.set(value);
}
public static void clearContext() { context.remove(); }}Copy the code
- Initialize the ribbon routing configuration
@Configuration
@ConditionalOnClass(DiscoveryEnabledNIWSServerList.class)
@AutoConfigureBefore(RibbonClientConfiguration.class)
@ConditionalOnProperty(value = "zuul.ribbon.metadata.enabled")
public class RibbonMetaFilterAutoConfiguration {
@Bean
@ConditionalOnMissingBean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public ZoneAvoidanceRule metadataAwareRule() {
returnnew MetadataCanaryRuleHandler(); }}Copy the code
- The header is passed in when the client calls it, as in axios
axios.interceptors.request.use(config => {
NProgress.start() // start progress bar
if (store.getters.access_token) {
config.headers['Authorization'] = 'Bearer ' + token
config.headers['version'] = 'v1.0'// Developer's own version flag, corresponding to eureka metadata configuration}return config
}
Copy the code
conclusion
-
Extending the ribbon’s routing rules allows you to access different versions of services based on the client, which can be interpreted as grayscale publishing.
-
Production environment can use Kong, Traefik zuul to achieve grayscale publishing
-
The code please refer to the grayscale publishing function of pig, which has been all open source
-
About PIG: Based on Spring Cloud, oAuth2.0 development platform based on Vue before and after separation, support account, SMS, SSO and other logins, provide supporting video development tutorials. gitee.com/log4j/pig